diff --git a/.gitignore b/.gitignore index d0736707b80..b57addfccc9 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ NashornProfile.txt /.settings/ /compile_commands.json /.cache +/.gdbinit +/.lldbinit diff --git a/make/Global.gmk b/make/Global.gmk index 16a5b05cccb..3e6721f994c 100644 --- a/make/Global.gmk +++ b/make/Global.gmk @@ -102,7 +102,7 @@ help: $(info $(_) # method is 'auto', 'ignore' or 'fail' (default)) $(info $(_) TEST="test1 ..." # Use the given test descriptor(s) for testing, e.g.) $(info $(_) # make test TEST="jdk_lang gtest:all") - $(info $(_) TEST_DEPS="dependency1 ..." # Specify additional dependencies for running tests, e.g docs-jdk + $(info $(_) TEST_DEPS="dependency1 ..." # Specify additional dependencies for running tests, e.g docs-jdk) $(info $(_) JTREG="OPT1=x;OPT2=y" # Control the JTREG test harness, use 'make test-only JTREG=help' to list) $(info $(_) GTEST="OPT1=x;OPT2=y" # Control the GTEST test harness, use 'make test-only GTEST=help' to list) $(info $(_) MICRO="OPT1=x;OPT2=y" # Control the MICRO test harness, use 'make test-only MICRO=help' to list) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 747d8f84dbc..636d1ed18b2 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -45,7 +45,7 @@ ifneq ($(TEST_VM_OPTS), ) endif $(eval $(call ParseKeywordVariable, TEST_OPTS, \ - SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR JCOV JCOV_DIFF_CHANGESET, \ + SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR JCOV JCOV_DIFF_CHANGESET AOT_JDK, \ STRING_KEYWORDS := VM_OPTIONS JAVA_OPTIONS, \ )) @@ -202,11 +202,12 @@ $(eval $(call SetTestOpt,JOBS,JTREG)) $(eval $(call SetTestOpt,TIMEOUT_FACTOR,JTREG)) $(eval $(call SetTestOpt,FAILURE_HANDLER_TIMEOUT,JTREG)) $(eval $(call SetTestOpt,REPORT,JTREG)) +$(eval $(call SetTestOpt,AOT_JDK,JTREG)) $(eval $(call ParseKeywordVariable, JTREG, \ SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR FAILURE_HANDLER_TIMEOUT \ TEST_MODE ASSERT VERBOSE RETAIN TEST_THREAD_FACTORY MAX_MEM RUN_PROBLEM_LISTS \ - RETRY_COUNT REPEAT_COUNT MAX_OUTPUT REPORT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ + RETRY_COUNT REPEAT_COUNT MAX_OUTPUT REPORT AOT_JDK $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \ EXTRA_PROBLEM_LISTS LAUNCHER_OPTIONS \ $(CUSTOM_JTREG_STRING_KEYWORDS), \ @@ -702,6 +703,58 @@ define SetJtregValue endif endef + +# Parameter 1 is the name of the rule. +# +# Remaining parameters are named arguments. +# VM_OPTIONS List of JVM arguments to use when creating AOT cache +# +# After calling this, the following variables are defined +# $1_AOT_TARGETS List of all targets that the test rule will need to depend on +# $1_AOT_JDK_CACHE The AOT cache file to be used to run the test with +# +SetupAot = $(NamedParamsMacroTemplate) +define SetupAotBody + $1_AOT_JDK_CONF := $$($1_TEST_SUPPORT_DIR)/aot/jdk.aotconf + $1_AOT_JDK_CACHE := $$($1_TEST_SUPPORT_DIR)/aot/jdk.aotcache + + $1_JAVA_TOOL_OPTS := $$(addprefix -J, $$($1_VM_OPTIONS)) + + $$($1_AOT_JDK_CACHE): $$(JDK_IMAGE_DIR)/release + $$(call MakeDir, $$($1_TEST_SUPPORT_DIR)/aot) + + $(foreach jtool, javac javap jlink jar, \ + $(info AOT: Create cache configuration for $(jtool)) \ + $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/aot.$(jtool), ( \ + $$(FIXPATH) $(JDK_UNDER_TEST)/bin/$(jtool) $$($1_JAVA_TOOL_OPTS) \ + -J-XX:AOTMode=record -J-XX:AOTConfiguration=$$($1_AOT_JDK_CONF).$(jtool) --help \ + )) + ) + + $$(info AOT: Copy $(JDK_UNDER_TEST)/lib/classlist to $$($1_AOT_JDK_CONF).jdk ) + $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/aot, ( \ + $$(FIXPATH) $(CP) $(JDK_UNDER_TEST)/lib/classlist $$($1_AOT_JDK_CONF).jdk \ + )) + + $$(FIXPATH) $$(CAT) $$($1_AOT_JDK_CONF).* > $$($1_AOT_JDK_CONF).temp + $$(FIXPATH) $$(CAT) $$($1_AOT_JDK_CONF).temp | $(GREP) -v '#' | $(GREP) -v '@' | $(SORT) | \ + $(SED) -e 's/id:.*//g' | uniq \ + > $$($1_AOT_JDK_CONF) + $$(FIXPATH) $$(CAT) $$($1_AOT_JDK_CONF).temp | $(GREP) '@cp' | $(SORT) \ + >> $$($1_AOT_JDK_CONF) + + $$(info AOT: Generate AOT cache $$($1_AOT_JDK_CACHE) with flags: $$($1_VM_OPTIONS)) + $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/aot, ( \ + $$(FIXPATH) $(JDK_UNDER_TEST)/bin/java \ + $$($1_VM_OPTIONS) -Xlog:cds,cds+class=debug:file=$$($1_AOT_JDK_CACHE).log \ + -XX:AOTMode=create -XX:AOTConfiguration=$$($1_AOT_JDK_CONF) -XX:AOTCache=$$($1_AOT_JDK_CACHE) \ + )) + + $1_AOT_TARGETS += $$($1_AOT_JDK_CACHE) + +endef + + SetupRunJtregTest = $(NamedParamsMacroTemplate) define SetupRunJtregTestBody $1_TEST_RESULTS_DIR := $$(TEST_RESULTS_DIR)/$1 @@ -762,6 +815,7 @@ define SetupRunJtregTestBody JTREG_RETRY_COUNT ?= 0 JTREG_REPEAT_COUNT ?= 0 JTREG_REPORT ?= files + JTREG_AOT_JDK ?= false ifneq ($$(JTREG_RETRY_COUNT), 0) ifneq ($$(JTREG_REPEAT_COUNT), 0) @@ -891,6 +945,17 @@ define SetupRunJtregTestBody endif endif + ifeq ($$(JTREG_AOT_JDK), true) + $$(info Add AOT target for $1) + $$(eval $$(call SetupAot, $1, VM_OPTIONS := $$(JTREG_ALL_OPTIONS) )) + + $$(info AOT_TARGETS=$$($1_AOT_TARGETS)) + $$(info AOT_JDK_CACHE=$$($1_AOT_JDK_CACHE)) + + $1_JTREG_BASIC_OPTIONS += -vmoption:-XX:AOTCache="$$($1_AOT_JDK_CACHE)" + endif + + $$(eval $$(call SetupRunJtregTestCustom, $1)) # SetupRunJtregTestCustom might also adjust JTREG_AUTO_ variables @@ -906,6 +971,7 @@ define SetupRunJtregTestBody JTREG_TIMEOUT_FACTOR ?= $$(JTREG_AUTO_TIMEOUT_FACTOR) clean-outputdirs-$1: + $$(call LogWarn, Clean up dirs for $1) $$(RM) -r $$($1_TEST_SUPPORT_DIR) $$(RM) -r $$($1_TEST_RESULTS_DIR) @@ -953,7 +1019,7 @@ define SetupRunJtregTestBody done endif - run-test-$1: pre-run-test clean-outputdirs-$1 + run-test-$1: clean-outputdirs-$1 pre-run-test $$($1_AOT_TARGETS) $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR) \ diff --git a/make/ZipSecurity.gmk b/make/ZipSecurity.gmk index 373ba13ecc6..08f9caadd9a 100644 --- a/make/ZipSecurity.gmk +++ b/make/ZipSecurity.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2024, 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 @@ -27,7 +27,7 @@ default: all include $(SPEC) include MakeBase.gmk -include JavaCompilation.gmk +include ZipArchive.gmk ################################################################################ # diff --git a/make/ZipSource.gmk b/make/ZipSource.gmk index 341af7e9847..c1df6af7583 100644 --- a/make/ZipSource.gmk +++ b/make/ZipSource.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2024, 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 @@ -27,8 +27,8 @@ default: all include $(SPEC) include MakeBase.gmk -include JavaCompilation.gmk include Modules.gmk +include ZipArchive.gmk SRC_ZIP_WORK_DIR := $(SUPPORT_OUTPUTDIR)/src $(if $(filter $(TOPDIR)/%, $(SUPPORT_OUTPUTDIR)), $(eval SRC_ZIP_BASE := $(TOPDIR)), $(eval SRC_ZIP_BASE := $(SUPPORT_OUTPUTDIR))) diff --git a/make/common/modules/LauncherCommon.gmk b/make/common/modules/LauncherCommon.gmk index aa721a683d7..b522df076f3 100644 --- a/make/common/modules/LauncherCommon.gmk +++ b/make/common/modules/LauncherCommon.gmk @@ -178,10 +178,8 @@ ifeq ($(call isTargetOsType, unix)+$(MAKEFILE_PREFIX), true+Launcher) # We assume all our man pages should reside in section 1. MAN_FILES_MD := $(wildcard $(addsuffix /*.md, $(call FindModuleManDirs, $(MODULE)))) - MAN_FILES_TROFF := $(wildcard $(addsuffix /*.1, $(call FindModuleManDirs, $(MODULE)))) ifneq ($(MAN_FILES_MD), ) - # If we got markdown files, ignore the troff files ifeq ($(ENABLE_PANDOC), false) $(info Warning: pandoc not found. Not generating man pages) else @@ -226,13 +224,5 @@ ifeq ($(call isTargetOsType, unix)+$(MAKEFILE_PREFIX), true+Launcher) TARGETS += $(BUILD_MAN_PAGES) endif - else - # No markdown man pages present - $(eval $(call SetupCopyFiles, COPY_MAN_PAGES, \ - DEST := $(SUPPORT_OUTPUTDIR)/modules_man/$(MODULE)/man1, \ - FILES := $(MAN_FILES_TROFF), \ - )) - - TARGETS += $(COPY_MAN_PAGES) endif endif diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index a28d85c146f..25cf15c5f3b 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -253,6 +253,7 @@ var getJibProfilesCommon = function (input, data) { configure_args: concat( "--with-exclude-translations=es,fr,it,ko,pt_BR,sv,ca,tr,cs,sk,ja_JP_A,ja_JP_HA,ja_JP_HI,ja_JP_I,zh_TW,zh_HK", "--disable-jvm-feature-shenandoahgc", + "--disable-cds-archive-coh", versionArgs(input, common)) }; diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 039c531301f..114c82c5229 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -1896,6 +1896,11 @@ private void finishClassLoading(ClassList classes, Map usingModules = package2ModulesUsingIt.getOrDefault(ed.packageName(), Set.of()); ed.to.retainAll(usingModules); diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 1b2eb40b252..0a4c2d9a48d 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -30,6 +30,7 @@ include $(SPEC) include MakeBase.gmk include CopyFiles.gmk +include JarArchive.gmk include JavaCompilation.gmk include TestFilesCompilation.gmk diff --git a/src/demo/share/jfc/SampleTree/SampleTree.java b/src/demo/share/jfc/SampleTree/SampleTree.java index 90588e6ec3a..8ff33828791 100644 --- a/src/demo/share/jfc/SampleTree/SampleTree.java +++ b/src/demo/share/jfc/SampleTree/SampleTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -142,7 +142,6 @@ public SampleTree() { /** Constructs a JPanel containing check boxes for the different * options that tree supports. */ - @SuppressWarnings("serial") private JPanel constructOptionsPanel() { JCheckBox aCheckbox; JPanel retPanel = new JPanel(false); diff --git a/src/demo/share/jfc/TableExample/TableExample3.java b/src/demo/share/jfc/TableExample/TableExample3.java index 9f3c11f4448..a5344f8802a 100644 --- a/src/demo/share/jfc/TableExample/TableExample3.java +++ b/src/demo/share/jfc/TableExample/TableExample3.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -97,7 +97,6 @@ public void windowClosing(WindowEvent e) { }; // Create a model of the data. - @SuppressWarnings("serial") TableModel dataModel = new AbstractTableModel() { // These methods always need to be implemented. diff --git a/src/demo/share/jfc/TableExample/TableExample4.java b/src/demo/share/jfc/TableExample/TableExample4.java index 4d81a3d8cf3..b429c9ec9de 100644 --- a/src/demo/share/jfc/TableExample/TableExample4.java +++ b/src/demo/share/jfc/TableExample/TableExample4.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -99,7 +99,6 @@ public void windowClosing(WindowEvent e) { }; // Create a model of the data. - @SuppressWarnings("serial") TableModel dataModel = new AbstractTableModel() { // These methods always need to be implemented. @@ -180,7 +179,6 @@ public void setValueAt(Object aValue, int row, int column) { // Show the values in the "Favorite Number" column in different colors. TableColumn numbersColumn = tableView.getColumn("Favorite Number"); - @SuppressWarnings("serial") DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index a97d01b7683..017dc0ed85f 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2632,6 +2632,23 @@ bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { // to be subsumed into complex addressing expressions or compute them // into registers? bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { + + // Loads and stores with indirect memory input (e.g., volatile loads and + // stores) do not subsume the input into complex addressing expressions. If + // the addressing expression is input to at least one such load or store, do + // not clone the addressing expression. Query needs_acquiring_load and + // needs_releasing_store as a proxy for indirect memory input, as it is not + // possible to directly query for indirect memory input at this stage. + for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) { + Node* n = m->fast_out(i); + if (n->is_Load() && needs_acquiring_load(n)) { + return false; + } + if (n->is_Store() && needs_releasing_store(n)) { + return false; + } + } + if (clone_base_plus_offset_address(m, mstack, address_visited)) { return true; } @@ -5755,10 +5772,6 @@ opclass memory(indirect, indIndexScaled, indIndexScaledI2L, indIndexI2L, indInde indirectN, indIndexScaledN, indIndexScaledI2LN, indIndexI2LN, indIndexN, indOffIN, indOffLN, indirectX2P, indOffX2P); -opclass memory_noindex(indirect, - indOffI1, indOffL1,indOffI2, indOffL2, indOffI4, indOffL4, indOffI8, indOffL8, - indirectN, indOffIN, indOffLN, indirectX2P, indOffX2P); - // iRegIorL2I is used for src inputs in rules for 32 bit int (I) // operations. it allows the src to be either an iRegI or a (ConvL2I // iRegL). in the latter case the l2i normally planted for a ConvL2I @@ -6695,16 +6708,21 @@ instruct loadNKlass(iRegNNoSp dst, memory4 mem) ins_pipe(iload_reg_mem); %} -instruct loadNKlassCompactHeaders(iRegNNoSp dst, memory_noindex mem) +instruct loadNKlassCompactHeaders(iRegNNoSp dst, memory4 mem) %{ match(Set dst (LoadNKlass mem)); predicate(!needs_acquiring_load(n) && UseCompactObjectHeaders); ins_cost(4 * INSN_COST); - format %{ "load_narrow_klass_compact $dst, $mem\t# compressed class ptr" %} + format %{ + "ldrw $dst, $mem\t# compressed class ptr, shifted\n\t" + "lsrw $dst, $dst, markWord::klass_shift_at_offset" + %} ins_encode %{ - assert($mem$$index$$Register == noreg, "must not have indexed address"); - __ load_narrow_klass_compact_c2($dst$$Register, $mem$$base$$Register, $mem$$disp); + // inlined aarch64_enc_ldrw + loadStore(masm, &MacroAssembler::ldrw, $dst$$Register, $mem->opcode(), + as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp, 4); + __ lsrw($dst$$Register, $dst$$Register, markWord::klass_shift_at_offset); %} ins_pipe(iload_reg_mem); %} diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index 4c22133c056..3b0c8ae432c 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -2690,12 +2690,3 @@ bool C2_MacroAssembler::in_scratch_emit_size() { } return MacroAssembler::in_scratch_emit_size(); } - -void C2_MacroAssembler::load_narrow_klass_compact_c2(Register dst, Register obj, int disp) { - // Note: Don't clobber obj anywhere in that method! - - // The incoming address is pointing into obj-start + klass_offset_in_bytes. We need to extract - // obj-start, so that we can load from the object's mark-word instead. - ldr(dst, Address(obj, disp - oopDesc::klass_offset_in_bytes())); - lsr(dst, dst, markWord::klass_shift); -} diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp index c6ddcf46cba..d61b050407d 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp @@ -186,6 +186,4 @@ void vector_signum_sve(FloatRegister dst, FloatRegister src, FloatRegister zero, FloatRegister one, FloatRegister vtmp, PRegister pgtmp, SIMD_RegVariant T); - void load_narrow_klass_compact_c2(Register dst, Register obj, int disp); - #endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp index 34e6e688abb..e57dab7d1ed 100644 --- a/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp @@ -66,6 +66,7 @@ define_pd_global(bool, OptoScheduling, false); define_pd_global(bool, OptoBundling, false); define_pd_global(bool, OptoRegScheduling, false); define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); +define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 8); define_pd_global(bool, IdealizeClearArrayNode, true); define_pd_global(intx, ReservedCodeCacheSize, 48*M); diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index b892489af70..836caa86cb0 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -393,7 +393,13 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, bool verifyoop, bool generate_poll) { if (VerifyActivationFrameSize) { - Unimplemented(); + Label L; + sub(rscratch2, rfp, esp); + int min_frame_size = (frame::link_offset - frame::interpreter_frame_initial_sp_offset) * wordSize; + subs(rscratch2, rscratch2, min_frame_size); + br(Assembler::GE, L); + stop("broken stack frame"); + bind(L); } if (verifyoop) { interp_verify_oop(r0, state); diff --git a/src/hotspot/cpu/arm/c2_globals_arm.hpp b/src/hotspot/cpu/arm/c2_globals_arm.hpp index 57ed8f11c08..a44a8f649ae 100644 --- a/src/hotspot/cpu/arm/c2_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c2_globals_arm.hpp @@ -64,6 +64,7 @@ define_pd_global(bool, OptoBundling, false); define_pd_global(bool, OptoScheduling, true); define_pd_global(bool, OptoRegScheduling, false); define_pd_global(bool, SuperWordLoopUnrollAnalysis, false); +define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); define_pd_global(bool, IdealizeClearArrayNode, true); #ifdef _LP64 diff --git a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp index 00a92ff6b62..f45faa21f01 100644 --- a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp @@ -59,6 +59,7 @@ define_pd_global(bool, UseCISCSpill, false); define_pd_global(bool, OptoBundling, false); define_pd_global(bool, OptoRegScheduling, false); define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); +define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); // GL: // Detected a problem with unscaled compressed oops and // narrow_oop_use_complex_address() == false. diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 84102ef41e8..aedded83623 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -1602,7 +1602,6 @@ static void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj, #ifdef ASSERT __ load_const_optimized(tmp2, ContinuationEntry::cookie_value()); __ stw(tmp2, in_bytes(ContinuationEntry::cookie_offset()), R1_SP); - __ std(tmp2, _abi0(cr), R1_SP); #endif //ASSERT __ li(zero, 0); @@ -1646,10 +1645,6 @@ static void continuation_enter_cleanup(MacroAssembler* masm) { __ ld_ptr(tmp1, JavaThread::cont_entry_offset(), R16_thread); __ cmpd(CCR0, R1_SP, tmp1); __ asm_assert_eq(FILE_AND_LINE ": incorrect R1_SP"); - __ load_const_optimized(tmp1, ContinuationEntry::cookie_value()); - __ ld(tmp2, _abi0(cr), R1_SP); - __ cmpd(CCR0, tmp1, tmp2); - __ asm_assert_eq(FILE_AND_LINE ": cookie not found"); #endif __ ld_ptr(tmp1, ContinuationEntry::parent_cont_fastpath_offset(), R1_SP); diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index 7b0316e208f..bf553b35770 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -3124,13 +3124,3 @@ void C2_MacroAssembler::extract_fp_v(FloatRegister dst, VectorRegister src, Basi vfmv_f_s(dst, tmp); } } - -void C2_MacroAssembler::load_narrow_klass_compact_c2(Register dst, Address src) { - // The incoming address is pointing into obj-start + klass_offset_in_bytes. We need to extract - // obj-start, so that we can load from the object's mark-word instead. Usually the address - // comes as obj-start in obj and klass_offset_in_bytes in disp. - assert(UseCompactObjectHeaders, "must"); - int offset = oopDesc::mark_offset_in_bytes() - oopDesc::klass_offset_in_bytes(); - ld(dst, Address(src.base(), src.offset() + offset)); - srli(dst, dst, markWord::klass_shift); -} diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp index 8f9d9cd2ccd..8736294e72c 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp @@ -281,6 +281,4 @@ void extract_v(Register dst, VectorRegister src, BasicType bt, int idx, VectorRegister tmp); void extract_fp_v(FloatRegister dst, VectorRegister src, BasicType bt, int idx, VectorRegister tmp); - void load_narrow_klass_compact_c2(Register dst, Address src); - #endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp index 53a41665f4b..e9947f9888a 100644 --- a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp @@ -66,6 +66,7 @@ define_pd_global(bool, OptoScheduling, true); define_pd_global(bool, OptoBundling, false); define_pd_global(bool, OptoRegScheduling, false); define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); +define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); define_pd_global(bool, IdealizeClearArrayNode, true); define_pd_global(intx, ReservedCodeCacheSize, 48*M); diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index cc3c3b4a63c..ffbb7c58911 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -117,8 +117,6 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseZvfh, false, DIAGNOSTIC, "Use Zvfh instructions") \ product(bool, UseZvkn, false, EXPERIMENTAL, \ "Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \ - product(bool, UseRVVForBigIntegerShiftIntrinsics, true, \ - "Use RVV instructions for left/right shift of BigInteger") \ product(bool, UseCtxFencei, false, EXPERIMENTAL, \ "Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush") diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index b00b4474d69..897222ef995 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -441,7 +441,14 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, Register Rs) { // Pay attention to the argument Rs, which is acquiesce in t0. if (VerifyActivationFrameSize) { - Unimplemented(); + Label L; + sub(t1, fp, esp); + int min_frame_size = + (frame::link_offset - frame::interpreter_frame_initial_sp_offset + frame::metadata_words) * wordSize; + sub(t1, t1, min_frame_size); + bgez(t1, L); + stop("broken stack frame"); + bind(L); } if (verifyoop && state == atos) { verify_oop(x10); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index ac0445e5e4e..81d3338638d 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -3466,6 +3466,17 @@ void MacroAssembler::cmpxchg(Register addr, Register expected, assert_different_registers(expected, t0); assert_different_registers(new_val, t0); + // NOTE: + // Register _result_ may be the same register as _new_val_ or _expected_. + // Hence do NOT use _result_ until after 'cas'. + // + // Register _expected_ may be the same register as _new_val_ and is assumed to be preserved. + // Hence do NOT change _expected_ or _new_val_. + // + // Having _expected_ and _new_val_ being the same register is a very puzzling cas. + // + // TODO: Address these issues. + if (UseZacas) { if (result_as_bool) { mv(t0, expected); @@ -3473,8 +3484,9 @@ void MacroAssembler::cmpxchg(Register addr, Register expected, xorr(t0, t0, expected); seqz(result, t0); } else { - mv(result, expected); - atomic_cas(result, new_val, addr, size, acquire, release); + mv(t0, expected); + atomic_cas(t0, new_val, addr, size, acquire, release); + mv(result, t0); } return; } @@ -3510,15 +3522,16 @@ void MacroAssembler::cmpxchg_weak(Register addr, Register expected, enum operand_size size, Assembler::Aqrl acquire, Assembler::Aqrl release, Register result) { - if (UseZacas) { - cmpxchg(addr, expected, new_val, size, acquire, release, result, true); - return; - } assert_different_registers(addr, t0); assert_different_registers(expected, t0); assert_different_registers(new_val, t0); + if (UseZacas) { + cmpxchg(addr, expected, new_val, size, acquire, release, result, true); + return; + } + Label fail, done; load_reserved(t0, addr, size, acquire); bne(t0, expected, fail); @@ -3581,83 +3594,18 @@ ATOMIC_XCHGU(xchgalwu, xchgalw) #undef ATOMIC_XCHGU -#define ATOMIC_CAS(OP, AOP, ACQUIRE, RELEASE) \ -void MacroAssembler::atomic_##OP(Register prev, Register newv, Register addr) { \ - assert(UseZacas, "invariant"); \ - prev = prev->is_valid() ? prev : zr; \ - AOP(prev, addr, newv, (Assembler::Aqrl)(ACQUIRE | RELEASE)); \ - return; \ -} - -ATOMIC_CAS(cas, amocas_d, Assembler::relaxed, Assembler::relaxed) -ATOMIC_CAS(casw, amocas_w, Assembler::relaxed, Assembler::relaxed) -ATOMIC_CAS(casl, amocas_d, Assembler::relaxed, Assembler::rl) -ATOMIC_CAS(caslw, amocas_w, Assembler::relaxed, Assembler::rl) -ATOMIC_CAS(casal, amocas_d, Assembler::aq, Assembler::rl) -ATOMIC_CAS(casalw, amocas_w, Assembler::aq, Assembler::rl) - -#undef ATOMIC_CAS - -#define ATOMIC_CASU(OP1, OP2) \ -void MacroAssembler::atomic_##OP1(Register prev, Register newv, Register addr) { \ - atomic_##OP2(prev, newv, addr); \ - zero_extend(prev, prev, 32); \ - return; \ -} - -ATOMIC_CASU(caswu, casw) -ATOMIC_CASU(caslwu, caslw) -ATOMIC_CASU(casalwu, casalw) - -#undef ATOMIC_CASU - -void MacroAssembler::atomic_cas( - Register prev, Register newv, Register addr, enum operand_size size, Assembler::Aqrl acquire, Assembler::Aqrl release) { +void MacroAssembler::atomic_cas(Register prev, Register newv, Register addr, + enum operand_size size, Assembler::Aqrl acquire, Assembler::Aqrl release) { switch (size) { case int64: - switch ((Assembler::Aqrl)(acquire | release)) { - case Assembler::relaxed: - atomic_cas(prev, newv, addr); - break; - case Assembler::rl: - atomic_casl(prev, newv, addr); - break; - case Assembler::aqrl: - atomic_casal(prev, newv, addr); - break; - default: - ShouldNotReachHere(); - } + amocas_d(prev, addr, newv, (Assembler::Aqrl)(acquire | release)); break; case int32: - switch ((Assembler::Aqrl)(acquire | release)) { - case Assembler::relaxed: - atomic_casw(prev, newv, addr); - break; - case Assembler::rl: - atomic_caslw(prev, newv, addr); - break; - case Assembler::aqrl: - atomic_casalw(prev, newv, addr); - break; - default: - ShouldNotReachHere(); - } + amocas_w(prev, addr, newv, (Assembler::Aqrl)(acquire | release)); break; case uint32: - switch ((Assembler::Aqrl)(acquire | release)) { - case Assembler::relaxed: - atomic_caswu(prev, newv, addr); - break; - case Assembler::rl: - atomic_caslwu(prev, newv, addr); - break; - case Assembler::aqrl: - atomic_casalwu(prev, newv, addr); - break; - default: - ShouldNotReachHere(); - } + amocas_w(prev, addr, newv, (Assembler::Aqrl)(acquire | release)); + zero_extend(prev, prev, 32); break; default: ShouldNotReachHere(); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index dc06708b0ff..568df056222 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -1175,16 +1175,6 @@ class MacroAssembler: public Assembler { void atomic_xchgwu(Register prev, Register newv, Register addr); void atomic_xchgalwu(Register prev, Register newv, Register addr); - void atomic_cas(Register prev, Register newv, Register addr); - void atomic_casw(Register prev, Register newv, Register addr); - void atomic_casl(Register prev, Register newv, Register addr); - void atomic_caslw(Register prev, Register newv, Register addr); - void atomic_casal(Register prev, Register newv, Register addr); - void atomic_casalw(Register prev, Register newv, Register addr); - void atomic_caswu(Register prev, Register newv, Register addr); - void atomic_caslwu(Register prev, Register newv, Register addr); - void atomic_casalwu(Register prev, Register newv, Register addr); - void atomic_cas(Register prev, Register newv, Register addr, enum operand_size size, Assembler::Aqrl acquire = Assembler::relaxed, Assembler::Aqrl release = Assembler::relaxed); diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index b944cc5b4b9..ae8565e1bcf 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -4814,10 +4814,14 @@ instruct loadNKlassCompactHeaders(iRegNNoSp dst, memory mem) match(Set dst (LoadNKlass mem)); ins_cost(LOAD_COST); - format %{ "load_narrow_klass_compact $dst, $mem\t# compressed class ptr, #@loadNKlassCompactHeaders" %} + format %{ + "lwu $dst, $mem\t# compressed klass ptr, shifted\n\t" + "srli $dst, $dst, markWord::klass_shift_at_offset" + %} ins_encode %{ - __ load_narrow_klass_compact_c2(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp)); + __ srli(as_Register($dst$$reg), as_Register($dst$$reg), (unsigned) markWord::klass_shift_at_offset); %} ins_pipe(iload_reg_mem); diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index e4ae4f3cfd1..795e6882c6a 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -6502,7 +6502,7 @@ static const int64_t right_3_bits = right_n_bits(3); StubRoutines::_poly1305_processBlocks = generate_poly1305_processBlocks(); } - if (UseRVVForBigIntegerShiftIntrinsics) { + if (UseRVV) { StubRoutines::_bigIntegerLeftShiftWorker = generate_bigIntegerLeftShift(); StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift(); } diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp index 6d5492b86b3..28b797a639e 100644 --- a/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp @@ -34,16 +34,6 @@ // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. -address StubRoutines::riscv::_get_previous_sp_entry = nullptr; - -address StubRoutines::riscv::_f2i_fixup = nullptr; -address StubRoutines::riscv::_f2l_fixup = nullptr; -address StubRoutines::riscv::_d2i_fixup = nullptr; -address StubRoutines::riscv::_d2l_fixup = nullptr; -address StubRoutines::riscv::_float_sign_mask = nullptr; -address StubRoutines::riscv::_float_sign_flip = nullptr; -address StubRoutines::riscv::_double_sign_mask = nullptr; -address StubRoutines::riscv::_double_sign_flip = nullptr; address StubRoutines::riscv::_zero_blocks = nullptr; address StubRoutines::riscv::_compare_long_string_LL = nullptr; address StubRoutines::riscv::_compare_long_string_UU = nullptr; @@ -52,7 +42,6 @@ address StubRoutines::riscv::_compare_long_string_UL = nullptr; address StubRoutines::riscv::_string_indexof_linear_ll = nullptr; address StubRoutines::riscv::_string_indexof_linear_uu = nullptr; address StubRoutines::riscv::_string_indexof_linear_ul = nullptr; -address StubRoutines::riscv::_large_byte_array_inflate = nullptr; bool StubRoutines::riscv::_completed = false; diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp index 3d1f4a61f00..a099d71475e 100644 --- a/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp +++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp @@ -47,18 +47,6 @@ class riscv { friend class StubGenerator; private: - static address _get_previous_sp_entry; - - static address _f2i_fixup; - static address _f2l_fixup; - static address _d2i_fixup; - static address _d2l_fixup; - - static address _float_sign_mask; - static address _float_sign_flip; - static address _double_sign_mask; - static address _double_sign_flip; - static address _zero_blocks; static address _compare_long_string_LL; @@ -68,48 +56,11 @@ class riscv { static address _string_indexof_linear_ll; static address _string_indexof_linear_uu; static address _string_indexof_linear_ul; - static address _large_byte_array_inflate; static bool _completed; public: - static address get_previous_sp_entry() { - return _get_previous_sp_entry; - } - - static address f2i_fixup() { - return _f2i_fixup; - } - - static address f2l_fixup() { - return _f2l_fixup; - } - - static address d2i_fixup() { - return _d2i_fixup; - } - - static address d2l_fixup() { - return _d2l_fixup; - } - - static address float_sign_mask() { - return _float_sign_mask; - } - - static address float_sign_flip() { - return _float_sign_flip; - } - - static address double_sign_mask() { - return _double_sign_mask; - } - - static address double_sign_flip() { - return _double_sign_flip; - } - static address zero_blocks() { return _zero_blocks; } @@ -142,10 +93,6 @@ class riscv { return _string_indexof_linear_uu; } - static address large_byte_array_inflate() { - return _large_byte_array_inflate; - } - static bool complete() { return _completed; } diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 6e8ee1ab7e0..3b8d8119a8e 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -150,11 +150,12 @@ void VM_Version::common_initialize() { } if (FLAG_IS_DEFAULT(AvoidUnalignedAccesses)) { - if (unaligned_access.value() != MISALIGNED_FAST) { - FLAG_SET_DEFAULT(AvoidUnalignedAccesses, true); - } else { - FLAG_SET_DEFAULT(AvoidUnalignedAccesses, false); - } + FLAG_SET_DEFAULT(AvoidUnalignedAccesses, + unaligned_access.value() != MISALIGNED_FAST); + } + + if (FLAG_IS_DEFAULT(AlignVector)) { + FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses); } // See JDK-8026049 @@ -233,7 +234,6 @@ void VM_Version::c2_initialize() { if (!UseRVV) { FLAG_SET_DEFAULT(MaxVectorSize, 0); - FLAG_SET_DEFAULT(UseRVVForBigIntegerShiftIntrinsics, false); } else { if (!FLAG_IS_DEFAULT(MaxVectorSize) && MaxVectorSize != _initial_vector_length) { warning("Current system does not support RVV vector length for MaxVectorSize %d. Set MaxVectorSize to %d", diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp index c98c100a068..60e347a2d92 100644 --- a/src/hotspot/cpu/s390/assembler_s390.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.hpp @@ -1236,6 +1236,9 @@ class Assembler : public AbstractAssembler { // NOR #define VNO_ZOPC (unsigned long)(0xe7L << 40 | 0x6bL << 0) // V1 := !(V2 | V3), element size = 2**m + //NOT-XOR +#define VNX_ZOPC (unsigned long)(0xe7L << 40 | 0x6cL << 0) // V1 := !(V2 | V3), element size = 2**m + // OR #define VO_ZOPC (unsigned long)(0xe7L << 40 | 0x6aL << 0) // V1 := V2 | V3, element size = 2**m @@ -1287,6 +1290,13 @@ class Assembler : public AbstractAssembler { #define VSTRC_ZOPC (unsigned long)(0xe7L << 40 | 0x8aL << 0) // String range compare #define VISTR_ZOPC (unsigned long)(0xe7L << 40 | 0x5cL << 0) // Isolate String +#define VFA_ZOPC (unsigned long)(0xe7L << 40 | 0xE3L << 0) // V1 := V2 + V3, element size = 2**m +#define VFS_ZOPC (unsigned long)(0xe7L << 40 | 0xE2L << 0) // V1 := V2 - V3, element size = 2**m +#define VFM_ZOPC (unsigned long)(0xe7L << 40 | 0xE7L << 0) // V1 := V2 * V3, element size = 2**m +#define VFD_ZOPC (unsigned long)(0xe7L << 40 | 0xE5L << 0) // V1 := V2 / V3, element size = 2**m +#define VFSQ_ZOPC (unsigned long)(0xe7L << 40 | 0xCEL << 0) // V1 := sqrt of V2, element size = 2**m +#define VFLR_ZOPC (unsigned long)(0xe7L << 40 | 0xC5L << 0) // vector fp load rounded, element size = 2**m + //-------------------------------- //-- Miscellaneous Operations -- @@ -2322,22 +2332,22 @@ class Assembler : public AbstractAssembler { inline void z_xilf(Register r1, int64_t i2); // xor r1 = r1 ^ i2_imm32 ; or only for bits 32-63 // shift - inline void z_sla( Register r1, int64_t d2, Register b2=Z_R0); // shift left r1 = r1 << ((d2+b2)&0x3f) ; int32, only 31 bits shifted, sign preserved! - inline void z_slak(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int32, only 31 bits shifted, sign preserved! - inline void z_slag(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int64, only 63 bits shifted, sign preserved! - inline void z_sra( Register r1, int64_t d2, Register b2=Z_R0); // shift right r1 = r1 >> ((d2+b2)&0x3f) ; int32, sign extended - inline void z_srak(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int32, sign extended - inline void z_srag(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int64, sign extended - inline void z_sll( Register r1, int64_t d2, Register b2=Z_R0); // shift left r1 = r1 << ((d2+b2)&0x3f) ; int32, zeros added - inline void z_sllk(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int32, zeros added - inline void z_sllg(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int64, zeros added - inline void z_srl( Register r1, int64_t d2, Register b2=Z_R0); // shift right r1 = r1 >> ((d2+b2)&0x3f) ; int32, zero extended - inline void z_srlk(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int32, zero extended - inline void z_srlg(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int64, zero extended + inline void z_sla( Register r1, int64_t d2, Register b2 = Z_R0); // shift left r1 = r1 << ((d2+b2)&0x3f) ; int32, only 31 bits shifted, sign preserved! + inline void z_slak(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int32, only 31 bits shifted, sign preserved! + inline void z_slag(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int64, only 63 bits shifted, sign preserved! + inline void z_sra( Register r1, int64_t d2, Register b2 = Z_R0); // shift right r1 = r1 >> ((d2+b2)&0x3f) ; int32, sign extended + inline void z_srak(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int32, sign extended + inline void z_srag(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int64, sign extended + inline void z_sll( Register r1, int64_t d2, Register b2 = Z_R0); // shift left r1 = r1 << ((d2+b2)&0x3f) ; int32, zeros added + inline void z_sllk(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int32, zeros added + inline void z_sllg(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // shift left r1 = r3 << ((d2+b2)&0x3f) ; int64, zeros added + inline void z_srl( Register r1, int64_t d2, Register b2 = Z_R0); // shift right r1 = r1 >> ((d2+b2)&0x3f) ; int32, zero extended + inline void z_srlk(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int32, zero extended + inline void z_srlg(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int64, zero extended // rotate - inline void z_rll( Register r1, Register r3, int64_t d2, Register b2=Z_R0); // rot r1 = r3 << (d2+b2 & 0x3f) ; int32 -- z10 - inline void z_rllg(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // rot r1 = r3 << (d2+b2 & 0x3f) ; int64 -- z10 + inline void z_rll( Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // rot r1 = r3 << (d2+b2 & 0x3f) ; int32 -- z10 + inline void z_rllg(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // rot r1 = r3 << (d2+b2 & 0x3f) ; int64 -- z10 // rotate the AND/XOR/OR/insert inline void z_rnsbg( Register r1, Register r2, int64_t spos3, int64_t epos4, int64_t nrot5, bool test_only = false); // rotate then AND selected bits -- z196 @@ -2459,7 +2469,7 @@ class Assembler : public AbstractAssembler { inline void z_mvc(const Address& d, const Address& s, int64_t l); // move l bytes inline void z_mvc(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2); // move l+1 bytes inline void z_mvcin(int64_t d1, int64_t l, Register b1, int64_t d2, Register b2); // move l+1 bytes - inline void z_mvcle(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // move region of memory + inline void z_mvcle(Register r1, Register r3, int64_t d2, Register b2 = Z_R0); // move region of memory inline void z_stfle(int64_t d2, Register b2); // store facility list extended @@ -2491,6 +2501,7 @@ class Assembler : public AbstractAssembler { // Load (transfer from memory) inline void z_vlm( VectorRegister v1, VectorRegister v3, int64_t d2, Register b2); inline void z_vl( VectorRegister v1, int64_t d2, Register x2, Register b2); + inline void z_vl( VectorRegister v1, const Address& a); inline void z_vleb( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t m3); inline void z_vleh( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t m3); inline void z_vlef( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t m3); @@ -2529,10 +2540,10 @@ class Assembler : public AbstractAssembler { inline void z_vlgvg( Register r1, VectorRegister v3, int64_t d2, Register b2); inline void z_vlvg( VectorRegister v1, Register r3, int64_t d2, Register b2, int64_t m4); - inline void z_vlvgb( VectorRegister v1, Register r3, int64_t d2, Register b2); - inline void z_vlvgh( VectorRegister v1, Register r3, int64_t d2, Register b2); - inline void z_vlvgf( VectorRegister v1, Register r3, int64_t d2, Register b2); - inline void z_vlvgg( VectorRegister v1, Register r3, int64_t d2, Register b2); + inline void z_vlvgb( VectorRegister v1, Register r3, int64_t d2, Register b2 = Z_R0); + inline void z_vlvgh( VectorRegister v1, Register r3, int64_t d2, Register b2 = Z_R0); + inline void z_vlvgf( VectorRegister v1, Register r3, int64_t d2, Register b2 = Z_R0); + inline void z_vlvgg( VectorRegister v1, Register r3, int64_t d2, Register b2 = Z_R0); inline void z_vlvgp( VectorRegister v1, Register r2, Register r3); @@ -2619,6 +2630,7 @@ class Assembler : public AbstractAssembler { // Store inline void z_vstm( VectorRegister v1, VectorRegister v3, int64_t d2, Register b2); inline void z_vst( VectorRegister v1, int64_t d2, Register x2, Register b2); + inline void z_vst( VectorRegister v1, const Address& a); inline void z_vsteb( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t m3); inline void z_vsteh( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t m3); inline void z_vstef( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t m3); @@ -2679,13 +2691,16 @@ class Assembler : public AbstractAssembler { inline void z_vscbiq( VectorRegister v1, VectorRegister v2, VectorRegister v3); // MULTIPLY - inline void z_vml( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); - inline void z_vmh( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); - inline void z_vmlh( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); - inline void z_vme( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); - inline void z_vmle( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); - inline void z_vmo( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); - inline void z_vmlo( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vml( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vmlb( VectorRegister v1, VectorRegister v2, VectorRegister v3); + inline void z_vmlhw(VectorRegister v1, VectorRegister v2, VectorRegister v3); + inline void z_vmlf( VectorRegister v1, VectorRegister v2, VectorRegister v3); + inline void z_vmh( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vmlh( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vme( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vmle( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vmo( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vmlo( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); // MULTIPLY & ADD inline void z_vmal( VectorRegister v1, VectorRegister v2, VectorRegister v3, VectorRegister v4, int64_t m5); @@ -2744,6 +2759,9 @@ class Assembler : public AbstractAssembler { // NOR inline void z_vno( VectorRegister v1, VectorRegister v2, VectorRegister v3); + //NOT-XOR + inline void z_vnx( VectorRegister v1, VectorRegister v2, VectorRegister v3); + // OR inline void z_vo( VectorRegister v1, VectorRegister v2, VectorRegister v3); @@ -2810,6 +2828,10 @@ class Assembler : public AbstractAssembler { inline void z_vctzf( VectorRegister v1, VectorRegister v2); inline void z_vctzg( VectorRegister v1, VectorRegister v2); inline void z_vpopct( VectorRegister v1, VectorRegister v2, int64_t m3); + inline void z_vpopctb(VectorRegister v1, VectorRegister v2); + inline void z_vpopcth(VectorRegister v1, VectorRegister v2); + inline void z_vpopctf(VectorRegister v1, VectorRegister v2); + inline void z_vpopctg(VectorRegister v1, VectorRegister v2); // Rotate/Shift inline void z_verllv( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); @@ -2898,9 +2920,39 @@ class Assembler : public AbstractAssembler { inline void z_vistrfs(VectorRegister v1, VectorRegister v2); - // Floatingpoint instructions + // Vector Floatingpoint instructions // ========================== + // Add + inline void z_vfa( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vfasb(VectorRegister v1, VectorRegister v2, VectorRegister v3); + inline void z_vfadb(VectorRegister v1, VectorRegister v2, VectorRegister v3); + + //SUB + inline void z_vfs( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vfssb(VectorRegister v1, VectorRegister v2, VectorRegister v3); + inline void z_vfsdb(VectorRegister v1, VectorRegister v2, VectorRegister v3); + + //MUL + inline void z_vfm( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vfmsb(VectorRegister v1, VectorRegister v2, VectorRegister v3); + inline void z_vfmdb(VectorRegister v1, VectorRegister v2, VectorRegister v3); + + //DIV + inline void z_vfd( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4); + inline void z_vfdsb(VectorRegister v1, VectorRegister v2, VectorRegister v3); + inline void z_vfddb(VectorRegister v1, VectorRegister v2, VectorRegister v3); + + //square root + inline void z_vfsq( VectorRegister v1, VectorRegister v2, int64_t m3); + inline void z_vfsqsb(VectorRegister v1, VectorRegister v2); + inline void z_vfsqdb(VectorRegister v1, VectorRegister v2); + + //vector fp load rounded + inline void z_vflr( VectorRegister v1, VectorRegister v2, int64_t m3, int64_t m5); + inline void z_vflrd( VectorRegister v1, VectorRegister v2, int64_t m5); + // Floatingpoint instructions + // ========================== // compare instructions inline void z_cebr(FloatRegister r1, FloatRegister r2); // compare (r1, r2) ; float inline void z_ceb(FloatRegister r1, int64_t d2, Register x2, Register b2); // compare (r1, *(d2_imm12+x2+b2)) ; float diff --git a/src/hotspot/cpu/s390/assembler_s390.inline.hpp b/src/hotspot/cpu/s390/assembler_s390.inline.hpp index 78ce87ddeb7..e9277b8bb6f 100644 --- a/src/hotspot/cpu/s390/assembler_s390.inline.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.inline.hpp @@ -787,6 +787,7 @@ inline void Assembler::z_vleb( VectorRegister v1, int64_t d2, Register x2, Reg inline void Assembler::z_vleh( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t ix3){emit_48(VLEH_ZOPC | vreg(v1, 8) | rxmask_48(d2, x2, b2) | uimm4(ix3, 32, 48)); } inline void Assembler::z_vlef( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t ix3){emit_48(VLEF_ZOPC | vreg(v1, 8) | rxmask_48(d2, x2, b2) | uimm4(ix3, 32, 48)); } inline void Assembler::z_vleg( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t ix3){emit_48(VLEG_ZOPC | vreg(v1, 8) | rxmask_48(d2, x2, b2) | uimm4(ix3, 32, 48)); } +inline void Assembler::z_vl(VectorRegister v1, const Address& a) { z_vl(v1, a.disp(), a.indexOrR0(), a.baseOrR0()); } // Gather/Scatter inline void Assembler::z_vgef( VectorRegister v1, int64_t d2, VectorRegister vx2, Register b2, int64_t ix3) {emit_48(VGEF_ZOPC | vreg(v1, 8) | rvmask_48(d2, vx2, b2) | uimm4(ix3, 32, 48)); } @@ -820,7 +821,7 @@ inline void Assembler::z_vlgvh( Register r1, VectorRegister v3, int64_t d2, Reg inline void Assembler::z_vlgvf( Register r1, VectorRegister v3, int64_t d2, Register b2) {z_vlgv(r1, v3, d2, b2, VRET_FW); } // load FW from VR element (index d2(b2)) into GR (logical) inline void Assembler::z_vlgvg( Register r1, VectorRegister v3, int64_t d2, Register b2) {z_vlgv(r1, v3, d2, b2, VRET_DW); } // load DW from VR element (index d2(b2)) into GR. -inline void Assembler::z_vlvg( VectorRegister v1, Register r3, int64_t d2, Register b2, int64_t m4) {emit_48(VLVG_ZOPC | vreg(v1, 8) | reg(r3, 12, 48) | rsmask_48(d2, b2) | vesc_mask(m4, VRET_BYTE, VRET_DW, 32)); } +inline void Assembler::z_vlvg( VectorRegister v1, Register r3, int64_t d2, Register b2, int64_t m4) {emit_48(VLVG_ZOPC | vreg(v1, 8) | reg(r3, 12, 48) | rsmaskt_48(d2, b2) | vesc_mask(m4, VRET_BYTE, VRET_DW, 32)); } inline void Assembler::z_vlvgb( VectorRegister v1, Register r3, int64_t d2, Register b2) {z_vlvg(v1, r3, d2, b2, VRET_BYTE); } inline void Assembler::z_vlvgh( VectorRegister v1, Register r3, int64_t d2, Register b2) {z_vlvg(v1, r3, d2, b2, VRET_HW); } inline void Assembler::z_vlvgf( VectorRegister v1, Register r3, int64_t d2, Register b2) {z_vlvg(v1, r3, d2, b2, VRET_FW); } @@ -916,6 +917,7 @@ inline void Assembler::z_vsteh( VectorRegister v1, int64_t d2, Register x2, Reg inline void Assembler::z_vstef( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t ix3){emit_48(VSTEF_ZOPC | vreg(v1, 8) | rxmask_48(d2, x2, b2) | uimm4(ix3, 32, 48)); } inline void Assembler::z_vsteg( VectorRegister v1, int64_t d2, Register x2, Register b2, int64_t ix3){emit_48(VSTEG_ZOPC | vreg(v1, 8) | rxmask_48(d2, x2, b2) | uimm4(ix3, 32, 48)); } inline void Assembler::z_vstl( VectorRegister v1, Register r3, int64_t d2, Register b2) {emit_48(VSTL_ZOPC | vreg(v1, 8) | reg(r3, 12, 48) | rsmask_48(d2, b2)); } +inline void Assembler::z_vst(VectorRegister v1, const Address& a) { z_vst(v1, a.disp(), a.indexOrR0(), a.baseOrR0()); } // Misc inline void Assembler::z_vgm( VectorRegister v1, int64_t imm2, int64_t imm3, int64_t m4) {emit_48(VGM_ZOPC | vreg(v1, 8) | uimm8( imm2, 16, 48) | uimm8(imm3, 24, 48) | vesc_mask(m4, VRET_BYTE, VRET_DW, 32)); } @@ -973,6 +975,9 @@ inline void Assembler::z_vscbiq( VectorRegister v1, VectorRegister v2, VectorReg // MULTIPLY inline void Assembler::z_vml( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VML_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_BYTE, VRET_FW, 32)); } inline void Assembler::z_vmh( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VMH_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_BYTE, VRET_FW, 32)); } +inline void Assembler::z_vmlb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vml(v1, v2, v3, VRET_BYTE);} // vector element type 'B' +inline void Assembler::z_vmlhw( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vml(v1, v2, v3, VRET_HW);} // vector element type 'H' +inline void Assembler::z_vmlf( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vml(v1, v2, v3, VRET_FW);} // vector element type 'F' inline void Assembler::z_vmlh( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VMLH_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_BYTE, VRET_FW, 32)); } inline void Assembler::z_vme( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VME_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_BYTE, VRET_FW, 32)); } inline void Assembler::z_vmle( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VMLE_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_BYTE, VRET_FW, 32)); } @@ -1035,6 +1040,9 @@ inline void Assembler::z_vx( VectorRegister v1, VectorRegister v2, VectorReg // NOR inline void Assembler::z_vno( VectorRegister v1, VectorRegister v2, VectorRegister v3) {emit_48(VNO_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16)); } +//NOT-XOR +inline void Assembler::z_vnx( VectorRegister v1, VectorRegister v2, VectorRegister v3) {emit_48(VNX_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16)); } + // OR inline void Assembler::z_vo( VectorRegister v1, VectorRegister v2, VectorRegister v3) {emit_48(VO_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16)); } @@ -1101,6 +1109,10 @@ inline void Assembler::z_vctzh( VectorRegister v1, VectorRegister v2) inline void Assembler::z_vctzf( VectorRegister v1, VectorRegister v2) {z_vctz(v1, v2, VRET_FW); } // vector element type 'F' inline void Assembler::z_vctzg( VectorRegister v1, VectorRegister v2) {z_vctz(v1, v2, VRET_DW); } // vector element type 'G' inline void Assembler::z_vpopct( VectorRegister v1, VectorRegister v2, int64_t m3) {emit_48(VPOPCT_ZOPC| vreg(v1, 8) | vreg(v2, 12) | vesc_mask(m3, VRET_BYTE, VRET_DW, 32)); } +inline void Assembler::z_vpopctb( VectorRegister v1, VectorRegister v2) {z_vpopct(v1, v2, VRET_BYTE); } +inline void Assembler::z_vpopcth( VectorRegister v1, VectorRegister v2) {z_vpopct(v1, v2, VRET_HW); } +inline void Assembler::z_vpopctf( VectorRegister v1, VectorRegister v2) {z_vpopct(v1, v2, VRET_FW); } +inline void Assembler::z_vpopctg( VectorRegister v1, VectorRegister v2) {z_vpopct(v1, v2, VRET_DW); } // Rotate/Shift inline void Assembler::z_verllv( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VERLLV_ZOPC| vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_BYTE, VRET_DW, 32)); } @@ -1108,7 +1120,7 @@ inline void Assembler::z_verllvb(VectorRegister v1, VectorRegister v2, VectorReg inline void Assembler::z_verllvh(VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_verllv(v1, v2, v3, VRET_HW); } // vector element type 'H' inline void Assembler::z_verllvf(VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_verllv(v1, v2, v3, VRET_FW); } // vector element type 'F' inline void Assembler::z_verllvg(VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_verllv(v1, v2, v3, VRET_DW); } // vector element type 'G' -inline void Assembler::z_verll( VectorRegister v1, VectorRegister v3, int64_t d2, Register b2, int64_t m4) {emit_48(VERLL_ZOPC | vreg(v1, 8) | vreg(v3, 12) | rsmask_48(d2, b2) | vesc_mask(m4, VRET_BYTE, VRET_DW, 32)); } +inline void Assembler::z_verll( VectorRegister v1, VectorRegister v3, int64_t d2, Register b2, int64_t m4) {emit_48(VERLL_ZOPC | vreg(v1, 8) | vreg(v3, 12) | rsmask_48(d2, b2) | vesc_mask(m4, VRET_BYTE, VRET_DW, 32)); } inline void Assembler::z_verllb( VectorRegister v1, VectorRegister v3, int64_t d2, Register b2) {z_verll(v1, v3, d2, b2, VRET_BYTE);}// vector element type 'B' inline void Assembler::z_verllh( VectorRegister v1, VectorRegister v3, int64_t d2, Register b2) {z_verll(v1, v3, d2, b2, VRET_HW);} // vector element type 'H' inline void Assembler::z_verllf( VectorRegister v1, VectorRegister v3, int64_t d2, Register b2) {z_verll(v1, v3, d2, b2, VRET_FW);} // vector element type 'F' @@ -1188,12 +1200,41 @@ inline void Assembler::z_vistrbs(VectorRegister v1, VectorRegister v2) inline void Assembler::z_vistrhs(VectorRegister v1, VectorRegister v2) {z_vistr(v1, v2, VRET_HW, VOPRC_CCSET); } inline void Assembler::z_vistrfs(VectorRegister v1, VectorRegister v2) {z_vistr(v1, v2, VRET_FW, VOPRC_CCSET); } +//------------------------------- +// Vector FLOAT INSTRUCTIONS +//------------------------------- +// ADD +inline void Assembler::z_vfa( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VFA_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_FW, VRET_QW, 32)); } +inline void Assembler::z_vfasb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vfa(v1, v2, v3, VRET_FW); } // vector element type 'F' +inline void Assembler::z_vfadb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vfa(v1, v2, v3, VRET_DW); } // vector element type 'G' + +// SUB +inline void Assembler::z_vfs( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VFS_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_FW, VRET_QW, 32)); } +inline void Assembler::z_vfssb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vfs(v1, v2, v3, VRET_FW); } // vector element type 'F' +inline void Assembler::z_vfsdb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vfs(v1, v2, v3, VRET_DW); } // vector element type 'G' + +// MUL +inline void Assembler::z_vfm( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VFM_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_FW, VRET_QW, 32)); } +inline void Assembler::z_vfmsb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vfm(v1, v2, v3, VRET_FW); } // vector element type 'F' +inline void Assembler::z_vfmdb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vfm(v1, v2, v3, VRET_DW); } // vector element type 'G' + +// DIV +inline void Assembler::z_vfd( VectorRegister v1, VectorRegister v2, VectorRegister v3, int64_t m4) {emit_48(VFD_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vreg(v3, 16) | vesc_mask(m4, VRET_FW, VRET_QW, 32)); } +inline void Assembler::z_vfdsb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vfd(v1, v2, v3, VRET_FW); } // vector element type 'F' +inline void Assembler::z_vfddb( VectorRegister v1, VectorRegister v2, VectorRegister v3) {z_vfd(v1, v2, v3, VRET_DW); } // vector element type 'G' + +// square root +inline void Assembler::z_vfsq( VectorRegister v1, VectorRegister v2, int64_t m3) {emit_48(VFSQ_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vesc_mask(m3, VRET_FW, VRET_QW, 32)); } +inline void Assembler::z_vfsqsb( VectorRegister v1, VectorRegister v2) {z_vfsq(v1, v2, VRET_FW); } +inline void Assembler::z_vfsqdb( VectorRegister v1, VectorRegister v2) {z_vfsq(v1, v2, VRET_DW); } + +// vector fp load rounded +inline void Assembler::z_vflr( VectorRegister v1, VectorRegister v2, int64_t m5, int64_t m3) {emit_48(VFLR_ZOPC | vreg(v1, 8) | vreg(v2, 12) | vesc_mask(m5, VRET_FW, 7, 24) | vesc_mask(m3, VRET_FW, VRET_QW, 32)); } +inline void Assembler::z_vflrd( VectorRegister v1, VectorRegister v2, int64_t m5) {z_vflr(v1, v2, m5, VRET_DW); } //------------------------------- // FLOAT INSTRUCTIONS //------------------------------- - -//---------------- // LOAD //---------------- inline void Assembler::z_ler( FloatRegister r1, FloatRegister r2) { emit_16( LER_ZOPC | fregt(r1,8,16) | freg(r2,12,16)); } diff --git a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp index 378d5e4cfe1..c8393fe0e60 100644 --- a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp @@ -169,6 +169,7 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R #endif clear_reg(Z_R0); // make sure register is properly initialized. +#if 0 if (VM_Version::has_VectorFacility()) { const int min_vcnt = 32; // Minimum #characters required to use vector instructions. // Otherwise just do nothing in vector mode. @@ -223,6 +224,7 @@ unsigned int C2_MacroAssembler::string_compress(Register result, Register src, R bind(VectorDone); } +#endif { const int min_cnt = 8; // Minimum #characters required to use unrolled loop. @@ -461,6 +463,7 @@ unsigned int C2_MacroAssembler::string_inflate(Register src, Register dst, Regis #endif clear_reg(Z_R0); // make sure register is properly initialized. +#if 0 if (VM_Version::has_VectorFacility()) { const int min_vcnt = 32; // Minimum #characters required to use vector instructions. // Otherwise just do nothing in vector mode. @@ -489,6 +492,7 @@ unsigned int C2_MacroAssembler::string_inflate(Register src, Register dst, Regis bind(VectorDone); } +#endif const int min_cnt = 8; // Minimum #characters required to use unrolled scalar loop. // Otherwise just do nothing in unrolled scalar mode. @@ -623,6 +627,7 @@ unsigned int C2_MacroAssembler::string_inflate_const(Register src, Register dst, bool restore_inputs = false; bool workreg_clear = false; +#if 0 if ((len >= 32) && VM_Version::has_VectorFacility()) { const int min_vcnt = 32; // Minimum #characters required to use vector instructions. // Otherwise just do nothing in vector mode. @@ -678,6 +683,7 @@ unsigned int C2_MacroAssembler::string_inflate_const(Register src, Register dst, src_off += min_vcnt; dst_off += min_vcnt*2; } +#endif if ((len-nprocessed) > 8) { const int min_cnt = 8; // Minimum #characters required to use unrolled scalar loop. diff --git a/src/hotspot/cpu/s390/c2_globals_s390.hpp b/src/hotspot/cpu/s390/c2_globals_s390.hpp index 0192cb716ba..7f780ca63a0 100644 --- a/src/hotspot/cpu/s390/c2_globals_s390.hpp +++ b/src/hotspot/cpu/s390/c2_globals_s390.hpp @@ -60,7 +60,8 @@ define_pd_global(bool, UseCISCSpill, true); define_pd_global(bool, OptoBundling, false); define_pd_global(bool, OptoScheduling, false); define_pd_global(bool, OptoRegScheduling, false); -define_pd_global(bool, SuperWordLoopUnrollAnalysis, false); +define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); +define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); // On s390x, we can clear the array with a single instruction, // so don't idealize it. define_pd_global(bool, IdealizeClearArrayNode, false); diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp index d826b4a06f3..8ead8e8ff38 100644 --- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp @@ -218,10 +218,10 @@ SaveLiveRegisters::SaveLiveRegisters(MacroAssembler *masm, BarrierStubC2 *stub) const int register_save_size = iterate_over_register_mask(ACTION_COUNT_ONLY) * BytesPerWord; - _frame_size = align_up(register_save_size, frame::alignment_in_bytes) + frame::z_abi_160_size; // FIXME: this could be restricted to argument only + _frame_size = align_up(register_save_size, frame::alignment_in_bytes) + frame::z_abi_160_size; __ save_return_pc(); - __ push_frame(_frame_size, Z_R14); // FIXME: check if Z_R1_scaratch can do a job here; + __ push_frame(_frame_size, Z_R14); __ z_lg(Z_R14, _z_common_abi(return_pc) + _frame_size, Z_SP); @@ -240,6 +240,7 @@ int SaveLiveRegisters::iterate_over_register_mask(IterationAction action, int of int reg_save_index = 0; RegMaskIterator live_regs_iterator(_reg_mask); + // Going to preserve the volatile registers which can be used by Register Allocator. while(live_regs_iterator.has_next()) { const OptoReg::Name opto_reg = live_regs_iterator.next(); @@ -251,8 +252,11 @@ int SaveLiveRegisters::iterate_over_register_mask(IterationAction action, int of const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); if (vm_reg->is_Register()) { Register std_reg = vm_reg->as_Register(); - - if (std_reg->encoding() >= Z_R2->encoding() && std_reg->encoding() <= Z_R15->encoding()) { + // Z_R0 and Z_R1 will not be allocated by the register allocator, see s390.ad (Integer Register Classes) + // Z_R6 to Z_R15 are saved registers, except Z_R14 (see Z-Abi) + if (std_reg->encoding() == Z_R14->encoding() || + (std_reg->encoding() >= Z_R2->encoding() && + std_reg->encoding() <= Z_R5->encoding())) { reg_save_index++; if (action == ACTION_SAVE) { @@ -265,8 +269,10 @@ int SaveLiveRegisters::iterate_over_register_mask(IterationAction action, int of } } else if (vm_reg->is_FloatRegister()) { FloatRegister fp_reg = vm_reg->as_FloatRegister(); - if (fp_reg->encoding() >= Z_F0->encoding() && fp_reg->encoding() <= Z_F15->encoding() - && fp_reg->encoding() != Z_F1->encoding()) { + // Z_R1 will not be allocated by the register allocator, see s390.ad (Float Register Classes) + if (fp_reg->encoding() >= Z_F0->encoding() && + fp_reg->encoding() <= Z_F7->encoding() && + fp_reg->encoding() != Z_F1->encoding()) { reg_save_index++; if (action == ACTION_SAVE) { @@ -277,8 +283,20 @@ int SaveLiveRegisters::iterate_over_register_mask(IterationAction action, int of assert(action == ACTION_COUNT_ONLY, "Sanity"); } } - } else if (false /* vm_reg->is_VectorRegister() */){ - fatal("Vector register support is not there yet!"); + } else if (vm_reg->is_VectorRegister()) { + VectorRegister vs_reg = vm_reg->as_VectorRegister(); + // Z_V0 to Z_V15 will not be allocated by the register allocator, see s390.ad (reg class z_v_reg) + if (vs_reg->encoding() >= Z_V16->encoding() && + vs_reg->encoding() <= Z_V31->encoding()) { + reg_save_index += 2; + if (action == ACTION_SAVE) { + __ z_vst(vs_reg, Address(Z_SP, offset - reg_save_index * BytesPerWord)); + } else if (action == ACTION_RESTORE) { + __ z_vl(vs_reg, Address(Z_SP, offset - reg_save_index * BytesPerWord)); + } else { + assert(action == ACTION_COUNT_ONLY, "Sanity"); + } + } } else { fatal("Register type is not known"); } diff --git a/src/hotspot/cpu/s390/globals_s390.hpp b/src/hotspot/cpu/s390/globals_s390.hpp index fb5892ba62f..cf4be20397c 100644 --- a/src/hotspot/cpu/s390/globals_s390.hpp +++ b/src/hotspot/cpu/s390/globals_s390.hpp @@ -107,6 +107,11 @@ define_pd_global(intx, InitArrayShortSize, 1*BytesPerLong); /* Seems to pay off with 2 pages already. */ \ product(size_t, MVCLEThreshold, +2*(4*K), DIAGNOSTIC, \ "Threshold above which page-aligned MVCLE copy/init is used.") \ + /* special instructions */ \ + product(bool, SuperwordUseVX, false, \ + "Use Z15 Vector instructions for superword optimization.") \ + product(bool, UseSFPV, false, DIAGNOSTIC, \ + "Use SFPV Vector instructions for superword optimization.") \ \ product(bool, PreferLAoverADD, false, DIAGNOSTIC, \ "Use LA/LAY instructions over ADD instructions (z/Architecture).") \ diff --git a/src/hotspot/cpu/s390/registerSaver_s390.hpp b/src/hotspot/cpu/s390/registerSaver_s390.hpp index 97883685384..13674f1562d 100644 --- a/src/hotspot/cpu/s390/registerSaver_s390.hpp +++ b/src/hotspot/cpu/s390/registerSaver_s390.hpp @@ -47,10 +47,11 @@ class RegisterSaver { // Boolean flags to force only argument registers to be saved. static int live_reg_save_size(RegisterSet reg_set); - static int live_reg_frame_size(RegisterSet reg_set); + static int live_reg_frame_size(RegisterSet reg_set, bool save_vectors = false); + static int calculate_vregstosave_num(); // Specify the register that should be stored as the return pc in the current frame. - static OopMap* save_live_registers(MacroAssembler* masm, RegisterSet reg_set, Register return_pc = Z_R14); - static void restore_live_registers(MacroAssembler* masm, RegisterSet reg_set); + static OopMap* save_live_registers(MacroAssembler* masm, RegisterSet reg_set, Register return_pc = Z_R14, bool save_vectors = false); + static void restore_live_registers(MacroAssembler* masm, RegisterSet reg_set, bool save_vectors = false); // Generate the OopMap (again, regs where saved before). static OopMap* generate_oop_map(MacroAssembler* masm, RegisterSet reg_set); @@ -65,11 +66,13 @@ class RegisterSaver { int_reg = 0, float_reg = 1, excluded_reg = 2, // Not saved/restored. + v_reg = 3 } RegisterType; typedef enum { reg_size = 8, half_reg_size = reg_size / 2, + v_reg_size = 16 } RegisterConstants; // Remember type, number, and VMReg. diff --git a/src/hotspot/cpu/s390/register_s390.cpp b/src/hotspot/cpu/s390/register_s390.cpp index f055a1c0134..c0840add5d6 100644 --- a/src/hotspot/cpu/s390/register_s390.cpp +++ b/src/hotspot/cpu/s390/register_s390.cpp @@ -26,11 +26,6 @@ #include "precompiled.hpp" #include "register_s390.hpp" - -const int ConcreteRegisterImpl::max_gpr = Register::number_of_registers * 2; -const int ConcreteRegisterImpl::max_fpr = ConcreteRegisterImpl::max_gpr + - FloatRegister::number_of_registers * 2; - const char* Register::name() const { const char* names[number_of_registers] = { "Z_R0", "Z_R1", "Z_R2", "Z_R3", "Z_R4", "Z_R5", "Z_R6", "Z_R7", @@ -54,5 +49,11 @@ const char* VectorRegister::name() const { "Z_V16", "Z_V17", "Z_V18", "Z_V19", "Z_V20", "Z_V21", "Z_V22", "Z_V23", "Z_V24", "Z_V25", "Z_V26", "Z_V27", "Z_V28", "Z_V29", "Z_V30", "Z_V31" }; - return is_valid() ? names[encoding()] : "fnoreg"; + return is_valid() ? names[encoding()] : "vnoreg"; +} + +// Method to convert a FloatRegister to a VectorRegister (VectorRegister) +VectorRegister FloatRegister::to_vr() const { + if (*this == fnoreg) { return vnoreg; } + return as_VectorRegister(encoding()); } diff --git a/src/hotspot/cpu/s390/register_s390.hpp b/src/hotspot/cpu/s390/register_s390.hpp index 18af232e569..6fcba746cd3 100644 --- a/src/hotspot/cpu/s390/register_s390.hpp +++ b/src/hotspot/cpu/s390/register_s390.hpp @@ -64,6 +64,7 @@ class Register { public: enum { number_of_registers = 16, + max_slots_per_register = 2, number_of_arg_registers = 5 }; @@ -164,12 +165,13 @@ constexpr ConditionRegister Z_CR = as_ConditionRegister(0); //========================= // The implementation of float registers for the z/Architecture. - +class VectorRegister; class FloatRegister { int _encoding; public: enum { number_of_registers = 16, + max_slots_per_register = 2, number_of_arg_registers = 4 }; @@ -192,6 +194,8 @@ class FloatRegister { constexpr bool is_nonvolatile() const { return (8 <= _encoding && _encoding <= 15); } const char* name() const; + // convert to VR + VectorRegister to_vr() const; }; inline constexpr FloatRegister as_FloatRegister(int encoding) { @@ -285,6 +289,7 @@ class VectorRegister { public: enum { number_of_registers = 32, + max_slots_per_register = 4, number_of_arg_registers = 0 }; @@ -379,21 +384,20 @@ constexpr VectorRegister Z_V31 = as_VectorRegister(31); // Need to know the total number of registers of all sorts for SharedInfo. // Define a class that exports it. - class ConcreteRegisterImpl : public AbstractRegisterImpl { public: enum { - number_of_registers = - (Register::number_of_registers + - FloatRegister::number_of_registers) - * 2 // register halves - + 1 // condition code register + max_gpr = Register::number_of_registers * Register::max_slots_per_register, + max_fpr = max_gpr + FloatRegister::number_of_registers * FloatRegister::max_slots_per_register, + max_vr = max_fpr + VectorRegister::number_of_registers * VectorRegister::max_slots_per_register, + // A big enough number for C2: all the registers plus flags + // This number must be large enough to cover REG_COUNT (defined by c2) registers. + // There is no requirement that any ordering here matches any ordering c2 gives + // it's optoregs. + number_of_registers = max_vr + 1 // gpr/fpr/vr + flags }; - static const int max_gpr; - static const int max_fpr; }; - // Common register declarations used in assembler code. constexpr Register Z_EXC_OOP = Z_R2; constexpr Register Z_EXC_PC = Z_R3; diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 63e150c9e9c..e1a98139992 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -97,8 +97,9 @@ register %{ // e.g. Z_R3_H, which is needed by the allocator, but is not used // for stores, loads, etc. - // Integer/Long Registers - // ---------------------------- +// ---------------------------- +// Integer/Long Registers +// ---------------------------- // z/Architecture has 16 64-bit integer registers. @@ -136,7 +137,9 @@ register %{ reg_def Z_R15 (NS, NS, Op_RegI, 15, Z_R15->as_VMReg()); // s SP reg_def Z_R15_H(NS, NS, Op_RegI, 99, Z_R15->as_VMReg()->next()); - // Float/Double Registers +// ---------------------------- +// Float/Double Registers +// ---------------------------- // The rules of ADL require that double registers be defined in pairs. // Each pair must be two 32-bit values, but not necessarily a pair of @@ -182,7 +185,169 @@ register %{ reg_def Z_F15 (SOC, SOE, Op_RegF, 15, Z_F15->as_VMReg()); reg_def Z_F15_H(SOC, SOE, Op_RegF, 99, Z_F15->as_VMReg()->next()); - +// ---------------------------- +// Vector Registers +// ---------------------------- + // 1st 16 VRs are aliases for the FPRs which are already defined above. + reg_def Z_VR0 ( SOC, SOC, Op_RegF, 0, VMRegImpl::Bad()); + reg_def Z_VR0_H ( SOC, SOC, Op_RegF, 0, VMRegImpl::Bad()); + reg_def Z_VR0_J ( SOC, SOC, Op_RegF, 0, VMRegImpl::Bad()); + reg_def Z_VR0_K ( SOC, SOC, Op_RegF, 0, VMRegImpl::Bad()); + + reg_def Z_VR1 ( SOC, SOC, Op_RegF, 1, VMRegImpl::Bad()); + reg_def Z_VR1_H ( SOC, SOC, Op_RegF, 1, VMRegImpl::Bad()); + reg_def Z_VR1_J ( SOC, SOC, Op_RegF, 1, VMRegImpl::Bad()); + reg_def Z_VR1_K ( SOC, SOC, Op_RegF, 1, VMRegImpl::Bad()); + + reg_def Z_VR2 ( SOC, SOC, Op_RegF, 2, VMRegImpl::Bad()); + reg_def Z_VR2_H ( SOC, SOC, Op_RegF, 2, VMRegImpl::Bad()); + reg_def Z_VR2_J ( SOC, SOC, Op_RegF, 2, VMRegImpl::Bad()); + reg_def Z_VR2_K ( SOC, SOC, Op_RegF, 2, VMRegImpl::Bad()); + + reg_def Z_VR3 ( SOC, SOC, Op_RegF, 3, VMRegImpl::Bad()); + reg_def Z_VR3_H ( SOC, SOC, Op_RegF, 3, VMRegImpl::Bad()); + reg_def Z_VR3_J ( SOC, SOC, Op_RegF, 3, VMRegImpl::Bad()); + reg_def Z_VR3_K ( SOC, SOC, Op_RegF, 3, VMRegImpl::Bad()); + + reg_def Z_VR4 ( SOC, SOC, Op_RegF, 4, VMRegImpl::Bad()); + reg_def Z_VR4_H ( SOC, SOC, Op_RegF, 4, VMRegImpl::Bad()); + reg_def Z_VR4_J ( SOC, SOC, Op_RegF, 4, VMRegImpl::Bad()); + reg_def Z_VR4_K ( SOC, SOC, Op_RegF, 4, VMRegImpl::Bad()); + + reg_def Z_VR5 ( SOC, SOC, Op_RegF, 5, VMRegImpl::Bad()); + reg_def Z_VR5_H ( SOC, SOC, Op_RegF, 5, VMRegImpl::Bad()); + reg_def Z_VR5_J ( SOC, SOC, Op_RegF, 5, VMRegImpl::Bad()); + reg_def Z_VR5_K ( SOC, SOC, Op_RegF, 5, VMRegImpl::Bad()); + + reg_def Z_VR6 ( SOC, SOC, Op_RegF, 6, VMRegImpl::Bad()); + reg_def Z_VR6_H ( SOC, SOC, Op_RegF, 6, VMRegImpl::Bad()); + reg_def Z_VR6_J ( SOC, SOC, Op_RegF, 6, VMRegImpl::Bad()); + reg_def Z_VR6_K ( SOC, SOC, Op_RegF, 6, VMRegImpl::Bad()); + + reg_def Z_VR7 ( SOC, SOC, Op_RegF, 7, VMRegImpl::Bad()); + reg_def Z_VR7_H ( SOC, SOC, Op_RegF, 7, VMRegImpl::Bad()); + reg_def Z_VR7_J ( SOC, SOC, Op_RegF, 7, VMRegImpl::Bad()); + reg_def Z_VR7_K ( SOC, SOC, Op_RegF, 7, VMRegImpl::Bad()); + + reg_def Z_VR8 ( SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); + reg_def Z_VR8_H ( SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); + reg_def Z_VR8_J ( SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); + reg_def Z_VR8_K ( SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); + + reg_def Z_VR9 ( SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); + reg_def Z_VR9_H ( SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); + reg_def Z_VR9_J ( SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); + reg_def Z_VR9_K ( SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); + + reg_def Z_VR10 ( SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); + reg_def Z_VR10_H ( SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); + reg_def Z_VR10_J ( SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); + reg_def Z_VR10_K ( SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); + + reg_def Z_VR11 ( SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); + reg_def Z_VR11_H ( SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); + reg_def Z_VR11_J ( SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); + reg_def Z_VR11_K ( SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); + + reg_def Z_VR12 ( SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); + reg_def Z_VR12_H ( SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); + reg_def Z_VR12_J ( SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); + reg_def Z_VR12_K ( SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); + + reg_def Z_VR13 ( SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); + reg_def Z_VR13_H ( SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); + reg_def Z_VR13_J ( SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); + reg_def Z_VR13_K ( SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); + + reg_def Z_VR14 ( SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); + reg_def Z_VR14_H ( SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); + reg_def Z_VR14_J ( SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); + reg_def Z_VR14_K ( SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); + + reg_def Z_VR15 ( SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); + reg_def Z_VR15_H ( SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); + reg_def Z_VR15_J ( SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); + reg_def Z_VR15_K ( SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); + + reg_def Z_VR16 ( SOC, SOC, Op_RegF, 16, Z_V16->as_VMReg() ); + reg_def Z_VR16_H ( SOC, SOC, Op_RegF, 16, Z_V16->as_VMReg()->next() ); + reg_def Z_VR16_J ( SOC, SOC, Op_RegF, 16, Z_V16->as_VMReg()->next(2) ); + reg_def Z_VR16_K ( SOC, SOC, Op_RegF, 16, Z_V16->as_VMReg()->next(3) ); + + reg_def Z_VR17 ( SOC, SOC, Op_RegF, 17, Z_V17->as_VMReg() ); + reg_def Z_VR17_H ( SOC, SOC, Op_RegF, 17, Z_V17->as_VMReg()->next() ); + reg_def Z_VR17_J ( SOC, SOC, Op_RegF, 17, Z_V17->as_VMReg()->next(2) ); + reg_def Z_VR17_K ( SOC, SOC, Op_RegF, 17, Z_V17->as_VMReg()->next(3) ); + + reg_def Z_VR18 ( SOC, SOC, Op_RegF, 18, Z_V18->as_VMReg() ); + reg_def Z_VR18_H ( SOC, SOC, Op_RegF, 18, Z_V18->as_VMReg()->next() ); + reg_def Z_VR18_J ( SOC, SOC, Op_RegF, 18, Z_V18->as_VMReg()->next(2) ); + reg_def Z_VR18_K ( SOC, SOC, Op_RegF, 18, Z_V18->as_VMReg()->next(3) ); + + reg_def Z_VR19 ( SOC, SOC, Op_RegF, 19, Z_V19->as_VMReg() ); + reg_def Z_VR19_H ( SOC, SOC, Op_RegF, 19, Z_V19->as_VMReg()->next() ); + reg_def Z_VR19_J ( SOC, SOC, Op_RegF, 19, Z_V19->as_VMReg()->next(2) ); + reg_def Z_VR19_K ( SOC, SOC, Op_RegF, 19, Z_V19->as_VMReg()->next(3) ); + + reg_def Z_VR20 ( SOC, SOC, Op_RegF, 20, Z_V20->as_VMReg() ); + reg_def Z_VR20_H ( SOC, SOC, Op_RegF, 20, Z_V20->as_VMReg()->next() ); + reg_def Z_VR20_J ( SOC, SOC, Op_RegF, 20, Z_V20->as_VMReg()->next(2) ); + reg_def Z_VR20_K ( SOC, SOC, Op_RegF, 20, Z_V20->as_VMReg()->next(3) ); + + reg_def Z_VR21 ( SOC, SOC, Op_RegF, 21, Z_V21->as_VMReg() ); + reg_def Z_VR21_H ( SOC, SOC, Op_RegF, 21, Z_V21->as_VMReg()->next() ); + reg_def Z_VR21_J ( SOC, SOC, Op_RegF, 21, Z_V21->as_VMReg()->next(2) ); + reg_def Z_VR21_K ( SOC, SOC, Op_RegF, 21, Z_V21->as_VMReg()->next(3) ); + + reg_def Z_VR22 ( SOC, SOC, Op_RegF, 22, Z_V22->as_VMReg() ); + reg_def Z_VR22_H ( SOC, SOC, Op_RegF, 22, Z_V22->as_VMReg()->next() ); + reg_def Z_VR22_J ( SOC, SOC, Op_RegF, 22, Z_V22->as_VMReg()->next(2) ); + reg_def Z_VR22_K ( SOC, SOC, Op_RegF, 22, Z_V22->as_VMReg()->next(3) ); + + reg_def Z_VR23 ( SOC, SOC, Op_RegF, 23, Z_V23->as_VMReg() ); + reg_def Z_VR23_H ( SOC, SOC, Op_RegF, 23, Z_V23->as_VMReg()->next() ); + reg_def Z_VR23_J ( SOC, SOC, Op_RegF, 23, Z_V23->as_VMReg()->next(2) ); + reg_def Z_VR23_K ( SOC, SOC, Op_RegF, 23, Z_V23->as_VMReg()->next(3) ); + + reg_def Z_VR24 ( SOC, SOC, Op_RegF, 24, Z_V24->as_VMReg() ); + reg_def Z_VR24_H ( SOC, SOC, Op_RegF, 24, Z_V24->as_VMReg()->next() ); + reg_def Z_VR24_J ( SOC, SOC, Op_RegF, 24, Z_V24->as_VMReg()->next(2) ); + reg_def Z_VR24_K ( SOC, SOC, Op_RegF, 24, Z_V24->as_VMReg()->next(3) ); + + reg_def Z_VR25 ( SOC, SOC, Op_RegF, 25, Z_V25->as_VMReg() ); + reg_def Z_VR25_H ( SOC, SOC, Op_RegF, 25, Z_V25->as_VMReg()->next() ); + reg_def Z_VR25_J ( SOC, SOC, Op_RegF, 25, Z_V25->as_VMReg()->next(2) ); + reg_def Z_VR25_K ( SOC, SOC, Op_RegF, 25, Z_V25->as_VMReg()->next(3) ); + + reg_def Z_VR26 ( SOC, SOC, Op_RegF, 26, Z_V26->as_VMReg() ); + reg_def Z_VR26_H ( SOC, SOC, Op_RegF, 26, Z_V26->as_VMReg()->next() ); + reg_def Z_VR26_J ( SOC, SOC, Op_RegF, 26, Z_V26->as_VMReg()->next(2) ); + reg_def Z_VR26_K ( SOC, SOC, Op_RegF, 26, Z_V26->as_VMReg()->next(3) ); + + reg_def Z_VR27 ( SOC, SOC, Op_RegF, 27, Z_V27->as_VMReg() ); + reg_def Z_VR27_H ( SOC, SOC, Op_RegF, 27, Z_V27->as_VMReg()->next() ); + reg_def Z_VR27_J ( SOC, SOC, Op_RegF, 27, Z_V27->as_VMReg()->next(2) ); + reg_def Z_VR27_K ( SOC, SOC, Op_RegF, 27, Z_V27->as_VMReg()->next(3) ); + + reg_def Z_VR28 ( SOC, SOC, Op_RegF, 28, Z_V28->as_VMReg() ); + reg_def Z_VR28_H ( SOC, SOC, Op_RegF, 28, Z_V28->as_VMReg()->next() ); + reg_def Z_VR28_J ( SOC, SOC, Op_RegF, 28, Z_V28->as_VMReg()->next(2) ); + reg_def Z_VR28_K ( SOC, SOC, Op_RegF, 28, Z_V28->as_VMReg()->next(3) ); + + reg_def Z_VR29 ( SOC, SOC, Op_RegF, 29, Z_V29->as_VMReg() ); + reg_def Z_VR29_H ( SOC, SOC, Op_RegF, 29, Z_V29->as_VMReg()->next() ); + reg_def Z_VR29_J ( SOC, SOC, Op_RegF, 29, Z_V29->as_VMReg()->next(2) ); + reg_def Z_VR29_K ( SOC, SOC, Op_RegF, 29, Z_V29->as_VMReg()->next(3) ); + + reg_def Z_VR30 ( SOC, SOC, Op_RegF, 30, Z_V30->as_VMReg() ); + reg_def Z_VR30_H ( SOC, SOC, Op_RegF, 30, Z_V30->as_VMReg()->next() ); + reg_def Z_VR30_J ( SOC, SOC, Op_RegF, 30, Z_V30->as_VMReg()->next(2) ); + reg_def Z_VR30_K ( SOC, SOC, Op_RegF, 30, Z_V30->as_VMReg()->next(3) ); + + reg_def Z_VR31 ( SOC, SOC, Op_RegF, 31, Z_V31->as_VMReg() ); + reg_def Z_VR31_H ( SOC, SOC, Op_RegF, 31, Z_V31->as_VMReg()->next() ); + reg_def Z_VR31_J ( SOC, SOC, Op_RegF, 31, Z_V31->as_VMReg()->next(2) ); + reg_def Z_VR31_K ( SOC, SOC, Op_RegF, 31, Z_V31->as_VMReg()->next(3) ); // Special Registers // Condition Codes Flag Registers @@ -194,7 +359,6 @@ register %{ reg_def Z_CR(SOC, SOC, Op_RegFlags, 0, Z_CR->as_VMReg()); // volatile - // Specify priority of register selection within phases of register // allocation. Highest priority is first. A useful heuristic is to // give registers a low priority when they are required by machine @@ -268,6 +432,41 @@ alloc_class chunk1( ); alloc_class chunk2( + Z_VR0, Z_VR0_H, Z_VR0_J, Z_VR0_K, + Z_VR1, Z_VR1_H, Z_VR1_J, Z_VR1_K, + Z_VR2, Z_VR2_H, Z_VR2_J, Z_VR2_K, + Z_VR3, Z_VR3_H, Z_VR3_J, Z_VR3_K, + Z_VR4, Z_VR4_H, Z_VR4_J, Z_VR4_K, + Z_VR5, Z_VR5_H, Z_VR5_J, Z_VR5_K, + Z_VR6, Z_VR6_H, Z_VR6_J, Z_VR6_K, + Z_VR7, Z_VR7_H, Z_VR7_J, Z_VR7_K, + Z_VR8, Z_VR8_H, Z_VR8_J, Z_VR8_K, + Z_VR9, Z_VR9_H, Z_VR9_J, Z_VR9_K, + Z_VR10, Z_VR10_H, Z_VR10_J, Z_VR10_K, + Z_VR11, Z_VR11_H, Z_VR11_J, Z_VR11_K, + Z_VR12, Z_VR12_H, Z_VR12_J, Z_VR12_K, + Z_VR13, Z_VR13_H, Z_VR13_J, Z_VR13_K, + Z_VR14, Z_VR14_H, Z_VR14_J, Z_VR14_K, + Z_VR15, Z_VR15_H, Z_VR15_J, Z_VR15_K, + Z_VR16, Z_VR16_H, Z_VR16_J, Z_VR16_K, + Z_VR17, Z_VR17_H, Z_VR17_J, Z_VR17_K, + Z_VR18, Z_VR18_H, Z_VR18_J, Z_VR18_K, + Z_VR19, Z_VR19_H, Z_VR19_J, Z_VR19_K, + Z_VR20, Z_VR20_H, Z_VR20_J, Z_VR20_K, + Z_VR21, Z_VR21_H, Z_VR21_J, Z_VR21_K, + Z_VR22, Z_VR22_H, Z_VR22_J, Z_VR22_K, + Z_VR23, Z_VR23_H, Z_VR23_J, Z_VR23_K, + Z_VR24, Z_VR24_H, Z_VR24_J, Z_VR24_K, + Z_VR25, Z_VR25_H, Z_VR25_J, Z_VR25_K, + Z_VR26, Z_VR26_H, Z_VR26_J, Z_VR26_K, + Z_VR27, Z_VR27_H, Z_VR27_J, Z_VR27_K, + Z_VR28, Z_VR28_H, Z_VR28_J, Z_VR28_K, + Z_VR29, Z_VR29_H, Z_VR29_J, Z_VR29_K, + Z_VR30, Z_VR30_H, Z_VR30_J, Z_VR30_K, + Z_VR31, Z_VR31_H, Z_VR31_J, Z_VR31_K +); + +alloc_class chunk3( Z_CR ); @@ -542,6 +741,27 @@ reg_class z_dbl_reg( ); reg_class z_rscratch1_dbl_reg(Z_F1,Z_F1_H); +reg_class z_v_reg( + // Attention: Only these ones are saved & restored at safepoint by RegisterSaver. + //1st 16 VRs overlaps with 1st 16 FPRs. + Z_VR16, Z_VR16_H, Z_VR16_J, Z_VR16_K, + Z_VR17, Z_VR17_H, Z_VR17_J, Z_VR17_K, + Z_VR18, Z_VR18_H, Z_VR18_J, Z_VR18_K, + Z_VR19, Z_VR19_H, Z_VR19_J, Z_VR19_K, + Z_VR20, Z_VR20_H, Z_VR20_J, Z_VR20_K, + Z_VR21, Z_VR21_H, Z_VR21_J, Z_VR21_K, + Z_VR22, Z_VR22_H, Z_VR22_J, Z_VR22_K, + Z_VR23, Z_VR23_H, Z_VR23_J, Z_VR23_K, + Z_VR24, Z_VR24_H, Z_VR24_J, Z_VR24_K, + Z_VR25, Z_VR25_H, Z_VR25_J, Z_VR25_K, + Z_VR26, Z_VR26_H, Z_VR26_J, Z_VR26_K, + Z_VR27, Z_VR27_H, Z_VR27_J, Z_VR27_K, + Z_VR28, Z_VR28_H, Z_VR28_J, Z_VR28_K, + Z_VR29, Z_VR29_H, Z_VR29_J, Z_VR29_K, + Z_VR30, Z_VR30_H, Z_VR30_J, Z_VR30_K, + Z_VR31, Z_VR31_H, Z_VR31_J, Z_VR31_K +); + %} //----------DEFINITION BLOCK--------------------------------------------------- @@ -953,8 +1173,8 @@ const Pipeline * MachEpilogNode::pipeline() const { //============================================================================= -// Figure out which register class each belongs in: rc_int, rc_float, rc_stack. -enum RC { rc_bad, rc_int, rc_float, rc_stack }; +// Figure out which register class each belongs in: rc_int, rc_float, rc_vector, rc_stack. +enum RC { rc_bad, rc_int, rc_float, rc_vector, rc_stack }; static enum RC rc_class(OptoReg::Name reg) { // Return the register class for the given register. The given register @@ -975,8 +1195,13 @@ static enum RC rc_class(OptoReg::Name reg) { return rc_float; } + // we have 128 vector register halves at index 64 + if (reg < 32+32+128) { + return rc_vector; + } + // Between float regs & stack are the flags regs. - assert(reg >= OptoReg::stack0(), "blow up if spilling flags"); + assert(OptoReg::is_stack(reg) || reg < 32+32+128, "blow up if spilling flags"); return rc_stack; } @@ -1035,7 +1260,7 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r "expected aligned-adjacent pairs"); // Generate spill code! - + int size = 0; if (src_lo == dst_lo && src_hi == dst_hi) { return 0; // Self copy, no move. } @@ -1049,6 +1274,37 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r const char *mnemo = nullptr; unsigned long opc = 0; + if (bottom_type()->isa_vect() != nullptr && ideal_reg() == Op_VecX) { + if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { + if (masm != nullptr) { + __ z_mvc(Address(Z_SP, 0, dst_offset), Address(Z_SP, 0, src_offset), 16); + } + size += 6; + } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_stack) { + VectorRegister Rsrc = as_VectorRegister(Matcher::_regEncode[src_lo]); + if (masm != nullptr) { + __ z_vst(Rsrc, Address(Z_SP, 0, dst_offset)); + } + size += 6; + } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vector) { + VectorRegister Rdst = as_VectorRegister(Matcher::_regEncode[dst_lo]); + if (masm != nullptr) { + __ z_vl(Rdst, Address(Z_SP, 0, src_offset)); + } + size += 6; + } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) { + VectorRegister Rsrc = as_VectorRegister(Matcher::_regEncode[src_lo]); + VectorRegister Rdst = as_VectorRegister(Matcher::_regEncode[dst_lo]); + if (masm != nullptr) { + __ z_vlr(Rdst, Rsrc); + } + size += 6; + } else { + ShouldNotReachHere(); + } + return size; + } + // Memory->Memory Spill. Use Z_R0 to hold the value. if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { @@ -1283,7 +1539,7 @@ source_hpp %{ // // To keep related declarations/definitions/uses close together, // we switch between source %{ }% and source_hpp %{ }% freely as needed. - +#include "opto/convertnode.hpp" #include "oops/klass.inline.hpp" //-------------------------------------------------------------- @@ -1446,6 +1702,32 @@ bool Matcher::match_rule_supported(int opcode) { case Op_PopCountL: // PopCount supported by H/W from z/Architecture G5 (z196) on. return (UsePopCountInstruction && VM_Version::has_PopCount()); + case Op_AddVB: + case Op_AddVS: + case Op_AddVI: + case Op_AddVL: + case Op_AddVD: + case Op_SubVB: + case Op_SubVS: + case Op_SubVI: + case Op_SubVL: + case Op_SubVD: + case Op_MulVB: + case Op_MulVS: + case Op_MulVI: + case Op_MulVD: + case Op_DivVD: + case Op_SqrtVD: + case Op_RoundDoubleModeV: + return SuperwordUseVX; + case Op_AddVF: + case Op_SubVF: + case Op_MulVF: + case Op_DivVF: + case Op_SqrtVF: + //PopCountVI supported by z14 onwards. + case Op_PopCountVI: + return (SuperwordUseVX && UseSFPV); case Op_FmaF: case Op_FmaD: return UseFMA; @@ -1491,14 +1773,24 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) { // Vector width in bytes. int Matcher::vector_width_in_bytes(BasicType bt) { - assert(MaxVectorSize == 8, ""); - return 8; + if (SuperwordUseVX) { + assert(MaxVectorSize == 16, ""); + return 16; + } else { + assert(MaxVectorSize == 8, ""); + return 8; + } } // Vector ideal reg. uint Matcher::vector_ideal_reg(int size) { - assert(MaxVectorSize == 8 && size == 8, ""); - return Op_RegL; + if (SuperwordUseVX) { + assert(MaxVectorSize == 16 && size == 16, ""); + return Op_VecX; + } else { + assert(MaxVectorSize == 8 && size == 8, ""); + return Op_RegL; + } } // Limits on vector size (number of elements) loaded into vector. @@ -2391,6 +2683,14 @@ ins_attrib ins_should_rematerialize(false); // Immediate Operands // Please note: // Formats are generated automatically for constants and base registers. +operand vecX() %{ + constraint(ALLOC_IN_RC(z_v_reg)); + match(VecX); + + format %{ %} + interface(REG_INTER); +%} + //---------------------------------------------- // SIGNED (shorter than INT) immediate operands @@ -10534,6 +10834,45 @@ instruct Repl4S_immm1(iRegL dst, immS_minus1 src) %{ ins_pipe(pipe_class_dummy); %} +instruct repl8S_reg_Ex(vecX dst, iRegI src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 8 && + Matcher::vector_element_basic_type(n) == T_SHORT); + + size(12); + ins_encode %{ + __ z_vlvgh($dst$$VectorRegister, $src$$Register, 0); + __ z_vreph($dst$$VectorRegister, $dst$$VectorRegister, 0); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl8S_immIminus1(vecX dst, immI_minus1 src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 8 && + Matcher::vector_element_basic_type(n) == T_SHORT); + + format %{ "VONE $dst, $src \t// replicate8S" %} + size(6); + ins_encode %{ + __ z_vone($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl8S_immI0(vecX dst, immI_0 zero) %{ + match(Set dst (Replicate zero)); + predicate(n->as_Vector()->length() == 8 && + Matcher::vector_element_basic_type(n) == T_SHORT); + + format %{ "VZERO $dst, $zero \t// replicate8S" %} + size(6); + ins_encode %{ + __ z_vzero($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + // Exploit rotate_then_insert, if available. // Replicate scalar int to packed int values (8 Bytes). instruct Repl2I_reg_risbg(iRegL dst, iRegI src, flagsReg cr) %{ @@ -10586,7 +10925,44 @@ instruct Repl2I_immm1(iRegL dst, immI_minus1 src) %{ ins_pipe(pipe_class_dummy); %} -// +instruct repl4I_reg_Ex(vecX dst, iRegI src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 4 && + Matcher::vector_element_basic_type(n) == T_INT); + + size(12); + ins_encode %{ + __ z_vlvgf($dst$$VectorRegister, $src$$Register, 0); + __ z_vrepf($dst$$VectorRegister, $dst$$VectorRegister, 0); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl4I_immI0(vecX dst, immI_0 zero) %{ + match(Set dst (Replicate zero)); + predicate(n->as_Vector()->length() == 4 && + Matcher::vector_element_basic_type(n) == T_INT); + + format %{ "VZERO $dst, $zero \t// replicate4I" %} + size(6); + ins_encode %{ + __ z_vzero($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl4I_immIminus1(vecX dst, immI_minus1 src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 4 && + Matcher::vector_element_basic_type(n) == T_INT); + + format %{ "VONE $dst, $dst, $dst \t// replicate4I" %} + size(6); + ins_encode %{ + __ z_vone($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} instruct Repl2F_reg_indirect(iRegL dst, regF src, flagsReg cr) %{ match(Set dst (Replicate src)); @@ -10650,6 +11026,139 @@ instruct Repl2F_imm0(iRegL dst, immFp0 src) %{ ins_pipe(pipe_class_dummy); %} +instruct repl4F_reg_Ex(vecX dst, regF src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 4 && + Matcher::vector_element_basic_type(n) == T_FLOAT); + + format %{ "VREP $dst, $src \t// replicate4F" %} + size(6); + + ins_encode %{ + __ z_vrepf($dst$$VectorRegister, $src$$FloatRegister->to_vr(), 0); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl4F_immF0(vecX dst, immFp0 zero) %{ + match(Set dst (Replicate zero)); + predicate(n->as_Vector()->length() == 4 && + Matcher::vector_element_basic_type(n) == T_FLOAT); + + format %{ "VZERO $dst, $zero \t// replicate4F" %} + size(6); + ins_encode %{ + __ z_vzero($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl2D_reg_Ex(vecX dst, regD src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 2 && + Matcher::vector_element_basic_type(n) == T_DOUBLE); + + format %{ "VREP $dst, $src \t// replicate2D" %} + size(6); + + ins_encode %{ + __ z_vrepg($dst$$VectorRegister, $src$$FloatRegister->to_vr(), 0); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl2D_immD0(vecX dst, immDp0 zero) %{ + match(Set dst (Replicate zero)); + predicate(n->as_Vector()->length() == 2 && + Matcher::vector_element_basic_type(n) == T_DOUBLE); + + format %{ "VZERO $dst, $zero \t// replicate2D" %} + size(6); + ins_encode %{ + __ z_vzero($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl16B_reg_Ex(vecX dst, iRegI src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 16 && + Matcher::vector_element_basic_type(n) == T_BYTE); + + size(12); + ins_encode %{ + __ z_vlvgb($dst$$VectorRegister, $src$$Register, 0); + __ z_vrepb($dst$$VectorRegister, $dst$$VectorRegister, 0); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl16B_immIminus1(vecX dst, immI_minus1 src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 16 && + Matcher::vector_element_basic_type(n) == T_BYTE); + + format %{ "VONE $dst, $src \t// replicate16B" %} + size(6); + ins_encode %{ + __ z_vone($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl16B_immI0(vecX dst, immI_0 zero) %{ + match(Set dst (Replicate zero)); + predicate(n->as_Vector()->length() == 16 && + Matcher::vector_element_basic_type(n) == T_BYTE); + + format %{ "VZERO $dst, $zero \t// replicate16B" %} + size(6); + ins_encode %{ + __ z_vzero($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl2L_reg_Ex(vecX dst, iRegL src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 2 && + Matcher::vector_element_basic_type(n) == T_LONG); + + size(12); + ins_encode %{ + __ z_vlvgg($dst$$VectorRegister, $src$$Register, 0); + __ z_vrepg($dst$$VectorRegister, $dst$$VectorRegister, 0); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl2L_immIminus1(vecX dst, immI_minus1 src) %{ + match(Set dst (Replicate src)); + predicate(n->as_Vector()->length() == 2 && + Matcher::vector_element_basic_type(n) == T_LONG); + + format %{ "VONE $dst, $src \t// replicate2L" %} + size(6); + ins_encode %{ + __ z_vone($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct repl2L_immI0(vecX dst, immI_0 zero) %{ + match(Set dst (Replicate zero)); + predicate(n->as_Vector()->length() == 2 && + Matcher::vector_element_basic_type(n) == T_LONG); + + format %{ "VZERO $dst, $zero \t// replicate16B" %} + size(6); + ins_encode %{ + __ z_vzero($dst$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + + // Load/Store vector // Store Aligned Packed Byte register to memory (8 Bytes). @@ -10664,6 +11173,21 @@ instruct storeA8B(memory mem, iRegL src) %{ ins_pipe(pipe_class_dummy); %} +// Store Packed Byte long register to memory +instruct storeV16(memoryRX mem, vecX src) %{ + predicate(n->as_StoreVector()->memory_size() == 16); + match(Set mem (StoreVector mem src)); + ins_cost(MEMORY_REF_COST); + + format %{ "VST $mem, $src \t// store 16-byte Vector" %} + size(6); + ins_encode %{ + __ z_vst($src$$VectorRegister, + Address(reg_to_register_object($mem$$base), $mem$$index$$Register, $mem$$disp)); + %} + ins_pipe(pipe_class_dummy); +%} + instruct loadV8(iRegL dst, memory mem) %{ match(Set dst (LoadVector mem)); predicate(n->as_LoadVector()->memory_size() == 8); @@ -10675,6 +11199,21 @@ instruct loadV8(iRegL dst, memory mem) %{ ins_pipe(pipe_class_dummy); %} +// Load Aligned Packed Byte +instruct loadV16(vecX dst, memoryRX mem) %{ + predicate(n->as_LoadVector()->memory_size() == 16); + match(Set dst (LoadVector mem)); + ins_cost(MEMORY_REF_COST); + + format %{ "VL $dst, $mem \t// load 16-byte Vector" %} + size(6); + ins_encode %{ + __ z_vl($dst$$VectorRegister, + Address(reg_to_register_object($mem$$base), $mem$$index$$Register, $mem$$disp)); + %} + ins_pipe(pipe_class_dummy); +%} + // Reinterpret: only one vector size used instruct reinterpret(iRegL dst) %{ match(Set dst (VectorReinterpret dst)); @@ -10684,6 +11223,303 @@ instruct reinterpret(iRegL dst) %{ ins_pipe(pipe_class_dummy); %} +instruct reinterpretX(vecX dst) %{ + match(Set dst (VectorReinterpret dst)); + ins_cost(0); + format %{ "reinterpret $dst" %} + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_dummy); +%} + +//----------Vector Arithmetic Instructions-------------------------------------- + +// Vector Addition Instructions + +instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (AddVB src1 src2)); + predicate(n->as_Vector()->length() == 16); + format %{ "VAB $dst,$src1,$src2\t// add packed16B" %} + size(6); + ins_encode %{ + __ z_vab($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (AddVS src1 src2)); + predicate(n->as_Vector()->length() == 8); + format %{ "VAH $dst,$src1,$src2\t// add packed8S" %} + size(6); + ins_encode %{ + __ z_vah($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (AddVI src1 src2)); + predicate(n->as_Vector()->length() == 4); + format %{ "VAF $dst,$src1,$src2\t// add packed4I" %} + size(6); + ins_encode %{ + __ z_vaf($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (AddVL src1 src2)); + predicate(n->as_Vector()->length() == 2); + format %{ "VAG $dst,$src1,$src2\t// add packed2L" %} + size(6); + ins_encode %{ + __ z_vag($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vmul16B_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (MulVB src1 src2)); + predicate(n->as_Vector()->length() == 16); + format %{ "VMLB $dst,$src1,$src2\t// mul packed16B" %} + size(6); + ins_encode %{ + __ z_vmlb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (MulVS src1 src2)); + predicate(n->as_Vector()->length() == 8); + format %{ "VMLHW $dst,$src1,$src2\t// mul packed8S" %} + size(6); + ins_encode %{ + __ z_vmlhw($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (MulVI src1 src2)); + predicate(n->as_Vector()->length() == 4); + format %{ "VMLF $dst,$src1,$src2\t// mul packed4I" %} + size(6); + ins_encode %{ + __ z_vmlf($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (SubVB src1 src2)); + predicate(n->as_Vector()->length() == 16); + format %{ "VSB $dst,$src1,$src2\t// sub packed16B" %} + size(6); + ins_encode %{ + __ z_vsb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vsub8S_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (SubVS src1 src2)); + predicate(n->as_Vector()->length() == 8); + format %{ "VSH $dst,$src1,$src2\t// sub packed8S" %} + size(6); + ins_encode %{ + __ z_vsh($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (SubVI src1 src2)); + predicate(n->as_Vector()->length() == 4); + format %{ "VSF $dst,$src1,$src2\t// sub packed4I" %} + size(6); + ins_encode %{ + __ z_vsf($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (SubVL src1 src2)); + predicate(n->as_Vector()->length() == 2); + format %{ "VSG $dst,$src1,$src2\t// sub packed2L" %} + size(6); + ins_encode %{ + __ z_vsg($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vadd4F_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (AddVF src1 src2)); + predicate(n->as_Vector()->length() == 4); + format %{ "VFASB $dst,$src1,$src2\t// add packed4F" %} + size(6); + ins_encode %{ + __ z_vfasb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vadd2D_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (AddVD src1 src2)); + predicate(n->as_Vector()->length() == 2); + format %{ "VFADB $dst,$src1,$src2\t// add packed2D" %} + size(6); + ins_encode %{ + __ z_vfadb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (SubVF src1 src2)); + predicate(n->as_Vector()->length() == 4); + format %{ "VFSSB $dst,$src1,$src2\t// sub packed4F" %} + size(6); + ins_encode %{ + __ z_vfssb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vsub2D_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (SubVD src1 src2)); + predicate(n->as_Vector()->length() == 2); + format %{ "VFSDB $dst,$src1,$src2\t// sub packed2D" %} + size(6); + ins_encode %{ + __ z_vfsdb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (MulVF src1 src2)); + predicate(n->as_Vector()->length() == 4); + format %{ "VFMSB $dst,$src1,$src2\t// mul packed4F" %} + size(6); + ins_encode %{ + __ z_vfmsb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (MulVD src1 src2)); + predicate(n->as_Vector()->length() == 2); + format %{ "VFMDB $dst,$src1,$src2\t// mul packed2D" %} + size(6); + ins_encode %{ + __ z_vfmdb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vdiv4F_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (DivVF src1 src2)); + predicate(n->as_Vector()->length() == 4); + format %{ "VFDSB $dst,$src1,$src2\t// div packed4F" %} + size(6); + ins_encode %{ + __ z_vfdsb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{ + match(Set dst (DivVD src1 src2)); + predicate(n->as_Vector()->length() == 2); + format %{ "VFDDB $dst,$src1,$src2\t// div packed2D" %} + size(6); + ins_encode %{ + __ z_vfddb($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +// Vector Square Root Instructions + +instruct vsqrt4F_reg(vecX dst, vecX src) %{ + match(Set dst (SqrtVF src)); + predicate(n->as_Vector()->length() == 4); + format %{ "VFSQSB $dst,$src\t// sqrt packed4F" %} + size(6); + ins_encode %{ + __ z_vfsqsb($dst$$VectorRegister, $src$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct vsqrt2D_reg(vecX dst, vecX src) %{ + match(Set dst (SqrtVD src)); + predicate(n->as_Vector()->length() == 2); + format %{ "VFSQDB $dst,$src\t// sqrt packed2D" %} + size(6); + ins_encode %{ + __ z_vfsqdb($dst$$VectorRegister, $src$$VectorRegister); + %} + ins_pipe(pipe_class_dummy); +%} + +// Vector Population Count Instructions + +instruct vpopcnt_reg(vecX dst, vecX src) %{ + match(Set dst (PopCountVI src)); + format %{ "VPOPCT $dst,$src\t// pop count packed" %} + size(6); + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + switch (bt) { + case T_BYTE: + __ z_vpopctb($dst$$VectorRegister, $src$$VectorRegister); + break; + case T_SHORT: + __ z_vpopcth($dst$$VectorRegister, $src$$VectorRegister); + break; + case T_INT: + __ z_vpopctf($dst$$VectorRegister, $src$$VectorRegister); + break; + case T_LONG: + __ z_vpopctg($dst$$VectorRegister, $src$$VectorRegister); + break; + default: + ShouldNotReachHere(); + } + %} + ins_pipe(pipe_class_dummy); +%} + +// Vector Round Instructions +instruct vround2D_reg(vecX dst, vecX src, immI8 rmode) %{ + match(Set dst (RoundDoubleModeV src rmode)); + predicate(n->as_Vector()->length() == 2); + format %{ "RoundDoubleModeV $src,$rmode" %} + size(6); + ins_encode %{ + switch ($rmode$$constant) { + case RoundDoubleModeNode::rmode_rint: + __ z_vflrd($dst$$VectorRegister, $src$$VectorRegister, 0); + break; + case RoundDoubleModeNode::rmode_floor: + __ z_vflrd($dst$$VectorRegister, $src$$VectorRegister, 7); + break; + case RoundDoubleModeNode::rmode_ceil: + __ z_vflrd($dst$$VectorRegister, $src$$VectorRegister, 6); + break; + default: + ShouldNotReachHere(); + } + %} + ins_pipe(pipe_class_dummy); +%} + //----------POPULATION COUNT RULES-------------------------------------------- // Byte reverse diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index c60f6ef3295..1844b0deb1c 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -81,6 +81,9 @@ #define RegisterSaver_ExcludedFloatReg(regname) \ { RegisterSaver::excluded_reg, regname->encoding(), regname->as_VMReg() } +#define RegisterSaver_LiveVReg(regname) \ + { RegisterSaver::v_reg, regname->encoding(), regname->as_VMReg() } + static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = { // Live registers which get spilled to the stack. Register positions // in this array correspond directly to the stack layout. @@ -258,6 +261,26 @@ static const RegisterSaver::LiveRegType RegisterSaver_LiveVolatileRegs[] = { // RegisterSaver_ExcludedIntReg(Z_R15) // stack pointer }; +static const RegisterSaver::LiveRegType RegisterSaver_LiveVRegs[] = { + // live vector registers (optional, only these are used by C2): + RegisterSaver_LiveVReg( Z_V16 ), + RegisterSaver_LiveVReg( Z_V17 ), + RegisterSaver_LiveVReg( Z_V18 ), + RegisterSaver_LiveVReg( Z_V19 ), + RegisterSaver_LiveVReg( Z_V20 ), + RegisterSaver_LiveVReg( Z_V21 ), + RegisterSaver_LiveVReg( Z_V22 ), + RegisterSaver_LiveVReg( Z_V23 ), + RegisterSaver_LiveVReg( Z_V24 ), + RegisterSaver_LiveVReg( Z_V25 ), + RegisterSaver_LiveVReg( Z_V26 ), + RegisterSaver_LiveVReg( Z_V27 ), + RegisterSaver_LiveVReg( Z_V28 ), + RegisterSaver_LiveVReg( Z_V29 ), + RegisterSaver_LiveVReg( Z_V30 ), + RegisterSaver_LiveVReg( Z_V31 ) +}; + int RegisterSaver::live_reg_save_size(RegisterSet reg_set) { int reg_space = -1; switch (reg_set) { @@ -271,23 +294,28 @@ int RegisterSaver::live_reg_save_size(RegisterSet reg_set) { return (reg_space / sizeof(RegisterSaver::LiveRegType)) * reg_size; } +int RegisterSaver::calculate_vregstosave_num() { + return (sizeof(RegisterSaver_LiveVRegs) / sizeof(RegisterSaver::LiveRegType)); +} -int RegisterSaver::live_reg_frame_size(RegisterSet reg_set) { - return live_reg_save_size(reg_set) + frame::z_abi_160_size; +int RegisterSaver::live_reg_frame_size(RegisterSet reg_set, bool save_vectors) { + const int vregstosave_num = save_vectors ? calculate_vregstosave_num() : 0; + return live_reg_save_size(reg_set) + vregstosave_num * v_reg_size + frame::z_abi_160_size; } // return_pc: Specify the register that should be stored as the return pc in the current frame. -OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, RegisterSet reg_set, Register return_pc) { +OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, RegisterSet reg_set, Register return_pc, bool save_vectors) { // Record volatile registers as callee-save values in an OopMap so // their save locations will be propagated to the caller frame's // RegisterMap during StackFrameStream construction (needed for // deoptimization; see compiledVFrame::create_stack_value). // Calculate frame size. - const int frame_size_in_bytes = live_reg_frame_size(reg_set); + const int frame_size_in_bytes = live_reg_frame_size(reg_set, save_vectors); const int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); - const int register_save_offset = frame_size_in_bytes - live_reg_save_size(reg_set); + const int vregstosave_num = save_vectors ? calculate_vregstosave_num() : 0; + const int register_save_offset = frame_size_in_bytes - (live_reg_save_size(reg_set) + vregstosave_num * v_reg_size); // OopMap frame size is in c2 stack slots (sizeof(jint)) not bytes or words. OopMap* map = new OopMap(frame_size_in_slots, 0); @@ -382,6 +410,23 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, RegisterSet reg assert(first != noreg, "Should spill at least one int reg."); __ z_stmg(first, last, first_offset, Z_SP); + for (int i = 0; i < vregstosave_num; i++, offset += v_reg_size) { + int reg_num = RegisterSaver_LiveVRegs[i].reg_num; + + __ z_vst(as_VectorRegister(reg_num), Address(Z_SP, offset)); + + map->set_callee_saved(VMRegImpl::stack2reg(offset>>2), + RegisterSaver_LiveVRegs[i].vmreg); + map->set_callee_saved(VMRegImpl::stack2reg((offset + half_reg_size ) >> 2), + RegisterSaver_LiveVRegs[i].vmreg->next()); + map->set_callee_saved(VMRegImpl::stack2reg((offset + (half_reg_size * 2)) >> 2), + RegisterSaver_LiveVRegs[i].vmreg->next(2)); + map->set_callee_saved(VMRegImpl::stack2reg((offset + (half_reg_size * 3)) >> 2), + RegisterSaver_LiveVRegs[i].vmreg->next(3)); + } + + assert(offset == frame_size_in_bytes, "consistency check"); + // And we're done. return map; } @@ -433,14 +478,18 @@ OopMap* RegisterSaver::generate_oop_map(MacroAssembler* masm, RegisterSet reg_se } offset += reg_size; } +#ifdef ASSERT + assert(offset == frame_size_in_bytes, "consistency check"); +#endif return map; } // Pop the current frame and restore all the registers that we saved. -void RegisterSaver::restore_live_registers(MacroAssembler* masm, RegisterSet reg_set) { +void RegisterSaver::restore_live_registers(MacroAssembler* masm, RegisterSet reg_set, bool save_vectors) { int offset; - const int register_save_offset = live_reg_frame_size(reg_set) - live_reg_save_size(reg_set); + const int vregstosave_num = save_vectors ? calculate_vregstosave_num() : 0; + const int register_save_offset = live_reg_frame_size(reg_set, save_vectors) - (live_reg_save_size(reg_set) + vregstosave_num * v_reg_size); Register first = noreg; Register last = noreg; @@ -517,6 +566,12 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, RegisterSet reg assert(first != noreg, "Should spill at least one int reg."); __ z_lmg(first, last, first_offset, Z_SP); + for (int i = 0; i < vregstosave_num; i++, offset += v_reg_size) { + int reg_num = RegisterSaver_LiveVRegs[i].reg_num; + + __ z_vl(as_VectorRegister(reg_num), Address(Z_SP, offset)); + } + // Pop the frame. __ pop_frame(); @@ -527,14 +582,12 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, RegisterSet reg // Pop the current frame and restore the registers that might be holding a result. void RegisterSaver::restore_result_registers(MacroAssembler* masm) { - int i; - int offset; const int regstosave_num = sizeof(RegisterSaver_LiveRegs) / sizeof(RegisterSaver::LiveRegType); const int register_save_offset = live_reg_frame_size(all_registers) - live_reg_save_size(all_registers); // Restore all result registers (ints and floats). - offset = register_save_offset; + int offset = register_save_offset; for (int i = 0; i < regstosave_num; i++, offset += reg_size) { int reg_num = RegisterSaver_LiveRegs[i].reg_num; int reg_type = RegisterSaver_LiveRegs[i].reg_type; @@ -557,6 +610,7 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) { ShouldNotReachHere(); } } + assert(offset == live_reg_frame_size(all_registers), "consistency check"); } // --------------------------------------------------------------------------- @@ -980,8 +1034,8 @@ static void gen_special_dispatch(MacroAssembler *masm, // Is the size of a vector size (in bytes) bigger than a size saved by default? // 8 bytes registers are saved by default on z/Architecture. bool SharedRuntime::is_wide_vector(int size) { - // Note, MaxVectorSize == 8 on this platform. - assert(size <= 8, "%d bytes vectors are not supported", size); + // Note, MaxVectorSize == 8/16 on this platform. + assert(size <= (SuperwordUseVX ? 16 : 8), "%d bytes vectors are not supported", size); return size > 8; } @@ -2865,8 +2919,9 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal __ z_lg(Z_R14, Address(Z_thread, JavaThread::saved_exception_pc_offset())); } + bool save_vectors = (id == SharedStubId::polling_page_vectors_safepoint_handler_id); // Save registers, fpu state, and flags - map = RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers); + map = RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers, Z_R14, save_vectors); if (!cause_return) { // Keep a copy of the return pc to detect if it gets modified. @@ -2898,7 +2953,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal // Pending exception case, used (sporadically) by // api/java_lang/Thread.State/index#ThreadState et al. - RegisterSaver::restore_live_registers(masm, RegisterSaver::all_registers); + RegisterSaver::restore_live_registers(masm, RegisterSaver::all_registers, save_vectors); // Jump to forward_exception_entry, with the issuing PC in Z_R14 // so it looks like the original nmethod called forward_exception_entry. @@ -2911,7 +2966,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal if (!cause_return) { Label no_adjust; // If our stashed return pc was modified by the runtime we avoid touching it - const int offset_of_return_pc = _z_common_abi(return_pc) + RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers); + const int offset_of_return_pc = _z_common_abi(return_pc) + RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers, save_vectors); __ z_cg(Z_R6, offset_of_return_pc, Z_SP); __ z_brne(no_adjust); @@ -2924,7 +2979,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal } // Normal exit, restore registers and exit. - RegisterSaver::restore_live_registers(masm, RegisterSaver::all_registers); + RegisterSaver::restore_live_registers(masm, RegisterSaver::all_registers, save_vectors); __ z_br(Z_R14); @@ -2932,7 +2987,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal masm->flush(); // Fill-out other meta info - return SafepointBlob::create(&buffer, oop_maps, RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers)/wordSize); + return SafepointBlob::create(&buffer, oop_maps, RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers, save_vectors)/wordSize); } diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index 4b17ff4594c..ee3f97f26ef 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -97,7 +97,23 @@ void VM_Version::initialize() { intx cache_line_size = Dcache_lineSize(0); #ifdef COMPILER2 - MaxVectorSize = 8; + int model_ix = get_model_index(); + + if ( model_ix >= 7 ) { + if (FLAG_IS_DEFAULT(SuperwordUseVX)) { + FLAG_SET_ERGO(SuperwordUseVX, true); + } + if (model_ix > 7 && FLAG_IS_DEFAULT(UseSFPV) && SuperwordUseVX) { + FLAG_SET_ERGO(UseSFPV, true); + } else if (model_ix == 7 && UseSFPV) { + warning("UseSFPV specified, but needs at least Z14."); + FLAG_SET_DEFAULT(UseSFPV, false); + } + } else if (SuperwordUseVX) { + warning("SuperwordUseVX specified, but needs at least Z13."); + FLAG_SET_DEFAULT(SuperwordUseVX, false); + } + MaxVectorSize = SuperwordUseVX ? 16 : 8; #endif if (has_PrefetchRaw()) { @@ -304,6 +320,12 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { FLAG_SET_DEFAULT(UseUnalignedAccesses, true); } + + // The OptoScheduling information is not maintained in s390.ad. + if (OptoScheduling) { + warning("OptoScheduling is not supported on this CPU."); + FLAG_SET_DEFAULT(OptoScheduling, false); + } } diff --git a/src/hotspot/cpu/s390/vmreg_s390.cpp b/src/hotspot/cpu/s390/vmreg_s390.cpp index 239b68513b9..5bec8313a48 100644 --- a/src/hotspot/cpu/s390/vmreg_s390.cpp +++ b/src/hotspot/cpu/s390/vmreg_s390.cpp @@ -43,6 +43,16 @@ void VMRegImpl::set_regName() { regName[i++] = freg->name(); freg = freg->successor(); } + + VectorRegister vreg = ::as_VectorRegister(0); + for (; i < ConcreteRegisterImpl::max_vr;) { + regName[i++] = vreg->name(); + regName[i++] = vreg->name(); + regName[i++] = vreg->name(); + regName[i++] = vreg->name(); + vreg = vreg->successor(); + } + for (; i < ConcreteRegisterImpl::number_of_registers; i ++) { regName[i] = "NON-GPR-XMM"; } diff --git a/src/hotspot/cpu/s390/vmreg_s390.hpp b/src/hotspot/cpu/s390/vmreg_s390.hpp index 3dd1bd9a16c..eb601f693ab 100644 --- a/src/hotspot/cpu/s390/vmreg_s390.hpp +++ b/src/hotspot/cpu/s390/vmreg_s390.hpp @@ -35,14 +35,26 @@ inline bool is_FloatRegister() { value() < ConcreteRegisterImpl::max_fpr; } +inline bool is_VectorRegister() { + return value() >= ConcreteRegisterImpl::max_fpr && + value() < ConcreteRegisterImpl::max_vr; +} + inline Register as_Register() { assert(is_Register() && is_even(value()), "even-aligned GPR name"); - return ::as_Register(value() >> 1); + return ::as_Register(value() / Register::max_slots_per_register); } inline FloatRegister as_FloatRegister() { assert(is_FloatRegister() && is_even(value()), "must be"); - return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1); + return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) / + FloatRegister::max_slots_per_register); +} + +inline VectorRegister as_VectorRegister() { + assert(is_VectorRegister(), "must be"); + return ::as_VectorRegister((value() - ConcreteRegisterImpl::max_fpr) / + VectorRegister::max_slots_per_register); } inline bool is_concrete() { diff --git a/src/hotspot/cpu/s390/vmreg_s390.inline.hpp b/src/hotspot/cpu/s390/vmreg_s390.inline.hpp index 593a0d48045..b03a66b3086 100644 --- a/src/hotspot/cpu/s390/vmreg_s390.inline.hpp +++ b/src/hotspot/cpu/s390/vmreg_s390.inline.hpp @@ -27,15 +27,21 @@ #define CPU_S390_VMREG_S390_INLINE_HPP inline VMReg Register::as_VMReg() const { - return VMRegImpl::as_VMReg(encoding() << 1); + return VMRegImpl::as_VMReg(encoding() * Register::max_slots_per_register); } inline VMReg FloatRegister::as_VMReg() const { - return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr); + return VMRegImpl::as_VMReg((encoding() * FloatRegister::max_slots_per_register) + + ConcreteRegisterImpl::max_gpr); +} + +inline VMReg VectorRegister::as_VMReg() const { + return VMRegImpl::as_VMReg((encoding() * VectorRegister::max_slots_per_register) + + ConcreteRegisterImpl::max_fpr); } inline VMReg ConditionRegister::as_VMReg() const { - return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_fpr); + return VMRegImpl::as_VMReg(encoding() + ConcreteRegisterImpl::max_vr); } #endif // CPU_S390_VMREG_S390_INLINE_HPP diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 06d93ddea26..8d0af29e91d 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -7073,13 +7073,3 @@ void C2_MacroAssembler::vector_saturating_op(int ideal_opc, BasicType elem_bt, X vector_saturating_op(ideal_opc, elem_bt, dst, src1, src2, vlen_enc); } } - -#ifdef _LP64 -void C2_MacroAssembler::load_narrow_klass_compact_c2(Register dst, Address src) { - // The incoming address is pointing into obj-start + klass_offset_in_bytes. We need to extract - // obj-start, so that we can load from the object's mark-word instead. Usually the address - // comes as obj-start in obj and klass_offset_in_bytes in disp. - movq(dst, src.plus_disp(-oopDesc::klass_offset_in_bytes())); - shrq(dst, markWord::klass_shift); -} -#endif diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 523200486cc..3a36fd75e3f 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -583,8 +583,4 @@ void select_from_two_vectors_evex(BasicType elem_bt, XMMRegister dst, XMMRegister src1, XMMRegister src2, int vlen_enc); -#ifdef _LP64 - void load_narrow_klass_compact_c2(Register dst, Address src); -#endif - #endif // CPU_X86_C2_MACROASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/c2_globals_x86.hpp b/src/hotspot/cpu/x86/c2_globals_x86.hpp index f7315011e6b..084dde217e4 100644 --- a/src/hotspot/cpu/x86/c2_globals_x86.hpp +++ b/src/hotspot/cpu/x86/c2_globals_x86.hpp @@ -76,6 +76,7 @@ define_pd_global(bool, OptoScheduling, false); define_pd_global(bool, OptoBundling, false); define_pd_global(bool, OptoRegScheduling, true); define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); +define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); define_pd_global(bool, IdealizeClearArrayNode, true); define_pd_global(uintx, ReservedCodeCacheSize, 48*M); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index fc083ecfa24..550c8047034 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -4368,11 +4368,15 @@ instruct loadNKlassCompactHeaders(rRegN dst, memory mem, rFlagsReg cr) match(Set dst (LoadNKlass mem)); effect(KILL cr); ins_cost(125); // XXX - format %{ "load_narrow_klass_compact $dst, $mem\t# compressed klass ptr" %} + format %{ + "movl $dst, $mem\t# compressed klass ptr, shifted\n\t" + "shrl $dst, markWord::klass_shift_at_offset" + %} ins_encode %{ - __ load_narrow_klass_compact_c2($dst$$Register, $mem$$Address); + __ movl($dst$$Register, $mem$$Address); + __ shrl($dst$$Register, markWord::klass_shift_at_offset); %} - ins_pipe(pipe_slow); // XXX + ins_pipe(ialu_reg_mem); // XXX %} // Load Float diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 388ee5c6ea0..a6ac2822b25 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -300,9 +300,9 @@ void CgroupV1MemoryController::print_version_specific_info(outputStream* st, jul jlong kmem_limit = kernel_memory_limit_in_bytes(phys_mem); jlong kmem_max_usage = kernel_memory_max_usage_in_bytes(); + OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_limit_in_bytes"); OSContainer::print_container_helper(st, kmem_usage, "kernel_memory_usage_in_bytes"); - OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_max_usage_in_bytes"); - OSContainer::print_container_helper(st, kmem_max_usage, "kernel_memory_limit_in_bytes"); + OSContainer::print_container_helper(st, kmem_max_usage, "kernel_memory_max_usage_in_bytes"); } char* CgroupV1Subsystem::cpu_cpuset_cpus() { diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 72330190b53..9aae3b5c143 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -931,10 +931,6 @@ void os::_exit(int num) { ALLOW_C_FUNCTION(::_exit, ::_exit(num);) } -bool os::dont_yield() { - return DontYieldALot; -} - void os::naked_yield() { sched_yield(); } diff --git a/src/hotspot/os/windows/attachListener_windows.cpp b/src/hotspot/os/windows/attachListener_windows.cpp index 5a34639a1cf..fa45c98ced2 100644 --- a/src/hotspot/os/windows/attachListener_windows.cpp +++ b/src/hotspot/os/windows/attachListener_windows.cpp @@ -161,7 +161,7 @@ class Win32AttachOperation: public AttachOperation { // Win32AttachOperationRequest is an element of AttachOperation request list. -class Win32AttachOperationRequest { +class Win32AttachOperationRequest: public CHeapObj { private: AttachAPIVersion _ver; char _name[AttachOperation::name_length_max + 1]; diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 9d514e584a4..fd857c2cd95 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4856,12 +4856,6 @@ int os::loadavg(double loadavg[], int nelem) { return -1; } - -// DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield() -bool os::dont_yield() { - return DontYieldALot; -} - int os::open(const char *path, int oflag, int mode) { errno_t err; wchar_t* wide_path = wide_abs_unc_path(path, err); diff --git a/src/hotspot/os_cpu/aix_ppc/globals_aix_ppc.hpp b/src/hotspot/os_cpu/aix_ppc/globals_aix_ppc.hpp index b946ce15fa0..e8b04add19d 100644 --- a/src/hotspot/os_cpu/aix_ppc/globals_aix_ppc.hpp +++ b/src/hotspot/os_cpu/aix_ppc/globals_aix_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,7 +29,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default define_pd_global(intx, VMThreadStackSize, 2048); diff --git a/src/hotspot/os_cpu/bsd_aarch64/globals_bsd_aarch64.hpp b/src/hotspot/os_cpu/bsd_aarch64/globals_bsd_aarch64.hpp index c18c4506ac9..4a10e7af091 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/globals_bsd_aarch64.hpp +++ b/src/hotspot/os_cpu/bsd_aarch64/globals_bsd_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -31,7 +31,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default define_pd_global(intx, VMThreadStackSize, 2048); diff --git a/src/hotspot/os_cpu/bsd_x86/globals_bsd_x86.hpp b/src/hotspot/os_cpu/bsd_x86/globals_bsd_x86.hpp index a434e329a8b..f67bb15c69e 100644 --- a/src/hotspot/os_cpu/bsd_x86/globals_bsd_x86.hpp +++ b/src/hotspot/os_cpu/bsd_x86/globals_bsd_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) // -define_pd_global(bool, DontYieldALot, false); #ifdef AMD64 define_pd_global(intx, CompilerThreadStackSize, 1024); define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default diff --git a/src/hotspot/os_cpu/bsd_zero/globals_bsd_zero.hpp b/src/hotspot/os_cpu/bsd_zero/globals_bsd_zero.hpp index 71aa9043e9e..daf2fd8f2a6 100644 --- a/src/hotspot/os_cpu/bsd_zero/globals_bsd_zero.hpp +++ b/src/hotspot/os_cpu/bsd_zero/globals_bsd_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,7 +31,6 @@ // runtime system. See globals.hpp for details of what they do. // -define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, ThreadStackSize, 1536); #ifdef _LP64 define_pd_global(intx, VMThreadStackSize, 1024); diff --git a/src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp index c4219c2bac3..955a0ae9dcd 100644 --- a/src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,8 +29,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -define_pd_global(bool, DontYieldALot, false); - // Set default stack sizes < 2MB so as to prevent stacks from getting // large-page aligned and backed by THPs on systems where 2MB is the // default huge page size. For non-JavaThreads, glibc may add an additional diff --git a/src/hotspot/os_cpu/linux_arm/globals_linux_arm.hpp b/src/hotspot/os_cpu/linux_arm/globals_linux_arm.hpp index 4f2d3918a4d..c4ffdf2c02e 100644 --- a/src/hotspot/os_cpu/linux_arm/globals_linux_arm.hpp +++ b/src/hotspot/os_cpu/linux_arm/globals_linux_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) // -define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, CompilerThreadStackSize, 512); // System default ThreadStackSize appears to be 512 which is too big. define_pd_global(intx, ThreadStackSize, 320); diff --git a/src/hotspot/os_cpu/linux_ppc/globals_linux_ppc.hpp b/src/hotspot/os_cpu/linux_ppc/globals_linux_ppc.hpp index 182c55b9f96..96dcf0a8c0e 100644 --- a/src/hotspot/os_cpu/linux_ppc/globals_linux_ppc.hpp +++ b/src/hotspot/os_cpu/linux_ppc/globals_linux_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,7 +29,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default define_pd_global(intx, VMThreadStackSize, 2048); diff --git a/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp index 297414bfcd5..16e4b205547 100644 --- a/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp +++ b/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,7 +29,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default define_pd_global(intx, VMThreadStackSize, 2048); diff --git a/src/hotspot/os_cpu/linux_s390/globals_linux_s390.hpp b/src/hotspot/os_cpu/linux_s390/globals_linux_s390.hpp index 295dd665d2d..49607e24d15 100644 --- a/src/hotspot/os_cpu/linux_s390/globals_linux_s390.hpp +++ b/src/hotspot/os_cpu/linux_s390/globals_linux_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,7 +31,6 @@ // Sets the default values for platform dependent flags used by the // runtime system (see globals.hpp). -define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, ThreadStackSize, 1024); // 0 => Use system default. define_pd_global(intx, VMThreadStackSize, 1024); // Some jck tests in lang/fp/fpl038 run out of compile thread stack. diff --git a/src/hotspot/os_cpu/linux_x86/globals_linux_x86.hpp b/src/hotspot/os_cpu/linux_x86/globals_linux_x86.hpp index 8f1f64c2d9e..97a5732d00a 100644 --- a/src/hotspot/os_cpu/linux_x86/globals_linux_x86.hpp +++ b/src/hotspot/os_cpu/linux_x86/globals_linux_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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,7 +28,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -define_pd_global(bool, DontYieldALot, false); #ifdef AMD64 define_pd_global(intx, CompilerThreadStackSize, 1024); define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default diff --git a/src/hotspot/os_cpu/linux_zero/globals_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/globals_linux_zero.hpp index 957c5c4a12a..ed09bf8372e 100644 --- a/src/hotspot/os_cpu/linux_zero/globals_linux_zero.hpp +++ b/src/hotspot/os_cpu/linux_zero/globals_linux_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,7 +31,6 @@ // runtime system. See globals.hpp for details of what they do. // -define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, ThreadStackSize, 1536); #ifdef _LP64 define_pd_global(intx, VMThreadStackSize, 1024); diff --git a/src/hotspot/os_cpu/windows_aarch64/globals_windows_aarch64.hpp b/src/hotspot/os_cpu/windows_aarch64/globals_windows_aarch64.hpp index 836fb463206..a438e438cdb 100644 --- a/src/hotspot/os_cpu/windows_aarch64/globals_windows_aarch64.hpp +++ b/src/hotspot/os_cpu/windows_aarch64/globals_windows_aarch64.hpp @@ -28,8 +28,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -define_pd_global(bool, DontYieldALot, false); - // Default stack size on Windows is determined by the executable (java.exe // has a default value of 320K/1MB [32bit/64bit]). Depending on Windows version, changing // ThreadStackSize to non-zero may have significant impact on memory usage. diff --git a/src/hotspot/os_cpu/windows_x86/globals_windows_x86.hpp b/src/hotspot/os_cpu/windows_x86/globals_windows_x86.hpp index c94796b097a..811fa2e07e9 100644 --- a/src/hotspot/os_cpu/windows_x86/globals_windows_x86.hpp +++ b/src/hotspot/os_cpu/windows_x86/globals_windows_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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,8 +28,6 @@ // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -define_pd_global(bool, DontYieldALot, false); - // Default stack size on Windows is determined by the executable (java.exe // has a default value of 320K/1MB [32bit/64bit]). Depending on Windows version, changing // ThreadStackSize to non-zero may have significant impact on memory usage. diff --git a/src/hotspot/share/adlc/output_c.cpp b/src/hotspot/share/adlc/output_c.cpp index 804e8f1a4e6..cc6ed278b49 100644 --- a/src/hotspot/share/adlc/output_c.cpp +++ b/src/hotspot/share/adlc/output_c.cpp @@ -2358,6 +2358,9 @@ class DefineEmitState { if (strcmp(rep_var,"$VectorRegister") == 0) return "as_VectorRegister"; if (strcmp(rep_var,"$VectorSRegister") == 0) return "as_VectorSRegister"; #endif +#if defined(S390) + if (strcmp(rep_var,"$VectorRegister") == 0) return "as_VectorRegister"; +#endif #if defined(AARCH64) if (strcmp(rep_var,"$PRegister") == 0) return "as_PRegister"; #endif diff --git a/src/hotspot/share/cds/aotClassInitializer.cpp b/src/hotspot/share/cds/aotClassInitializer.cpp new file mode 100644 index 00000000000..b09dfcde6b1 --- /dev/null +++ b/src/hotspot/share/cds/aotClassInitializer.cpp @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2024, 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 "cds/aotClassInitializer.hpp" +#include "cds/archiveBuilder.hpp" +#include "cds/cdsConfig.hpp" +#include "cds/heapShared.hpp" +#include "classfile/vmSymbols.hpp" +#include "oops/instanceKlass.inline.hpp" +#include "oops/symbol.hpp" +#include "runtime/javaCalls.hpp" + +// Detector for class names we wish to handle specially. +// It is either an exact string match or a string prefix match. +class AOTClassInitializer::AllowedSpec { + const char* _class_name; + bool _is_prefix; + int _len; +public: + AllowedSpec(const char* class_name, bool is_prefix = false) + : _class_name(class_name), _is_prefix(is_prefix) + { + _len = (class_name == nullptr) ? 0 : (int)strlen(class_name); + } + const char* class_name() { return _class_name; } + + bool matches(Symbol* name, int len) { + assert(_class_name != nullptr, "caller resp."); + if (_is_prefix) { + return len >= _len && name->starts_with(_class_name); + } else { + return len == _len && name->equals(_class_name); + } + } +}; + + +// Tell if ik has a name that matches one of the given specs. +bool AOTClassInitializer::is_allowed(AllowedSpec* specs, InstanceKlass* ik) { + Symbol* name = ik->name(); + int len = name->utf8_length(); + for (AllowedSpec* s = specs; s->class_name() != nullptr; s++) { + if (s->matches(name, len)) { + // If a type is included in the tables inside can_archive_initialized_mirror(), we require that + // - all super classes must be included + // - all super interfaces that have must be included. + // This ensures that in the production run, we don't run the of a supertype but skips + // ik's . + if (ik->java_super() != nullptr) { + DEBUG_ONLY(ResourceMark rm); + assert(AOTClassInitializer::can_archive_initialized_mirror(ik->java_super()), + "super class %s of %s must be aot-initialized", ik->java_super()->external_name(), + ik->external_name()); + } + + Array* interfaces = ik->local_interfaces(); + int len = interfaces->length(); + for (int i = 0; i < len; i++) { + InstanceKlass* intf = interfaces->at(i); + if (intf->class_initializer() != nullptr) { + assert(AOTClassInitializer::can_archive_initialized_mirror(intf), + "super interface %s (which has ) of %s must be aot-initialized", intf->external_name(), + ik->external_name()); + } + } + + return true; + } + } + return false; +} + + +bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) { + assert(!ArchiveBuilder::current()->is_in_buffer_space(ik), "must be source klass"); + if (!CDSConfig::is_initing_classes_at_dump_time()) { + return false; + } + + if (!ik->is_initialized()) { + return false; + } + + if (ik->is_hidden()) { + return HeapShared::is_archivable_hidden_klass(ik); + } + + if (ik->is_enum_subclass()) { + return true; + } + + // About "static field that may hold a different value" errors: + // + // Automatic selection for aot-inited classes + // ========================================== + // + // When CDSConfig::is_initing_classes_at_dump_time() is enabled, + // HeapShared::find_all_aot_initialized_classes() finds the classes of all + // heap objects that are reachable from HeapShared::_run_time_special_subgraph, + // and mark these classes as aot-inited. This preserves the initialized + // mirrors of these classes, and their methods are NOT executed + // at runtime. + // + // For example, with -XX:+AOTInvokeDynamicLinking, _run_time_special_subgraph + // will contain some DirectMethodHandle objects. As a result, the DirectMethodHandle + // class is automatically marked as aot-inited. + // + // When a class is aot-inited, its static fields are already set up + // by executing the method at AOT assembly time. Later on + // in the production run, when the class would normally be + // initialized, the VM performs guarding and synchronization as if + // it were going to run the again, but instead it simply + // observes that that class was aot-inited. The VM assumes that, if + // it were to run again, it would get a semantically + // equivalent set of final field values, so it just adopts the + // existing field values (from AOT assembly) and skips the call to + // . There may at that point be fixups performed by ad hoc + // code, if the VM recognizes a request in the library. + // + // It is true that this is not generally correct for all possible + // Java code. A method might have a side effect beyond + // initializing the static fields. It might send an email somewhere + // noting the current time of day. In that case, such an email + // would have been sent during the AOT assembly phase, and the email + // would NOT be sent again during production. This is clearly NOT + // what a user would want, if this were a general purpose facility. + // But in fact it is only for certain well-behaved classes, which + // are known NOT to have such side effects. We know this because + // the optimization (of skipping for aot-init classes) is + // only applied to classes fully defined by the JDK. + // + // (A day may come when we figure out how to gracefully extend this + // optimization to untrusted third parties, but it is not this day.) + // + // Manual selection + // ================ + // + // There are important cases where one aot-init class has a side + // effect on another aot-class, a side effect which is not captured + // in any static field value in either class. The simplest example + // is class A forces the initialization of class B. In that case, + // we need to aot-init either both classes or neither. From looking + // at the JDK state after AOT assembly is done, it is hard to tell + // that A "touched" B and B might escape our notice. Another common + // example is A copying a field value from B. We don't know where A + // got the value, but it would be wrong to re-initialize B at + // startup, while keeping the snapshot of the old B value in A. In + // general, if we aot-init A, we need to aot-init every class B that + // somehow contributed to A's initial state, and every class C that + // was somehow side-effected by A's initialization. We say that the + // aot-init of A is "init-coupled" to those of B and C. + // + // So there are init-coupled classes that cannot be automatically discovered. For + // example, DirectMethodHandle::IMPL_NAMES points to MethodHandles::IMPL_NAMES, + // but the MethodHandles class is not automatically marked because there are + // no archived instances of the MethodHandles type. + // + // If we aot-initialize DirectMethodHandle, but allow MethodHandles to be + // initialized at runtime, MethodHandles::IMPL_NAMES will get a different + // value than DirectMethodHandle::IMPL_NAMES. This *may or may not* be a problem, + // but to ensure compatibility, we should try to preserve the identity equality + // of these two fields. + // + // To do that, we add MethodHandles to the indy_specs[] table below. + // + // Luckily we do not need to be all-knowing in order to choose which + // items to add to that table. We have tools to help detect couplings. + // + // Automatic validation + // ==================== + // + // CDSHeapVerifier is used to detect potential problems with identity equality. + // + // A class B is assumed to be init-coupled to some aot-init class if + // B has a field which points to a live object X in the AOT heap. + // The live object X was created by some other class A which somehow + // used B's reference to X, perhaps with the help of an intermediate + // class Z. Or, B pulled the reference to X from some other class + // Y, and B obtained that reference from Y (or an intermediate Z). + // It is not certain how X got into the heap, nor whether B + // contributed it, but it is a good heuristic that B is init-coupled + // to X's class or some other aot-init class. In any case, B should + // be made an aot-init class as well, unless a manual inspection + // shows that would be a problem. If there is a problem, then the + // JDK code for B and/or X probably needs refactoring. If there is + // no problem, we add B to the list. Typically the same scan will + // find any other accomplices Y, Z, etc. One failure would be a + // class Q whose only initialization action is to scribble a special + // value into B, from which the value X is derived and then makes + // its way into the heap. In that case, the heuristic does not + // identify Q. It is (currently) a human responsibility, of JDK + // engineers, not to write such dirty JDK code, or to repair it if + // it crops up. Eventually we may have tools, or even a user mode + // with design rules and checks, that will vet our code base more + // automatically. + // + // To see how the tool detects the problem with MethodHandles::IMPL_NAMES: + // + // - Comment out all the lines in indy_specs[] except the {nullptr} line. + // - Rebuild the JDK + // + // Then run the following: + // java -XX:AOTMode=record -XX:AOTConfiguration=jc.aotconfig com.sun.tools.javac.Main + // java -XX:AOTMode=create -Xlog:cds -XX:AOTCache=jc.aot -XX:AOTConfiguration=jc.aotconfig + // + // You will see an error like this: + // + // Archive heap points to a static field that may hold a different value at runtime: + // Field: java/lang/invoke/MethodHandles::IMPL_NAMES + // Value: java.lang.invoke.MemberName$Factory + // {0x000000060e906ae8} - klass: 'java/lang/invoke/MemberName$Factory' - flags: + // + // - ---- fields (total size 2 words): + // --- trace begin --- + // [ 0] {0x000000060e8deeb0} java.lang.Class (java.lang.invoke.DirectMethodHandle::IMPL_NAMES) + // [ 1] {0x000000060e906ae8} java.lang.invoke.MemberName$Factory + // --- trace end --- + // + // Trouble-shooting + // ================ + // + // If you see a "static field that may hold a different value" error, it's probably + // because you've made some changes in the JDK core libraries (most likely + // java.lang.invoke). + // + // - Did you add a new static field to a class that could be referenced by + // cached object instances of MethodType, MethodHandle, etc? You may need + // to add that class to indy_specs[]. + // - Did you modify the of the classes in java.lang.invoke such that + // a static field now points to an object that should not be cached (e.g., + // a native resource such as a file descriptior, or a Thread)? + // + // Note that these potential problems only occur when one class gets + // the aot-init treatment, AND another class is init-coupled to it, + // AND the coupling is not detected. Currently there are a number + // classes that get the aot-init treatment, in java.lang.invoke + // because of invokedynamic. They are few enough for now to be + // manually tracked. There may be more in the future. + + // IS_PREFIX means that we match all class names that start with a + // prefix. Otherwise, it is an exact match, of just one class name. + const bool IS_PREFIX = true; + + { + static AllowedSpec specs[] = { + // everybody's favorite super + {"java/lang/Object"}, + + // above we selected all enums; we must include their super as well + {"java/lang/Enum"}, + {nullptr} + }; + if (is_allowed(specs, ik)) { + return true; + } + } + + if (CDSConfig::is_dumping_invokedynamic()) { + // This table was created with the help of CDSHeapVerifier. + // Also, some $Holder classes are needed. E.g., Invokers. explicitly + // initializes Invokers$Holder. Since Invokers. won't be executed + // at runtime, we need to make sure Invokers$Holder is also aot-inited. + // + // We hope we can reduce the size of this list over time, and move + // the responsibility for identifying such classes into the JDK + // code itself. See tracking RFE JDK-8342481. + static AllowedSpec indy_specs[] = { + {"java/lang/constant/ConstantDescs"}, + {"java/lang/constant/DynamicConstantDesc"}, + {"java/lang/invoke/BoundMethodHandle"}, + {"java/lang/invoke/BoundMethodHandle$Specializer"}, + {"java/lang/invoke/BoundMethodHandle$Species_", IS_PREFIX}, + {"java/lang/invoke/ClassSpecializer"}, + {"java/lang/invoke/ClassSpecializer$", IS_PREFIX}, + {"java/lang/invoke/DelegatingMethodHandle"}, + {"java/lang/invoke/DelegatingMethodHandle$Holder"}, // UNSAFE.ensureClassInitialized() + {"java/lang/invoke/DirectMethodHandle"}, + {"java/lang/invoke/DirectMethodHandle$Constructor"}, + {"java/lang/invoke/DirectMethodHandle$Holder"}, // UNSAFE.ensureClassInitialized() + {"java/lang/invoke/Invokers"}, + {"java/lang/invoke/Invokers$Holder"}, // UNSAFE.ensureClassInitialized() + {"java/lang/invoke/LambdaForm"}, + {"java/lang/invoke/LambdaForm$Holder"}, // UNSAFE.ensureClassInitialized() + {"java/lang/invoke/LambdaForm$NamedFunction"}, + {"java/lang/invoke/MethodHandle"}, + {"java/lang/invoke/MethodHandles"}, + {"java/lang/invoke/SimpleMethodHandle"}, + {"java/util/Collections"}, + {"java/util/stream/Collectors"}, + {"jdk/internal/constant/ConstantUtils"}, + {"jdk/internal/constant/PrimitiveClassDescImpl"}, + {"jdk/internal/constant/ReferenceClassDescImpl"}, + + // Can't include this, as it will pull in MethodHandleStatics which has many environment + // dependencies (on system properties, etc). + // MethodHandleStatics is an example of a class that must NOT get the aot-init treatment, + // because of its strong reliance on (a) final fields which are (b) environmentally determined. + //{"java/lang/invoke/InvokerBytecodeGenerator"}, + + {nullptr} + }; + if (is_allowed(indy_specs, ik)) { + return true; + } + } + + return false; +} + +// TODO: currently we have a hard-coded list. We should turn this into +// an annotation: @jdk.internal.vm.annotation.RuntimeSetupRequired +// See JDK-8342481. +bool AOTClassInitializer::is_runtime_setup_required(InstanceKlass* ik) { + return ik == vmClasses::Class_klass() || + ik == vmClasses::internal_Unsafe_klass() || + ik == vmClasses::ConcurrentHashMap_klass(); +} + +void AOTClassInitializer::call_runtime_setup(JavaThread* current, InstanceKlass* ik) { + assert(ik->has_aot_initialized_mirror(), "sanity"); + if (ik->is_runtime_setup_required()) { + if (log_is_enabled(Info, cds, init)) { + ResourceMark rm; + log_info(cds, init)("Calling %s::runtimeSetup()", ik->external_name()); + } + JavaValue result(T_VOID); + JavaCalls::call_static(&result, ik, + vmSymbols::runtimeSetup(), + vmSymbols::void_method_signature(), current); + if (current->has_pending_exception()) { + // We cannot continue, as we might have cached instances of ik in the heap, but propagating the + // exception would cause ik to be in an error state. + AOTLinkedClassBulkLoader::exit_on_exception(current); + } + } +} + diff --git a/src/hotspot/share/cds/aotClassInitializer.hpp b/src/hotspot/share/cds/aotClassInitializer.hpp new file mode 100644 index 00000000000..c8693a0add3 --- /dev/null +++ b/src/hotspot/share/cds/aotClassInitializer.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024, 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_CDS_AOTCLASSINITIALIZER_HPP +#define SHARE_CDS_AOTCLASSINITIALIZER_HPP + +#include "memory/allStatic.hpp" +#include "utilities/exceptions.hpp" + +class InstanceKlass; + +class AOTClassInitializer : AllStatic { + class AllowedSpec; + static bool is_allowed(AllowedSpec* specs, InstanceKlass* ik); + +public: + // Called by heapShared.cpp to see if src_ik->java_mirror() can be archived in + // the initialized state. + static bool can_archive_initialized_mirror(InstanceKlass* src_ik); + + static bool is_runtime_setup_required(InstanceKlass* ik); + static void call_runtime_setup(JavaThread* current, InstanceKlass* ik); +}; + +#endif // SHARE_CDS_AOTCLASSINITIALIZER_HPP diff --git a/src/hotspot/share/cds/aotClassLinker.cpp b/src/hotspot/share/cds/aotClassLinker.cpp new file mode 100644 index 00000000000..8525ce928a8 --- /dev/null +++ b/src/hotspot/share/cds/aotClassLinker.cpp @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2024, 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 "cds/aotClassLinker.hpp" +#include "cds/aotConstantPoolResolver.hpp" +#include "cds/aotLinkedClassTable.hpp" +#include "cds/archiveBuilder.hpp" +#include "cds/archiveUtils.inline.hpp" +#include "cds/cdsConfig.hpp" +#include "cds/heapShared.hpp" +#include "cds/lambdaFormInvokers.inline.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/dictionary.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "classfile/vmClasses.hpp" +#include "memory/resourceArea.hpp" +#include "oops/constantPool.inline.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/klass.inline.hpp" +#include "runtime/handles.inline.hpp" + +AOTClassLinker::ClassesTable* AOTClassLinker::_vm_classes = nullptr; +AOTClassLinker::ClassesTable* AOTClassLinker::_candidates = nullptr; +GrowableArrayCHeap* AOTClassLinker::_sorted_candidates = nullptr; + +#ifdef ASSERT +bool AOTClassLinker::is_initialized() { + assert(CDSConfig::is_dumping_archive(), "AOTClassLinker is for CDS dumping only"); + return _vm_classes != nullptr; +} +#endif + +void AOTClassLinker::initialize() { + assert(!is_initialized(), "sanity"); + + _vm_classes = new (mtClass)ClassesTable(); + _candidates = new (mtClass)ClassesTable(); + _sorted_candidates = new GrowableArrayCHeap(1000); + + for (auto id : EnumRange{}) { + add_vm_class(vmClasses::klass_at(id)); + } + + assert(is_initialized(), "sanity"); + + AOTConstantPoolResolver::initialize(); +} + +void AOTClassLinker::dispose() { + assert(is_initialized(), "sanity"); + + delete _vm_classes; + delete _candidates; + delete _sorted_candidates; + _vm_classes = nullptr; + _candidates = nullptr; + _sorted_candidates = nullptr; + + assert(!is_initialized(), "sanity"); + + AOTConstantPoolResolver::dispose(); +} + +bool AOTClassLinker::is_vm_class(InstanceKlass* ik) { + assert(is_initialized(), "sanity"); + return (_vm_classes->get(ik) != nullptr); +} + +void AOTClassLinker::add_vm_class(InstanceKlass* ik) { + assert(is_initialized(), "sanity"); + bool created; + _vm_classes->put_if_absent(ik, &created); + if (created) { + if (CDSConfig::is_dumping_aot_linked_classes()) { + bool v = try_add_candidate(ik); + assert(v, "must succeed for VM class"); + } + InstanceKlass* super = ik->java_super(); + if (super != nullptr) { + add_vm_class(super); + } + Array* ifs = ik->local_interfaces(); + for (int i = 0; i < ifs->length(); i++) { + add_vm_class(ifs->at(i)); + } + } +} + +bool AOTClassLinker::is_candidate(InstanceKlass* ik) { + return (_candidates->get(ik) != nullptr); +} + +void AOTClassLinker::add_new_candidate(InstanceKlass* ik) { + assert(!is_candidate(ik), "caller need to check"); + _candidates->put_when_absent(ik, true); + _sorted_candidates->append(ik); + + if (log_is_enabled(Info, cds, aot, link)) { + ResourceMark rm; + log_info(cds, aot, link)("%s %s %p", class_category_name(ik), ik->external_name(), ik); + } +} + +// ik is a candidate for aot-linking; see if it can really work +// that way, and return success or failure. Not only must ik itself +// look like a class that can be aot-linked but its supers must also be +// aot-linkable. +bool AOTClassLinker::try_add_candidate(InstanceKlass* ik) { + assert(is_initialized(), "sanity"); + assert(CDSConfig::is_dumping_aot_linked_classes(), "sanity"); + + if (!SystemDictionaryShared::is_builtin(ik)) { + // not loaded by a class loader which we know about + return false; + } + + if (is_candidate(ik)) { // already checked. + return true; + } + + if (ik->is_hidden()) { + assert(ik->shared_class_loader_type() != ClassLoader::OTHER, "must have been set"); + if (!CDSConfig::is_dumping_invokedynamic()) { + return false; + } + if (!SystemDictionaryShared::should_hidden_class_be_archived(ik)) { + return false; + } + if (HeapShared::is_lambda_proxy_klass(ik)) { + InstanceKlass* nest_host = ik->nest_host_not_null(); + if (!try_add_candidate(nest_host)) { + ResourceMark rm; + log_warning(cds, aot, link)("%s cannot be aot-linked because it nest host is not aot-linked", ik->external_name()); + return false; + } + } + } + + InstanceKlass* s = ik->java_super(); + if (s != nullptr && !try_add_candidate(s)) { + return false; + } + + Array* interfaces = ik->local_interfaces(); + int num_interfaces = interfaces->length(); + for (int index = 0; index < num_interfaces; index++) { + InstanceKlass* intf = interfaces->at(index); + if (!try_add_candidate(intf)) { + return false; + } + } + + // There are no loops in the class hierarchy, and this function is always called single-threaded, so + // we know ik has not been added yet. + assert(CDSConfig::current_thread_is_vm_or_dumper(), "that's why we don't need locks"); + add_new_candidate(ik); + + return true; +} + +void AOTClassLinker::add_candidates() { + assert_at_safepoint(); + if (CDSConfig::is_dumping_aot_linked_classes()) { + GrowableArray* klasses = ArchiveBuilder::current()->klasses(); + for (GrowableArrayIterator it = klasses->begin(); it != klasses->end(); ++it) { + Klass* k = *it; + if (k->is_instance_klass()) { + try_add_candidate(InstanceKlass::cast(k)); + } + } + } +} + +void AOTClassLinker::write_to_archive() { + assert(is_initialized(), "sanity"); + assert_at_safepoint(); + + if (CDSConfig::is_dumping_aot_linked_classes()) { + AOTLinkedClassTable* table = AOTLinkedClassTable::get(CDSConfig::is_dumping_static_archive()); + table->set_boot(write_classes(nullptr, true)); + table->set_boot2(write_classes(nullptr, false)); + table->set_platform(write_classes(SystemDictionary::java_platform_loader(), false)); + table->set_app(write_classes(SystemDictionary::java_system_loader(), false)); + } +} + +Array* AOTClassLinker::write_classes(oop class_loader, bool is_javabase) { + ResourceMark rm; + GrowableArray list; + + for (int i = 0; i < _sorted_candidates->length(); i++) { + InstanceKlass* ik = _sorted_candidates->at(i); + if (ik->class_loader() != class_loader) { + continue; + } + if ((ik->module() == ModuleEntryTable::javabase_moduleEntry()) != is_javabase) { + continue; + } + + if (ik->is_shared() && CDSConfig::is_dumping_dynamic_archive()) { + if (CDSConfig::is_using_aot_linked_classes()) { + // This class was recorded as AOT-linked for the base archive, + // so there's no need to do so again for the dynamic archive. + } else { + list.append(ik); + } + } else { + list.append(ArchiveBuilder::current()->get_buffered_addr(ik)); + } + } + + if (list.length() == 0) { + return nullptr; + } else { + const char* category = class_category_name(list.at(0)); + log_info(cds, aot, link)("wrote %d class(es) for category %s", list.length(), category); + return ArchiveUtils::archive_array(&list); + } +} + +int AOTClassLinker::num_platform_initiated_classes() { + if (CDSConfig::is_dumping_aot_linked_classes()) { + // AOTLinkedClassBulkLoader will initiate loading of all public boot classes in the platform loader. + return count_public_classes(nullptr); + } else { + return 0; + } +} + +int AOTClassLinker::num_app_initiated_classes() { + if (CDSConfig::is_dumping_aot_linked_classes()) { + // AOTLinkedClassBulkLoader will initiate loading of all public boot/platform classes in the app loader. + return count_public_classes(nullptr) + count_public_classes(SystemDictionary::java_platform_loader()); + } else { + return 0; + } +} + +int AOTClassLinker::count_public_classes(oop loader) { + int n = 0; + for (int i = 0; i < _sorted_candidates->length(); i++) { + InstanceKlass* ik = _sorted_candidates->at(i); + if (ik->is_public() && !ik->is_hidden() && ik->class_loader() == loader) { + n++; + } + } + + return n; +} + +// Used in logging: "boot1", "boot2", "plat", "app" and "unreg", or "array" +const char* AOTClassLinker::class_category_name(Klass* k) { + if (ArchiveBuilder::is_active() && ArchiveBuilder::current()->is_in_buffer_space(k)) { + k = ArchiveBuilder::current()->get_source_addr(k); + } + + if (k->is_array_klass()) { + return "array"; + } else { + oop loader = k->class_loader(); + if (loader == nullptr) { + if (k->module() != nullptr && + k->module()->name() != nullptr && + k->module()->name()->equals("java.base")) { + return "boot1"; // boot classes in java.base are loaded in the 1st phase + } else { + return "boot2"; // boot classes outside of java.base are loaded in the 2nd phase phase + } + } else { + if (loader == SystemDictionary::java_platform_loader()) { + return "plat"; + } else if (loader == SystemDictionary::java_system_loader()) { + return "app"; + } else { + return "unreg"; + } + } + } +} + +const char* AOTClassLinker::class_category_name(AOTLinkedClassCategory category) { + switch (category) { + case AOTLinkedClassCategory::BOOT1: + return "boot1"; + case AOTLinkedClassCategory::BOOT2: + return "boot2"; + case AOTLinkedClassCategory::PLATFORM: + return "plat"; + case AOTLinkedClassCategory::APP: + return "app"; + case AOTLinkedClassCategory::UNREGISTERED: + default: + return "unreg"; + } +} + diff --git a/src/hotspot/share/cds/aotClassLinker.hpp b/src/hotspot/share/cds/aotClassLinker.hpp new file mode 100644 index 00000000000..f15684a1ad2 --- /dev/null +++ b/src/hotspot/share/cds/aotClassLinker.hpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024, 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_CDS_AOTCLASSLINKER_HPP +#define SHARE_CDS_AOTCLASSLINKER_HPP + +#include "interpreter/bytecodes.hpp" +#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" +#include "oops/oopsHierarchy.hpp" +#include "utilities/exceptions.hpp" +#include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" +#include "utilities/resourceHash.hpp" + +class AOTLinkedClassTable; +class InstanceKlass; +class SerializeClosure; +template class Array; +enum class AOTLinkedClassCategory : int; + +// AOTClassLinker is used during the AOTCache Assembly Phase. +// It links eligible classes before they are written into the AOTCache +// +// The classes linked by AOTClassLinker are recorded in an AOTLinkedClassTable, +// which is also written into the AOTCache. +// +// AOTClassLinker is enabled by the -XX:+AOTClassLinking option. If this option +// is disabled, an empty AOTLinkedClassTable will be included in the AOTCache. +// +// For each class C in the AOTLinkedClassTable, the following properties for C +// are assigned by AOTClassLinker and cannot be changed thereafter. +// - The CodeSource for C +// - The bytecodes in C +// - The supertypes of C +// - The ClassLoader, Package and Module of C +// - The visibility of C +// +// During a production run, the JVM can use an AOTCache with an AOTLinkedClassTable +// only if it's guaranteed to produce the same results for the above set of properties +// for each class C in the AOTLinkedClassTable. +// +// For example, +// - C may be loaded from a different CodeSource when the CLASSPATH is changed. +// - Some JVMTI agent may allow the bytecodes of C to be modified. +// - C may be made invisible by module options such as --add-modules +// In such situations, the JVM will refuse to load the AOTCache. +// +class AOTClassLinker : AllStatic { + static const int TABLE_SIZE = 15889; // prime number + using ClassesTable = ResourceHashtable; + + // Classes loaded inside vmClasses::resolve_all() + static ClassesTable* _vm_classes; + + // Classes that should be automatically loaded into system dictionary at VM start-up + static ClassesTable* _candidates; + + // Sorted list such that super types come first. + static GrowableArrayCHeap* _sorted_candidates; + + DEBUG_ONLY(static bool is_initialized()); + + static void add_vm_class(InstanceKlass* ik); + static void add_new_candidate(InstanceKlass* ik); + + static Array* write_classes(oop class_loader, bool is_javabase); + static int count_public_classes(oop loader); + +public: + static void initialize(); + static void add_candidates(); + static void write_to_archive(); + static void dispose(); + + // Is this class resolved as part of vmClasses::resolve_all()? + static bool is_vm_class(InstanceKlass* ik); + + // When CDS is enabled, is ik guaranteed to be linked at deployment time (and + // cannot be replaced by JVMTI, etc)? + // This is a necessary (but not sufficient) condition for keeping a direct pointer + // to ik in AOT-computed data (such as ConstantPool entries in archived classes, + // or in AOT-compiled code). + static bool is_candidate(InstanceKlass* ik); + + // Request that ik be added to the candidates table. This will return true only if + // ik is allowed to be aot-linked. + static bool try_add_candidate(InstanceKlass* ik); + + static int num_app_initiated_classes(); + static int num_platform_initiated_classes(); + + // Used in logging: "boot1", "boot2", "plat", "app" and "unreg"; + static const char* class_category_name(AOTLinkedClassCategory category); + static const char* class_category_name(Klass* k); +}; + +// AOT-linked classes are divided into different categories and are loaded +// in two phases during the production run. +enum class AOTLinkedClassCategory : int { + BOOT1, // Only java.base classes are loaded in the 1st phase + BOOT2, // All boot classes that not in java.base are loaded in the 2nd phase + PLATFORM, // Classes for platform loader, loaded in the 2nd phase + APP, // Classes for the app loader, loaded in the 2nd phase + UNREGISTERED // classes loaded outside of the boot/platform/app loaders; currently not supported by AOTClassLinker +}; + +#endif // SHARE_CDS_AOTCLASSLINKER_HPP diff --git a/src/hotspot/share/cds/aotConstantPoolResolver.cpp b/src/hotspot/share/cds/aotConstantPoolResolver.cpp new file mode 100644 index 00000000000..584be7085ce --- /dev/null +++ b/src/hotspot/share/cds/aotConstantPoolResolver.cpp @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2022, 2024, 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 "cds/aotClassLinker.hpp" +#include "cds/aotConstantPoolResolver.hpp" +#include "cds/archiveBuilder.hpp" +#include "cds/cdsConfig.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "classfile/vmClasses.hpp" +#include "interpreter/bytecodeStream.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "memory/resourceArea.hpp" +#include "oops/constantPool.inline.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/klass.inline.hpp" +#include "runtime/handles.inline.hpp" + +AOTConstantPoolResolver::ClassesTable* AOTConstantPoolResolver::_processed_classes = nullptr; + +void AOTConstantPoolResolver::initialize() { + assert(_processed_classes == nullptr, "must be"); + _processed_classes = new (mtClass)ClassesTable(); +} + +void AOTConstantPoolResolver::dispose() { + assert(_processed_classes != nullptr, "must be"); + delete _processed_classes; + _processed_classes = nullptr; +} + +// Returns true if we CAN PROVE that cp_index will always resolve to +// the same information at both dump time and run time. This is a +// necessary (but not sufficient) condition for pre-resolving cp_index +// during CDS archive assembly. +bool AOTConstantPoolResolver::is_resolution_deterministic(ConstantPool* cp, int cp_index) { + assert(!is_in_archivebuilder_buffer(cp), "sanity"); + + if (cp->tag_at(cp_index).is_klass()) { + // We require cp_index to be already resolved. This is fine for now, are we + // currently archive only CP entries that are already resolved. + Klass* resolved_klass = cp->resolved_klass_at(cp_index); + return resolved_klass != nullptr && is_class_resolution_deterministic(cp->pool_holder(), resolved_klass); + } else if (cp->tag_at(cp_index).is_invoke_dynamic()) { + return is_indy_resolution_deterministic(cp, cp_index); + } else if (cp->tag_at(cp_index).is_field() || + cp->tag_at(cp_index).is_method() || + cp->tag_at(cp_index).is_interface_method()) { + int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); + if (!cp->tag_at(klass_cp_index).is_klass()) { + // Not yet resolved + return false; + } + Klass* k = cp->resolved_klass_at(klass_cp_index); + if (!is_class_resolution_deterministic(cp->pool_holder(), k)) { + return false; + } + + if (!k->is_instance_klass()) { + // TODO: support non instance klasses as well. + return false; + } + + // Here, We don't check if this entry can actually be resolved to a valid Field/Method. + // This method should be called by the ConstantPool to check Fields/Methods that + // have already been successfully resolved. + return true; + } else { + return false; + } +} + +bool AOTConstantPoolResolver::is_class_resolution_deterministic(InstanceKlass* cp_holder, Klass* resolved_class) { + assert(!is_in_archivebuilder_buffer(cp_holder), "sanity"); + assert(!is_in_archivebuilder_buffer(resolved_class), "sanity"); + + if (resolved_class->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(resolved_class); + + if (!ik->is_shared() && SystemDictionaryShared::is_excluded_class(ik)) { + return false; + } + + if (cp_holder->is_subtype_of(ik)) { + // All super types of ik will be resolved in ik->class_loader() before + // ik is defined in this loader, so it's safe to archive the resolved klass reference. + return true; + } + + if (CDSConfig::is_dumping_aot_linked_classes()) { + // Need to call try_add_candidate instead of is_candidate, as this may be called + // before AOTClassLinker::add_candidates(). + if (AOTClassLinker::try_add_candidate(ik)) { + return true; + } else { + return false; + } + } else if (AOTClassLinker::is_vm_class(ik)) { + if (ik->class_loader() != cp_holder->class_loader()) { + // At runtime, cp_holder() may not be able to resolve to the same + // ik. For example, a different version of ik may be defined in + // cp->pool_holder()'s loader using MethodHandles.Lookup.defineClass(). + return false; + } else { + return true; + } + } else { + return false; + } + } else if (resolved_class->is_objArray_klass()) { + Klass* elem = ObjArrayKlass::cast(resolved_class)->bottom_klass(); + if (elem->is_instance_klass()) { + return is_class_resolution_deterministic(cp_holder, InstanceKlass::cast(elem)); + } else if (elem->is_typeArray_klass()) { + return true; + } else { + return false; + } + } else if (resolved_class->is_typeArray_klass()) { + return true; + } else { + return false; + } +} + +void AOTConstantPoolResolver::dumptime_resolve_constants(InstanceKlass* ik, TRAPS) { + if (!ik->is_linked()) { + return; + } + bool first_time; + _processed_classes->put_if_absent(ik, &first_time); + if (!first_time) { + // We have already resolved the constants in class, so no need to do it again. + return; + } + + constantPoolHandle cp(THREAD, ik->constants()); + for (int cp_index = 1; cp_index < cp->length(); cp_index++) { // Index 0 is unused + switch (cp->tag_at(cp_index).value()) { + case JVM_CONSTANT_String: + resolve_string(cp, cp_index, CHECK); // may throw OOM when interning strings. + break; + } + } +} + +// This works only for the boot/platform/app loaders +Klass* AOTConstantPoolResolver::find_loaded_class(Thread* current, oop class_loader, Symbol* name) { + HandleMark hm(current); + Handle h_loader(current, class_loader); + Klass* k = SystemDictionary::find_instance_or_array_klass(current, name, h_loader); + if (k != nullptr) { + return k; + } + if (h_loader() == SystemDictionary::java_system_loader()) { + return find_loaded_class(current, SystemDictionary::java_platform_loader(), name); + } else if (h_loader() == SystemDictionary::java_platform_loader()) { + return find_loaded_class(current, nullptr, name); + } else { + assert(h_loader() == nullptr, "This function only works for boot/platform/app loaders %p %p %p", + cast_from_oop
(h_loader()), + cast_from_oop
(SystemDictionary::java_system_loader()), + cast_from_oop
(SystemDictionary::java_platform_loader())); + } + + return nullptr; +} + +Klass* AOTConstantPoolResolver::find_loaded_class(Thread* current, ConstantPool* cp, int class_cp_index) { + Symbol* name = cp->klass_name_at(class_cp_index); + return find_loaded_class(current, cp->pool_holder()->class_loader(), name); +} + +#if INCLUDE_CDS_JAVA_HEAP +void AOTConstantPoolResolver::resolve_string(constantPoolHandle cp, int cp_index, TRAPS) { + if (CDSConfig::is_dumping_heap()) { + int cache_index = cp->cp_to_object_index(cp_index); + ConstantPool::string_at_impl(cp, cp_index, cache_index, CHECK); + } +} +#endif + +void AOTConstantPoolResolver::preresolve_class_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray* preresolve_list) { + if (!SystemDictionaryShared::is_builtin_loader(ik->class_loader_data())) { + return; + } + + JavaThread* THREAD = current; + constantPoolHandle cp(THREAD, ik->constants()); + for (int cp_index = 1; cp_index < cp->length(); cp_index++) { + if (cp->tag_at(cp_index).value() == JVM_CONSTANT_UnresolvedClass) { + if (preresolve_list != nullptr && preresolve_list->at(cp_index) == false) { + // This class was not resolved during trial run. Don't attempt to resolve it. Otherwise + // the compiler may generate less efficient code. + continue; + } + if (find_loaded_class(current, cp(), cp_index) == nullptr) { + // Do not resolve any class that has not been loaded yet + continue; + } + Klass* resolved_klass = cp->klass_at(cp_index, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; // just ignore + } else { + log_trace(cds, resolve)("Resolved class [%3d] %s -> %s", cp_index, ik->external_name(), + resolved_klass->external_name()); + } + } + } +} + +void AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray* preresolve_list) { + JavaThread* THREAD = current; + constantPoolHandle cp(THREAD, ik->constants()); + if (cp->cache() == nullptr) { + return; + } + for (int i = 0; i < ik->methods()->length(); i++) { + Method* m = ik->methods()->at(i); + BytecodeStream bcs(methodHandle(THREAD, m)); + while (!bcs.is_last_bytecode()) { + bcs.next(); + Bytecodes::Code raw_bc = bcs.raw_code(); + switch (raw_bc) { + case Bytecodes::_getfield: + case Bytecodes::_putfield: + maybe_resolve_fmi_ref(ik, m, raw_bc, bcs.get_index_u2(), preresolve_list, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; // just ignore + } + break; + case Bytecodes::_invokehandle: + case Bytecodes::_invokespecial: + case Bytecodes::_invokevirtual: + case Bytecodes::_invokeinterface: + maybe_resolve_fmi_ref(ik, m, raw_bc, bcs.get_index_u2(), preresolve_list, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; // just ignore + } + break; + default: + break; + } + } + } +} + +void AOTConstantPoolResolver::maybe_resolve_fmi_ref(InstanceKlass* ik, Method* m, Bytecodes::Code bc, int raw_index, + GrowableArray* preresolve_list, TRAPS) { + methodHandle mh(THREAD, m); + constantPoolHandle cp(THREAD, ik->constants()); + HandleMark hm(THREAD); + int cp_index = cp->to_cp_index(raw_index, bc); + + if (cp->is_resolved(raw_index, bc)) { + return; + } + + if (preresolve_list != nullptr && preresolve_list->at(cp_index) == false) { + // This field wasn't resolved during the trial run. Don't attempt to resolve it. Otherwise + // the compiler may generate less efficient code. + return; + } + + int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); + if (find_loaded_class(THREAD, cp(), klass_cp_index) == nullptr) { + // Do not resolve any field/methods from a class that has not been loaded yet. + return; + } + + Klass* resolved_klass = cp->klass_ref_at(raw_index, bc, CHECK); + + switch (bc) { + case Bytecodes::_getfield: + case Bytecodes::_putfield: + InterpreterRuntime::resolve_get_put(bc, raw_index, mh, cp, false /*initialize_holder*/, CHECK); + break; + + case Bytecodes::_invokevirtual: + case Bytecodes::_invokespecial: + case Bytecodes::_invokeinterface: + InterpreterRuntime::cds_resolve_invoke(bc, raw_index, cp, CHECK); + break; + + case Bytecodes::_invokehandle: + InterpreterRuntime::cds_resolve_invokehandle(raw_index, cp, CHECK); + break; + + default: + ShouldNotReachHere(); + } + + if (log_is_enabled(Trace, cds, resolve)) { + ResourceMark rm(THREAD); + bool resolved = cp->is_resolved(raw_index, bc); + Symbol* name = cp->name_ref_at(raw_index, bc); + Symbol* signature = cp->signature_ref_at(raw_index, bc); + log_trace(cds, resolve)("%s %s [%3d] %s -> %s.%s:%s", + (resolved ? "Resolved" : "Failed to resolve"), + Bytecodes::name(bc), cp_index, ik->external_name(), + resolved_klass->external_name(), + name->as_C_string(), signature->as_C_string()); + } +} + +void AOTConstantPoolResolver::preresolve_indy_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray* preresolve_list) { + JavaThread* THREAD = current; + constantPoolHandle cp(THREAD, ik->constants()); + if (!CDSConfig::is_dumping_invokedynamic() || cp->cache() == nullptr) { + return; + } + + assert(preresolve_list != nullptr, "preresolve_indy_cp_entries() should not be called for " + "regenerated LambdaForm Invoker classes, which should not have indys anyway."); + + Array* indy_entries = cp->cache()->resolved_indy_entries(); + for (int i = 0; i < indy_entries->length(); i++) { + ResolvedIndyEntry* rie = indy_entries->adr_at(i); + int cp_index = rie->constant_pool_index(); + if (preresolve_list->at(cp_index) == true) { + if (!rie->is_resolved() && is_indy_resolution_deterministic(cp(), cp_index)) { + InterpreterRuntime::cds_resolve_invokedynamic(i, cp, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; // just ignore + } + } + if (log_is_enabled(Trace, cds, resolve)) { + ResourceMark rm(THREAD); + log_trace(cds, resolve)("%s indy [%3d] %s", + rie->is_resolved() ? "Resolved" : "Failed to resolve", + cp_index, ik->external_name()); + } + } + } +} + +// Check the MethodType signatures used by parameters to the indy BSMs. Make sure we don't +// use types that have been excluded, or else we might end up creating MethodTypes that cannot be stored +// in the AOT cache. +bool AOTConstantPoolResolver::check_methodtype_signature(ConstantPool* cp, Symbol* sig, Klass** return_type_ret) { + ResourceMark rm; + for (SignatureStream ss(sig); !ss.is_done(); ss.next()) { + if (ss.is_reference()) { + Symbol* type = ss.as_symbol(); + Klass* k = find_loaded_class(Thread::current(), cp->pool_holder()->class_loader(), type); + if (k == nullptr) { + return false; + } + + if (SystemDictionaryShared::should_be_excluded(k)) { + if (log_is_enabled(Warning, cds, resolve)) { + ResourceMark rm; + log_warning(cds, resolve)("Cannot aot-resolve Lambda proxy because %s is excluded", k->external_name()); + } + return false; + } + + if (ss.at_return_type() && return_type_ret != nullptr) { + *return_type_ret = k; + } + } + } + return true; +} + +bool AOTConstantPoolResolver::check_lambda_metafactory_signature(ConstantPool* cp, Symbol* sig) { + Klass* k; + if (!check_methodtype_signature(cp, sig, &k)) { + return false; + } + + // is the interface type implemented by the lambda proxy + if (!k->is_interface()) { + // cp->pool_holder() doesn't look like a valid class generated by javac + return false; + } + + + // The linked lambda callsite has an instance of the interface implemented by this lambda. If this + // interface requires its to be executed, then we must delay the execution to the production run + // as can have side effects ==> exclude such cases. + InstanceKlass* intf = InstanceKlass::cast(k); + bool exclude = intf->interface_needs_clinit_execution_as_super(); + if (log_is_enabled(Debug, cds, resolve)) { + ResourceMark rm; + log_debug(cds, resolve)("%s aot-resolve Lambda proxy of interface type %s", + exclude ? "Cannot" : "Can", k->external_name()); + } + return !exclude; +} + +bool AOTConstantPoolResolver::check_lambda_metafactory_methodtype_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i) { + int mt_index = cp->operand_argument_index_at(bsms_attribute_index, arg_i); + if (!cp->tag_at(mt_index).is_method_type()) { + // malformed class? + return false; + } + + Symbol* sig = cp->method_type_signature_at(mt_index); + if (log_is_enabled(Debug, cds, resolve)) { + ResourceMark rm; + log_debug(cds, resolve)("Checking MethodType for LambdaMetafactory BSM arg %d: %s", arg_i, sig->as_C_string()); + } + + return check_methodtype_signature(cp, sig); +} + +bool AOTConstantPoolResolver::check_lambda_metafactory_methodhandle_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i) { + int mh_index = cp->operand_argument_index_at(bsms_attribute_index, arg_i); + if (!cp->tag_at(mh_index).is_method_handle()) { + // malformed class? + return false; + } + + Symbol* sig = cp->method_handle_signature_ref_at(mh_index); + if (log_is_enabled(Debug, cds, resolve)) { + ResourceMark rm; + log_debug(cds, resolve)("Checking MethodType of MethodHandle for LambdaMetafactory BSM arg %d: %s", arg_i, sig->as_C_string()); + } + return check_methodtype_signature(cp, sig); +} + +bool AOTConstantPoolResolver::is_indy_resolution_deterministic(ConstantPool* cp, int cp_index) { + assert(cp->tag_at(cp_index).is_invoke_dynamic(), "sanity"); + if (!CDSConfig::is_dumping_invokedynamic()) { + return false; + } + + InstanceKlass* pool_holder = cp->pool_holder(); + if (!SystemDictionaryShared::is_builtin(pool_holder)) { + return false; + } + + int bsm = cp->bootstrap_method_ref_index_at(cp_index); + int bsm_ref = cp->method_handle_index_at(bsm); + Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref); + Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref); + Symbol* bsm_klass = cp->klass_name_at(cp->uncached_klass_ref_index_at(bsm_ref)); + + // We currently support only StringConcatFactory::makeConcatWithConstants() and LambdaMetafactory::metafactory() + // We should mark the allowed BSMs in the JDK code using a private annotation. + // See notes on RFE JDK-8342481. + + if (bsm_klass->equals("java/lang/invoke/StringConcatFactory") && + bsm_name->equals("makeConcatWithConstants") && + bsm_signature->equals("(Ljava/lang/invoke/MethodHandles$Lookup;" + "Ljava/lang/String;" + "Ljava/lang/invoke/MethodType;" + "Ljava/lang/String;" + "[Ljava/lang/Object;" + ")Ljava/lang/invoke/CallSite;")) { + Symbol* factory_type_sig = cp->uncached_signature_ref_at(cp_index); + if (log_is_enabled(Debug, cds, resolve)) { + ResourceMark rm; + log_debug(cds, resolve)("Checking StringConcatFactory callsite signature [%d]: %s", cp_index, factory_type_sig->as_C_string()); + } + + Klass* k; + if (!check_methodtype_signature(cp, factory_type_sig, &k)) { + return false; + } + if (k != vmClasses::String_klass()) { + // bad class file? + return false; + } + + return true; + } + + if (bsm_klass->equals("java/lang/invoke/LambdaMetafactory") && + bsm_name->equals("metafactory") && + bsm_signature->equals("(Ljava/lang/invoke/MethodHandles$Lookup;" + "Ljava/lang/String;" + "Ljava/lang/invoke/MethodType;" + "Ljava/lang/invoke/MethodType;" + "Ljava/lang/invoke/MethodHandle;" + "Ljava/lang/invoke/MethodType;" + ")Ljava/lang/invoke/CallSite;")) { + /* + * An indy callsite is associated with the following MethodType and MethodHandles: + * + * https://github.com/openjdk/jdk/blob/580eb62dc097efeb51c76b095c1404106859b673/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java#L293-L309 + * + * MethodType factoryType The expected signature of the {@code CallSite}. The + * parameter types represent the types of capture variables; + * the return type is the interface to implement. When + * used with {@code invokedynamic}, this is provided by + * the {@code NameAndType} of the {@code InvokeDynamic} + * + * MethodType interfaceMethodType Signature and return type of method to be + * implemented by the function object. + * + * MethodHandle implementation A direct method handle describing the implementation + * method which should be called (with suitable adaptation + * of argument types and return types, and with captured + * arguments prepended to the invocation arguments) at + * invocation time. + * + * MethodType dynamicMethodType The signature and return type that should + * be enforced dynamically at invocation time. + * In simple use cases this is the same as + * {@code interfaceMethodType}. + */ + Symbol* factory_type_sig = cp->uncached_signature_ref_at(cp_index); + if (log_is_enabled(Debug, cds, resolve)) { + ResourceMark rm; + log_debug(cds, resolve)("Checking indy callsite signature [%d]: %s", cp_index, factory_type_sig->as_C_string()); + } + + if (!check_lambda_metafactory_signature(cp, factory_type_sig)) { + return false; + } + + int bsms_attribute_index = cp->bootstrap_methods_attribute_index(cp_index); + int arg_count = cp->operand_argument_count_at(bsms_attribute_index); + if (arg_count != 3) { + // Malformed class? + return false; + } + + // interfaceMethodType + if (!check_lambda_metafactory_methodtype_arg(cp, bsms_attribute_index, 0)) { + return false; + } + + // implementation + if (!check_lambda_metafactory_methodhandle_arg(cp, bsms_attribute_index, 1)) { + return false; + } + + // dynamicMethodType + if (!check_lambda_metafactory_methodtype_arg(cp, bsms_attribute_index, 2)) { + return false; + } + + return true; + } + + return false; +} +#ifdef ASSERT +bool AOTConstantPoolResolver::is_in_archivebuilder_buffer(address p) { + if (!Thread::current()->is_VM_thread() || ArchiveBuilder::current() == nullptr) { + return false; + } else { + return ArchiveBuilder::current()->is_in_buffer_space(p); + } +} +#endif diff --git a/src/hotspot/share/cds/classPrelinker.hpp b/src/hotspot/share/cds/aotConstantPoolResolver.hpp similarity index 73% rename from src/hotspot/share/cds/classPrelinker.hpp rename to src/hotspot/share/cds/aotConstantPoolResolver.hpp index 41588961d8b..2f65849fbb4 100644 --- a/src/hotspot/share/cds/classPrelinker.hpp +++ b/src/hotspot/share/cds/aotConstantPoolResolver.hpp @@ -22,13 +22,13 @@ * */ -#ifndef SHARE_CDS_CLASSPRELINKER_HPP -#define SHARE_CDS_CLASSPRELINKER_HPP +#ifndef SHARE_CDS_AOTCONSTANTPOOLRESOLVER_HPP +#define SHARE_CDS_AOTCONSTANTPOOLRESOLVER_HPP #include "interpreter/bytecodes.hpp" -#include "oops/oopsHierarchy.hpp" #include "memory/allStatic.hpp" #include "memory/allocation.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/handles.hpp" #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" @@ -39,7 +39,9 @@ class constantPoolHandle; class InstanceKlass; class Klass; -// ClassPrelinker is used to perform ahead-of-time linking of ConstantPool entries +template class GrowableArray; + +// AOTConstantPoolResolver is used to perform ahead-of-time linking of ConstantPool entries // for archived InstanceKlasses. // // At run time, Java classes are loaded dynamically and may be replaced with JVMTI. @@ -49,23 +51,21 @@ class Klass; // For example, a JVM_CONSTANT_Class reference to a supertype can be safely resolved // at dump time, because at run time we will load a class from the CDS archive only // if all of its supertypes are loaded from the CDS archive. -class ClassPrelinker : AllStatic { - using ClassesTable = ResourceHashtable ; +class AOTConstantPoolResolver : AllStatic { + static const int TABLE_SIZE = 15889; // prime number + using ClassesTable = ResourceHashtable ; static ClassesTable* _processed_classes; - static ClassesTable* _vm_classes; - - static void add_one_vm_class(InstanceKlass* ik); #ifdef ASSERT + template static bool is_in_archivebuilder_buffer(T p) { + return is_in_archivebuilder_buffer((address)(p)); + } static bool is_in_archivebuilder_buffer(address p); #endif - template - static bool is_in_archivebuilder_buffer(T p) { - return is_in_archivebuilder_buffer((address)(p)); - } static void resolve_string(constantPoolHandle cp, int cp_index, TRAPS) NOT_CDS_JAVA_HEAP_RETURN; static bool is_class_resolution_deterministic(InstanceKlass* cp_holder, Klass* resolved_class); + static bool is_indy_resolution_deterministic(ConstantPool* cp, int cp_index); static Klass* find_loaded_class(Thread* current, oop class_loader, Symbol* name); static Klass* find_loaded_class(Thread* current, ConstantPool* cp, int class_cp_index); @@ -73,18 +73,20 @@ class ClassPrelinker : AllStatic { // fmi = FieldRef/MethodRef/InterfaceMethodRef static void maybe_resolve_fmi_ref(InstanceKlass* ik, Method* m, Bytecodes::Code bc, int raw_index, GrowableArray* resolve_fmi_list, TRAPS); + + static bool check_methodtype_signature(ConstantPool* cp, Symbol* sig, Klass** return_type_ret = nullptr); + static bool check_lambda_metafactory_signature(ConstantPool* cp, Symbol* sig); + static bool check_lambda_metafactory_methodtype_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i); + static bool check_lambda_metafactory_methodhandle_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i); + public: static void initialize(); static void dispose(); static void preresolve_class_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray* preresolve_list); static void preresolve_field_and_method_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray* preresolve_list); + static void preresolve_indy_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray* preresolve_list); - // Is this class resolved as part of vmClasses::resolve_all()? If so, these - // classes are guatanteed to be loaded at runtime (and cannot be replaced by JVMTI) - // when CDS is enabled. Therefore, we can safely keep a direct reference to these - // classes. - static bool is_vm_class(InstanceKlass* ik); // Resolve all constant pool entries that are safe to be stored in the // CDS archive. @@ -93,4 +95,4 @@ class ClassPrelinker : AllStatic { static bool is_resolution_deterministic(ConstantPool* cp, int cp_index); }; -#endif // SHARE_CDS_CLASSPRELINKER_HPP +#endif // SHARE_CDS_AOTCONSTANTPOOLRESOLVER_HPP diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp new file mode 100644 index 00000000000..9bab6042436 --- /dev/null +++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2024, 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 "cds/aotClassInitializer.hpp" +#include "cds/aotClassLinker.hpp" +#include "cds/aotLinkedClassBulkLoader.hpp" +#include "cds/aotLinkedClassTable.hpp" +#include "cds/cdsConfig.hpp" +#include "cds/heapShared.hpp" +#include "classfile/classLoaderData.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "classfile/vmClasses.hpp" +#include "gc/shared/gcVMOperations.hpp" +#include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/klass.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/java.hpp" + +bool AOTLinkedClassBulkLoader::_boot2_completed = false; +bool AOTLinkedClassBulkLoader::_platform_completed = false; +bool AOTLinkedClassBulkLoader::_app_completed = false; +bool AOTLinkedClassBulkLoader::_all_completed = false; + +void AOTLinkedClassBulkLoader::serialize(SerializeClosure* soc, bool is_static_archive) { + AOTLinkedClassTable::get(is_static_archive)->serialize(soc); +} + +void AOTLinkedClassBulkLoader::load_javabase_classes(JavaThread* current) { + assert(CDSConfig::is_using_aot_linked_classes(), "sanity"); + load_classes_in_loader(current, AOTLinkedClassCategory::BOOT1, nullptr); // only java.base classes +} + +void AOTLinkedClassBulkLoader::load_non_javabase_classes(JavaThread* current) { + assert(CDSConfig::is_using_aot_linked_classes(), "sanity"); + + // is_using_aot_linked_classes() requires is_using_full_module_graph(). As a result, + // the platform/system class loader should already have been initialized as part + // of the FMG support. + assert(CDSConfig::is_using_full_module_graph(), "must be"); + assert(SystemDictionary::java_platform_loader() != nullptr, "must be"); + assert(SystemDictionary::java_system_loader() != nullptr, "must be"); + + load_classes_in_loader(current, AOTLinkedClassCategory::BOOT2, nullptr); // all boot classes outside of java.base + _boot2_completed = true; + + load_classes_in_loader(current, AOTLinkedClassCategory::PLATFORM, SystemDictionary::java_platform_loader()); + _platform_completed = true; + + load_classes_in_loader(current, AOTLinkedClassCategory::APP, SystemDictionary::java_system_loader()); + _app_completed = true; + _all_completed = true; +} + +void AOTLinkedClassBulkLoader::load_classes_in_loader(JavaThread* current, AOTLinkedClassCategory class_category, oop class_loader_oop) { + load_classes_in_loader_impl(class_category, class_loader_oop, current); + if (current->has_pending_exception()) { + // We cannot continue, as we might have loaded some of the aot-linked classes, which + // may have dangling C++ pointers to other aot-linked classes that we have failed to load. + exit_on_exception(current); + } +} + +void AOTLinkedClassBulkLoader::exit_on_exception(JavaThread* current) { + assert(current->has_pending_exception(), "precondition"); + ResourceMark rm(current); + if (current->pending_exception()->is_a(vmClasses::OutOfMemoryError_klass())) { + log_error(cds)("Out of memory. Please run with a larger Java heap, current MaxHeapSize = " + SIZE_FORMAT "M", MaxHeapSize/M); + } else { + log_error(cds)("%s: %s", current->pending_exception()->klass()->external_name(), + java_lang_String::as_utf8_string(java_lang_Throwable::message(current->pending_exception()))); + } + vm_exit_during_initialization("Unexpected exception when loading aot-linked classes."); +} + +void AOTLinkedClassBulkLoader::load_classes_in_loader_impl(AOTLinkedClassCategory class_category, oop class_loader_oop, TRAPS) { + Handle h_loader(THREAD, class_loader_oop); + load_table(AOTLinkedClassTable::for_static_archive(), class_category, h_loader, CHECK); + load_table(AOTLinkedClassTable::for_dynamic_archive(), class_category, h_loader, CHECK); + + // Initialize the InstanceKlasses of all archived heap objects that are reachable from the + // archived java class mirrors. + // + // Only the classes in the static archive can have archived mirrors. + AOTLinkedClassTable* static_table = AOTLinkedClassTable::for_static_archive(); + switch (class_category) { + case AOTLinkedClassCategory::BOOT1: + // Delayed until finish_loading_javabase_classes(), as the VM is not ready to + // execute some of the methods. + break; + case AOTLinkedClassCategory::BOOT2: + init_required_classes_for_loader(h_loader, static_table->boot2(), CHECK); + break; + case AOTLinkedClassCategory::PLATFORM: + init_required_classes_for_loader(h_loader, static_table->platform(), CHECK); + break; + case AOTLinkedClassCategory::APP: + init_required_classes_for_loader(h_loader, static_table->app(), CHECK); + break; + case AOTLinkedClassCategory::UNREGISTERED: + ShouldNotReachHere(); + break; + } + + if (Universe::is_fully_initialized() && VerifyDuringStartup) { + // Make sure we're still in a clean state. + VM_Verify verify_op; + VMThread::execute(&verify_op); + } +} + +void AOTLinkedClassBulkLoader::load_table(AOTLinkedClassTable* table, AOTLinkedClassCategory class_category, Handle loader, TRAPS) { + if (class_category != AOTLinkedClassCategory::BOOT1) { + assert(Universe::is_module_initialized(), "sanity"); + } + + const char* category_name = AOTClassLinker::class_category_name(class_category); + switch (class_category) { + case AOTLinkedClassCategory::BOOT1: + load_classes_impl(class_category, table->boot(), category_name, loader, CHECK); + break; + + case AOTLinkedClassCategory::BOOT2: + load_classes_impl(class_category, table->boot2(), category_name, loader, CHECK); + break; + + case AOTLinkedClassCategory::PLATFORM: + { + initiate_loading(THREAD, category_name, loader, table->boot()); + initiate_loading(THREAD, category_name, loader, table->boot2()); + load_classes_impl(class_category, table->platform(), category_name, loader, CHECK); + } + break; + case AOTLinkedClassCategory::APP: + { + initiate_loading(THREAD, category_name, loader, table->boot()); + initiate_loading(THREAD, category_name, loader, table->boot2()); + initiate_loading(THREAD, category_name, loader, table->platform()); + load_classes_impl(class_category, table->app(), category_name, loader, CHECK); + } + break; + case AOTLinkedClassCategory::UNREGISTERED: + default: + ShouldNotReachHere(); // Currently aot-linked classes are not supported for this category. + break; + } +} + +void AOTLinkedClassBulkLoader::load_classes_impl(AOTLinkedClassCategory class_category, Array* classes, + const char* category_name, Handle loader, TRAPS) { + if (classes == nullptr) { + return; + } + + ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(loader()); + + for (int i = 0; i < classes->length(); i++) { + InstanceKlass* ik = classes->at(i); + if (log_is_enabled(Info, cds, aot, load)) { + ResourceMark rm(THREAD); + log_info(cds, aot, load)("%-5s %s%s%s", category_name, ik->external_name(), + ik->is_loaded() ? " (already loaded)" : "", + ik->is_hidden() ? " (hidden)" : ""); + } + + if (!ik->is_loaded()) { + if (ik->is_hidden()) { + load_hidden_class(loader_data, ik, CHECK); + } else { + InstanceKlass* actual; + if (loader_data == ClassLoaderData::the_null_class_loader_data()) { + actual = SystemDictionary::load_instance_class(ik->name(), loader, CHECK); + } else { + actual = SystemDictionaryShared::find_or_load_shared_class(ik->name(), loader, CHECK); + } + + if (actual != ik) { + ResourceMark rm(THREAD); + log_error(cds)("Unable to resolve %s class from CDS archive: %s", category_name, ik->external_name()); + log_error(cds)("Expected: " INTPTR_FORMAT ", actual: " INTPTR_FORMAT, p2i(ik), p2i(actual)); + log_error(cds)("JVMTI class retransformation is not supported when archive was generated with -XX:+AOTClassLinking."); + MetaspaceShared::unrecoverable_loading_error(); + } + assert(actual->is_loaded(), "must be"); + } + } + } +} + +// Initiate loading of the in the . The should have already been loaded +// by a parent loader of the . This is necessary for handling pre-resolved CP entries. +// +// For example, we initiate the loading of java/lang/String in the AppClassLoader. This will allow +// any App classes to have a pre-resolved ConstantPool entry that references java/lang/String. +// +// TODO: we can limit the number of initiated classes to only those that are actually referenced by +// AOT-linked classes loaded by . +void AOTLinkedClassBulkLoader::initiate_loading(JavaThread* current, const char* category_name, + Handle initiating_loader, Array* classes) { + if (classes == nullptr) { + return; + } + + assert(initiating_loader() == SystemDictionary::java_platform_loader() || + initiating_loader() == SystemDictionary::java_system_loader(), "must be"); + ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(initiating_loader()); + MonitorLocker mu1(SystemDictionary_lock); + + for (int i = 0; i < classes->length(); i++) { + InstanceKlass* ik = classes->at(i); + assert(ik->is_loaded(), "must have already been loaded by a parent loader"); + assert(ik->class_loader() != initiating_loader(), "must be a parent loader"); + assert(ik->class_loader() == nullptr || + ik->class_loader() == SystemDictionary::java_platform_loader(), "must be"); + if (ik->is_public() && !ik->is_hidden()) { + if (log_is_enabled(Info, cds, aot, load)) { + ResourceMark rm(current); + const char* defining_loader = (ik->class_loader() == nullptr ? "boot" : "plat"); + log_info(cds, aot, load)("%s %s (initiated, defined by %s)", category_name, ik->external_name(), + defining_loader); + } + SystemDictionary::add_to_initiating_loader(current, ik, loader_data); + } + } +} + +// Currently, we archive only three types of hidden classes: +// - LambdaForms +// - lambda proxy classes +// - StringConcat classes +// See HeapShared::is_archivable_hidden_klass(). +// +// LambdaForm classes (with names like java/lang/invoke/LambdaForm$MH+0x800000015) logically +// belong to the boot loader, but they are usually stored in their own special ClassLoaderData to +// facilitate class unloading, as a LambdaForm may refer to a class loaded by a custom loader +// that may be unloaded. +// +// We only support AOT-resolution of indys in the boot/platform/app loader, so there's no need +// to support class unloading. For simplicity, we put all archived LambdaForm classes in the +// "main" ClassLoaderData of the boot loader. +// +// (Even if we were to support other loaders, we would still feel free to ignore any requirement +// of class unloading, for any class asset in the AOT cache. Anything that makes it into the AOT +// cache has a lifetime dispensation from unloading. After all, the AOT cache never grows, and +// we can assume that the user is content with its size, and doesn't need its footprint to shrink.) +// +// Lambda proxy classes are normally stored in the same ClassLoaderData as their nest hosts, and +// StringConcat are normally stored in the main ClassLoaderData of the boot class loader. We +// do the same for the archived copies of such classes. +void AOTLinkedClassBulkLoader::load_hidden_class(ClassLoaderData* loader_data, InstanceKlass* ik, TRAPS) { + assert(HeapShared::is_lambda_form_klass(ik) || + HeapShared::is_lambda_proxy_klass(ik) || + HeapShared::is_string_concat_klass(ik), "sanity"); + DEBUG_ONLY({ + assert(ik->java_super()->is_loaded(), "must be"); + for (int i = 0; i < ik->local_interfaces()->length(); i++) { + assert(ik->local_interfaces()->at(i)->is_loaded(), "must be"); + } + }); + + Handle pd; + PackageEntry* pkg_entry = nullptr; + + // Since a hidden class does not have a name, it cannot be reloaded + // normally via the system dictionary. Instead, we have to finish the + // loading job here. + + if (HeapShared::is_lambda_proxy_klass(ik)) { + InstanceKlass* nest_host = ik->nest_host_not_null(); + assert(nest_host->is_loaded(), "must be"); + pd = Handle(THREAD, nest_host->protection_domain()); + pkg_entry = nest_host->package(); + } + + ik->restore_unshareable_info(loader_data, pd, pkg_entry, CHECK); + SystemDictionary::load_shared_class_misc(ik, loader_data); + ik->add_to_hierarchy(THREAD); + assert(ik->is_loaded(), "Must be in at least loaded state"); + + DEBUG_ONLY({ + // Make sure we don't make this hidden class available by name, even if we don't + // use any special ClassLoaderData. + Handle loader(THREAD, loader_data->class_loader()); + ResourceMark rm(THREAD); + assert(SystemDictionary::resolve_or_null(ik->name(), loader, THREAD) == nullptr, + "hidden classes cannot be accessible by name: %s", ik->external_name()); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } + }); +} + +void AOTLinkedClassBulkLoader::finish_loading_javabase_classes(TRAPS) { + init_required_classes_for_loader(Handle(), AOTLinkedClassTable::for_static_archive()->boot(), CHECK); +} + +// Some AOT-linked classes for must be initialized early. This includes +// - classes that were AOT-initialized by AOTClassInitializer +// - the classes of all objects that are reachable from the archived mirrors of +// the AOT-linked classes for . +void AOTLinkedClassBulkLoader::init_required_classes_for_loader(Handle class_loader, Array* classes, TRAPS) { + if (classes != nullptr) { + for (int i = 0; i < classes->length(); i++) { + InstanceKlass* ik = classes->at(i); + if (ik->class_loader_data() == nullptr) { + // This class is not yet loaded. We will initialize it in a later phase. + // For example, we have loaded only AOTLinkedClassCategory::BOOT1 classes + // but k is part of AOTLinkedClassCategory::BOOT2. + continue; + } + if (ik->has_aot_initialized_mirror()) { + ik->initialize_with_aot_initialized_mirror(CHECK); + } else { + // Some cached heap objects may hold references to methods in aot-linked + // classes (via MemberName). We need to make sure all classes are + // linked to allow such MemberNames to be invoked. + ik->link_class(CHECK); + } + } + } + + HeapShared::init_classes_for_special_subgraph(class_loader, CHECK); +} + +bool AOTLinkedClassBulkLoader::is_pending_aot_linked_class(Klass* k) { + if (!CDSConfig::is_using_aot_linked_classes()) { + return false; + } + + if (_all_completed) { // no more pending aot-linked classes + return false; + } + + if (k->is_objArray_klass()) { + k = ObjArrayKlass::cast(k)->bottom_klass(); + } + if (!k->is_instance_klass()) { + // type array klasses (and their higher dimensions), + // must have been loaded before a GC can ever happen. + return false; + } + + // There's a small window during VM start-up where a not-yet loaded aot-linked + // class k may be discovered by the GC during VM initialization. This can happen + // when the heap contains an aot-cached instance of k, but k is not ready to be + // loaded yet. (TODO: JDK-8342429 eliminates this possibility) + // + // The following checks try to limit this window as much as possible for each of + // the four AOTLinkedClassCategory of classes that can be aot-linked. + + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->is_shared_boot_class()) { + if (ik->module() != nullptr && ik->in_javabase_module()) { + // AOTLinkedClassCategory::BOOT1 -- all aot-linked classes in + // java.base must have been loaded before a GC can ever happen. + return false; + } else { + // AOTLinkedClassCategory::BOOT2 classes cannot be loaded until + // module system is ready. + return !_boot2_completed; + } + } else if (ik->is_shared_platform_class()) { + // AOTLinkedClassCategory::PLATFORM classes cannot be loaded until + // the platform class loader is initialized. + return !_platform_completed; + } else if (ik->is_shared_app_class()) { + // AOTLinkedClassCategory::APP cannot be loaded until the app class loader + // is initialized. + return !_app_completed; + } else { + return false; + } +} diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp new file mode 100644 index 00000000000..a8e6365b899 --- /dev/null +++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024, 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_CDS_AOTLINKEDCLASSBULKLOADER_HPP +#define SHARE_CDS_AOTLINKEDCLASSBULKLOADER_HPP + +#include "memory/allStatic.hpp" +#include "memory/allocation.hpp" +#include "runtime/handles.hpp" +#include "utilities/exceptions.hpp" +#include "utilities/macros.hpp" + +class AOTLinkedClassTable; +class ClassLoaderData; +class InstanceKlass; +class SerializeClosure; +template class Array; +enum class AOTLinkedClassCategory : int; + +// During a Production Run, the AOTLinkedClassBulkLoader loads all classes from +// a AOTLinkedClassTable into their respective ClassLoaders. This happens very early +// in the JVM bootstrap stage, before any application code is executed. +// +class AOTLinkedClassBulkLoader : AllStatic { + static bool _boot2_completed; + static bool _platform_completed; + static bool _app_completed; + static bool _all_completed; + static void load_classes_in_loader(JavaThread* current, AOTLinkedClassCategory class_category, oop class_loader_oop); + static void load_classes_in_loader_impl(AOTLinkedClassCategory class_category, oop class_loader_oop, TRAPS); + static void load_table(AOTLinkedClassTable* table, AOTLinkedClassCategory class_category, Handle loader, TRAPS); + static void initiate_loading(JavaThread* current, const char* category, Handle initiating_loader, Array* classes); + static void load_classes_impl(AOTLinkedClassCategory class_category, Array* classes, + const char* category_name, Handle loader, TRAPS); + static void load_hidden_class(ClassLoaderData* loader_data, InstanceKlass* ik, TRAPS); + static void init_required_classes_for_loader(Handle class_loader, Array* classes, TRAPS); +public: + static void serialize(SerializeClosure* soc, bool is_static_archive) NOT_CDS_RETURN; + + static void load_javabase_classes(JavaThread* current) NOT_CDS_RETURN; + static void load_non_javabase_classes(JavaThread* current) NOT_CDS_RETURN; + static void finish_loading_javabase_classes(TRAPS) NOT_CDS_RETURN; + static void exit_on_exception(JavaThread* current); + + static bool is_pending_aot_linked_class(Klass* k) NOT_CDS_RETURN_(false); +}; + +#endif // SHARE_CDS_AOTLINKEDCLASSBULKLOADER_HPP diff --git a/src/hotspot/share/cds/aotLinkedClassTable.cpp b/src/hotspot/share/cds/aotLinkedClassTable.cpp new file mode 100644 index 00000000000..bed090f00a9 --- /dev/null +++ b/src/hotspot/share/cds/aotLinkedClassTable.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, 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 "cds/aotLinkedClassTable.hpp" +#include "cds/cdsConfig.hpp" +#include "cds/serializeClosure.hpp" +#include "oops/array.hpp" + +AOTLinkedClassTable AOTLinkedClassTable::_for_static_archive; +AOTLinkedClassTable AOTLinkedClassTable::_for_dynamic_archive; + +void AOTLinkedClassTable::serialize(SerializeClosure* soc) { + soc->do_ptr((void**)&_boot); + soc->do_ptr((void**)&_boot2); + soc->do_ptr((void**)&_platform); + soc->do_ptr((void**)&_app); +} + diff --git a/src/hotspot/share/cds/aotLinkedClassTable.hpp b/src/hotspot/share/cds/aotLinkedClassTable.hpp new file mode 100644 index 00000000000..2a199c15edd --- /dev/null +++ b/src/hotspot/share/cds/aotLinkedClassTable.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024, 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_CDS_AOTLINKEDCLASSTABLE_HPP +#define SHARE_CDS_AOTLINKEDCLASSTABLE_HPP + +#include "utilities/globalDefinitions.hpp" + +template class Array; +class InstanceKlass; +class SerializeClosure; + +// Classes to be bulk-loaded, in the "linked" state, at VM bootstrap. +// +// AOTLinkedClassTable is produced by AOTClassLinker when an AOTCache is assembled. +// +// AOTLinkedClassTable is consumed by AOTLinkedClassBulkLoader when an AOTCache is used +// in a production run. +// +class AOTLinkedClassTable { + // The VM may load up to 2 CDS archives -- static and dynamic. Each + // archive can have its own AOTLinkedClassTable. + static AOTLinkedClassTable _for_static_archive; + static AOTLinkedClassTable _for_dynamic_archive; + + Array* _boot; // only java.base classes + Array* _boot2; // boot classes in other modules + Array* _platform; + Array* _app; + +public: + AOTLinkedClassTable() : + _boot(nullptr), _boot2(nullptr), + _platform(nullptr), _app(nullptr) {} + + static AOTLinkedClassTable* for_static_archive() { return &_for_static_archive; } + static AOTLinkedClassTable* for_dynamic_archive() { return &_for_dynamic_archive; } + + static AOTLinkedClassTable* get(bool is_static_archive) { + return is_static_archive ? for_static_archive() : for_dynamic_archive(); + } + + Array* boot() const { return _boot; } + Array* boot2() const { return _boot2; } + Array* platform() const { return _platform; } + Array* app() const { return _app; } + + void set_boot (Array* value) { _boot = value; } + void set_boot2 (Array* value) { _boot2 = value; } + void set_platform(Array* value) { _platform = value; } + void set_app (Array* value) { _app = value; } + + void serialize(SerializeClosure* soc); +}; + +#endif // SHARE_CDS_AOTLINKEDCLASSTABLE_HPP diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index a181257a519..36a17813d32 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -23,6 +23,8 @@ */ #include "precompiled.hpp" +#include "cds/aotClassLinker.hpp" +#include "cds/aotLinkedClassBulkLoader.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveHeapWriter.hpp" #include "cds/archiveUtils.hpp" @@ -33,7 +35,9 @@ #include "cds/heapShared.hpp" #include "cds/metaspaceShared.hpp" #include "cds/regeneratedClasses.hpp" +#include "classfile/classLoader.hpp" #include "classfile/classLoaderDataShared.hpp" +#include "classfile/classLoaderExt.hpp" #include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionaryShared.hpp" @@ -226,6 +230,10 @@ bool ArchiveBuilder::gather_klass_and_symbol(MetaspaceClosure::Ref* ref, bool re assert(klass->is_klass(), "must be"); if (!is_excluded(klass)) { _klasses->append(klass); + if (klass->is_hidden()) { + assert(klass->is_instance_klass(), "must be"); + assert(SystemDictionaryShared::should_hidden_class_be_archived(InstanceKlass::cast(klass)), "must be"); + } } // See RunTimeClassInfo::get_for(): make sure we have enough space for both maximum // Klass alignment as well as the RuntimeInfo* pointer we will embed in front of a Klass. @@ -284,6 +292,8 @@ void ArchiveBuilder::gather_klasses_and_symbols() { // but this should be enough for now _estimated_metaspaceobj_bytes += 200 * 1024 * 1024; } + + AOTClassLinker::add_candidates(); } int ArchiveBuilder::compare_symbols_by_address(Symbol** a, Symbol** b) { @@ -310,6 +320,15 @@ size_t ArchiveBuilder::estimate_archive_size() { size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive(); _estimated_hashtable_bytes = symbol_table_est + dictionary_est; + if (CDSConfig::is_dumping_aot_linked_classes()) { + // This is difficult to estimate when dumping the dynamic archive, as the + // AOTLinkedClassTable may need to contain classes in the static archive as well. + // + // Just give a generous estimate for now. We will remove estimate_archive_size() + // in JDK-8340416 + _estimated_hashtable_bytes += 20 * 1024 * 1024; + } + size_t total = 0; total += _estimated_metaspaceobj_bytes; @@ -423,11 +442,12 @@ bool ArchiveBuilder::gather_one_source_obj(MetaspaceClosure::Ref* ref, bool read if (src_obj == nullptr) { return false; } + + remember_embedded_pointer_in_enclosing_obj(ref); if (RegeneratedClasses::has_been_regenerated(src_obj)) { // No need to copy it. We will later relocate it to point to the regenerated klass/method. return false; } - remember_embedded_pointer_in_enclosing_obj(ref); FollowMode follow_mode = get_follow_mode(ref); SourceObjInfo src_info(ref, read_only, follow_mode); @@ -740,6 +760,16 @@ void ArchiveBuilder::mark_and_relocate_to_buffered_addr(address* ptr_location) { ArchivePtrMarker::mark_pointer(ptr_location); } +bool ArchiveBuilder::has_been_buffered(address src_addr) const { + if (RegeneratedClasses::has_been_regenerated(src_addr) || + _src_obj_table.get(src_addr) == nullptr || + get_buffered_addr(src_addr) == nullptr) { + return false; + } else { + return true; + } +} + address ArchiveBuilder::get_buffered_addr(address src_addr) const { SourceObjInfo* p = _src_obj_table.get(src_addr); assert(p != nullptr, "src_addr " INTPTR_FORMAT " is used but has not been archived", @@ -767,17 +797,35 @@ void ArchiveBuilder::relocate_metaspaceobj_embedded_pointers() { relocate_embedded_pointers(&_ro_src_objs); } +#define ADD_COUNT(x) \ + x += 1; \ + x ## _a += aotlinked ? 1 : 0; \ + x ## _i += inited ? 1 : 0; + +#define DECLARE_INSTANCE_KLASS_COUNTER(x) \ + int x = 0; \ + int x ## _a = 0; \ + int x ## _i = 0; + void ArchiveBuilder::make_klasses_shareable() { - int num_instance_klasses = 0; - int num_boot_klasses = 0; - int num_platform_klasses = 0; - int num_app_klasses = 0; - int num_hidden_klasses = 0; + DECLARE_INSTANCE_KLASS_COUNTER(num_instance_klasses); + DECLARE_INSTANCE_KLASS_COUNTER(num_boot_klasses); + DECLARE_INSTANCE_KLASS_COUNTER(num_vm_klasses); + DECLARE_INSTANCE_KLASS_COUNTER(num_platform_klasses); + DECLARE_INSTANCE_KLASS_COUNTER(num_app_klasses); + DECLARE_INSTANCE_KLASS_COUNTER(num_old_klasses); + DECLARE_INSTANCE_KLASS_COUNTER(num_hidden_klasses); + DECLARE_INSTANCE_KLASS_COUNTER(num_enum_klasses); + DECLARE_INSTANCE_KLASS_COUNTER(num_unregistered_klasses); int num_unlinked_klasses = 0; - int num_unregistered_klasses = 0; int num_obj_array_klasses = 0; int num_type_array_klasses = 0; + int boot_unlinked = 0; + int platform_unlinked = 0; + int app_unlinked = 0; + int unreg_unlinked = 0; + for (int i = 0; i < klasses()->length(); i++) { // Some of the code in ConstantPool::remove_unshareable_info() requires the classes // to be in linked state, so it must be call here before the next loop, which returns @@ -791,8 +839,12 @@ void ArchiveBuilder::make_klasses_shareable() { for (int i = 0; i < klasses()->length(); i++) { const char* type; const char* unlinked = ""; + const char* kind = ""; const char* hidden = ""; + const char* old = ""; const char* generated = ""; + const char* aotlinked_msg = ""; + const char* inited_msg = ""; Klass* k = get_buffered_addr(klasses()->at(i)); k->remove_java_mirror(); #ifdef _LP64 @@ -815,60 +867,127 @@ void ArchiveBuilder::make_klasses_shareable() { k->remove_unshareable_info(); } else { assert(k->is_instance_klass(), " must be"); - num_instance_klasses ++; InstanceKlass* ik = InstanceKlass::cast(k); - if (ik->is_shared_boot_class()) { + InstanceKlass* src_ik = get_source_addr(ik); + bool aotlinked = AOTClassLinker::is_candidate(src_ik); + bool inited = ik->has_aot_initialized_mirror(); + ADD_COUNT(num_instance_klasses); + if (CDSConfig::is_dumping_dynamic_archive()) { + // For static dump, class loader type are already set. + ik->assign_class_loader_type(); + } + if (ik->is_hidden()) { + ADD_COUNT(num_hidden_klasses); + hidden = " hidden"; + oop loader = k->class_loader(); + if (loader == nullptr) { + type = "boot"; + ADD_COUNT(num_boot_klasses); + } else if (loader == SystemDictionary::java_platform_loader()) { + type = "plat"; + ADD_COUNT(num_platform_klasses); + } else if (loader == SystemDictionary::java_system_loader()) { + type = "app"; + ADD_COUNT(num_app_klasses); + } else { + type = "bad"; + assert(0, "shouldn't happen"); + } + if (CDSConfig::is_dumping_invokedynamic()) { + assert(HeapShared::is_archivable_hidden_klass(ik), "sanity"); + } else { + // Legacy CDS support for lambda proxies + CDS_JAVA_HEAP_ONLY(assert(HeapShared::is_lambda_proxy_klass(ik), "sanity");) + } + } else if (ik->is_shared_boot_class()) { type = "boot"; - num_boot_klasses ++; + ADD_COUNT(num_boot_klasses); } else if (ik->is_shared_platform_class()) { type = "plat"; - num_platform_klasses ++; + ADD_COUNT(num_platform_klasses); } else if (ik->is_shared_app_class()) { type = "app"; - num_app_klasses ++; + ADD_COUNT(num_app_klasses); } else { assert(ik->is_shared_unregistered_class(), "must be"); type = "unreg"; - num_unregistered_klasses ++; + ADD_COUNT(num_unregistered_klasses); + } + + if (AOTClassLinker::is_vm_class(src_ik)) { + ADD_COUNT(num_vm_klasses); } if (!ik->is_linked()) { num_unlinked_klasses ++; - unlinked = " ** unlinked"; + unlinked = " unlinked"; + if (ik->is_shared_boot_class()) { + boot_unlinked ++; + } else if (ik->is_shared_platform_class()) { + platform_unlinked ++; + } else if (ik->is_shared_app_class()) { + app_unlinked ++; + } else { + unreg_unlinked ++; + } } - if (ik->is_hidden()) { - num_hidden_klasses ++; - hidden = " ** hidden"; + if (ik->is_interface()) { + kind = " interface"; + } else if (src_ik->is_enum_subclass()) { + kind = " enum"; + ADD_COUNT(num_enum_klasses); + } + + if (!ik->can_be_verified_at_dumptime()) { + ADD_COUNT(num_old_klasses); + old = " old"; } if (ik->is_generated_shared_class()) { - generated = " ** generated"; + generated = " generated"; + } + if (aotlinked) { + aotlinked_msg = " aot-linked"; } + if (inited) { + inited_msg = " inited"; + } + MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread::current(), ik); ik->remove_unshareable_info(); } if (log_is_enabled(Debug, cds, class)) { ResourceMark rm; - log_debug(cds, class)("klasses[%5d] = " PTR_FORMAT " %-5s %s%s%s%s", i, + log_debug(cds, class)("klasses[%5d] = " PTR_FORMAT " %-5s %s%s%s%s%s%s%s%s", i, p2i(to_requested(k)), type, k->external_name(), - hidden, unlinked, generated); + kind, hidden, old, unlinked, generated, aotlinked_msg, inited_msg); } } +#define STATS_FORMAT "= %5d, aot-linked = %5d, inited = %5d" +#define STATS_PARAMS(x) num_ ## x, num_ ## x ## _a, num_ ## x ## _i + log_info(cds)("Number of classes %d", num_instance_klasses + num_obj_array_klasses + num_type_array_klasses); - log_info(cds)(" instance classes = %5d", num_instance_klasses); - log_info(cds)(" boot = %5d", num_boot_klasses); - log_info(cds)(" app = %5d", num_app_klasses); - log_info(cds)(" platform = %5d", num_platform_klasses); - log_info(cds)(" unregistered = %5d", num_unregistered_klasses); - log_info(cds)(" (hidden) = %5d", num_hidden_klasses); - log_info(cds)(" (unlinked) = %5d", num_unlinked_klasses); + log_info(cds)(" instance classes " STATS_FORMAT, STATS_PARAMS(instance_klasses)); + log_info(cds)(" boot " STATS_FORMAT, STATS_PARAMS(boot_klasses)); + log_info(cds)(" vm " STATS_FORMAT, STATS_PARAMS(vm_klasses)); + log_info(cds)(" platform " STATS_FORMAT, STATS_PARAMS(platform_klasses)); + log_info(cds)(" app " STATS_FORMAT, STATS_PARAMS(app_klasses)); + log_info(cds)(" unregistered " STATS_FORMAT, STATS_PARAMS(unregistered_klasses)); + log_info(cds)(" (enum) " STATS_FORMAT, STATS_PARAMS(enum_klasses)); + log_info(cds)(" (hidden) " STATS_FORMAT, STATS_PARAMS(hidden_klasses)); + log_info(cds)(" (old) " STATS_FORMAT, STATS_PARAMS(old_klasses)); + log_info(cds)(" (unlinked) = %5d, boot = %d, plat = %d, app = %d, unreg = %d", + num_unlinked_klasses, boot_unlinked, platform_unlinked, app_unlinked, unreg_unlinked); log_info(cds)(" obj array classes = %5d", num_obj_array_klasses); log_info(cds)(" type array classes = %5d", num_type_array_klasses); log_info(cds)(" symbols = %5d", _symbols->length()); +#undef STATS_FORMAT +#undef STATS_PARAMS + DynamicArchive::make_array_klasses_shareable(); } @@ -876,6 +995,7 @@ void ArchiveBuilder::serialize_dynamic_archivable_items(SerializeClosure* soc) { SymbolTable::serialize_shared_table_header(soc, false); SystemDictionaryShared::serialize_dictionary_headers(soc, false); DynamicArchive::serialize_array_klasses(soc); + AOTLinkedClassBulkLoader::serialize(soc, false); } uintx ArchiveBuilder::buffer_to_offset(address p) const { diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp index f306e4676b3..39fffc26c37 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -292,7 +292,7 @@ class ArchiveBuilder : public StackObj { intx buffer_to_requested_delta() const { return _buffer_to_requested_delta; } bool is_in_buffer_space(address p) const { - return (buffer_bottom() <= p && p < buffer_top()); + return (buffer_bottom() != nullptr && buffer_bottom() <= p && p < buffer_top()); } template bool is_in_requested_static_archive(T p) const { @@ -420,6 +420,11 @@ class ArchiveBuilder : public StackObj { mark_and_relocate_to_buffered_addr((address*)ptr_location); } + bool has_been_buffered(address src_addr) const; + template bool has_been_buffered(T src_addr) const { + return has_been_buffered((address)src_addr); + } + address get_buffered_addr(address src_addr) const; template T get_buffered_addr(T src_addr) const { return (T)get_buffered_addr((address)src_addr); diff --git a/src/hotspot/share/cds/archiveHeapLoader.cpp b/src/hotspot/share/cds/archiveHeapLoader.cpp index 01831cf0f3e..b05fd20f4f5 100644 --- a/src/hotspot/share/cds/archiveHeapLoader.cpp +++ b/src/hotspot/share/cds/archiveHeapLoader.cpp @@ -449,10 +449,6 @@ class PatchNativePointers: public BitMapClosure { bool do_bit(size_t offset) { Metadata** p = _start + offset; *p = (Metadata*)(address(*p) + MetaspaceShared::relocation_delta()); - // Currently we have only Klass pointers in heap objects. - // This needs to be relaxed when we support other types of native - // pointers such as Method. - assert(((Klass*)(*p))->is_klass(), "must be"); return true; } }; diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp b/src/hotspot/share/cds/archiveHeapWriter.cpp index 636b368117d..be821044a96 100644 --- a/src/hotspot/share/cds/archiveHeapWriter.cpp +++ b/src/hotspot/share/cds/archiveHeapWriter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -27,14 +27,15 @@ #include "cds/cdsConfig.hpp" #include "cds/filemap.hpp" #include "cds/heapShared.hpp" +#include "classfile/javaClasses.hpp" #include "classfile/systemDictionary.hpp" #include "gc/shared/collectedHeap.hpp" #include "memory/iterator.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.hpp" #include "oops/compressedOops.hpp" -#include "oops/oop.inline.hpp" #include "oops/objArrayOop.inline.hpp" +#include "oops/oop.inline.hpp" #include "oops/oopHandle.inline.hpp" #include "oops/typeArrayKlass.hpp" #include "oops/typeArrayOop.hpp" @@ -535,7 +536,14 @@ oop ArchiveHeapWriter::load_oop_from_buffer(narrowOop* buffered_addr) { template void ArchiveHeapWriter::relocate_field_in_buffer(T* field_addr_in_buffer, CHeapBitMap* oopmap) { oop source_referent = load_source_oop_from_buffer(field_addr_in_buffer); - if (!CompressedOops::is_null(source_referent)) { + if (source_referent != nullptr) { + if (java_lang_Class::is_instance(source_referent)) { + // When the source object points to a "real" mirror, the buffered object should point + // to the "scratch" mirror, which has all unarchivable fields scrubbed (to be reinstated + // at run time). + source_referent = HeapShared::scratch_java_mirror(source_referent); + assert(source_referent != nullptr, "must be"); + } oop request_referent = source_obj_to_requested_obj(source_referent); store_requested_oop_in_buffer(field_addr_in_buffer, request_referent); mark_oop_pointer(field_addr_in_buffer, oopmap); @@ -731,7 +739,9 @@ void ArchiveHeapWriter::compute_ptrmap(ArchiveHeapInfo* heap_info) { Metadata** buffered_field_addr = requested_addr_to_buffered_addr(requested_field_addr); Metadata* native_ptr = *buffered_field_addr; - assert(native_ptr != nullptr, "sanity"); + guarantee(native_ptr != nullptr, "sanity"); + guarantee(ArchiveBuilder::current()->has_been_buffered((address)native_ptr), + "Metadata %p should have been archived", native_ptr); address buffered_native_ptr = ArchiveBuilder::current()->get_buffered_addr((address)native_ptr); address requested_native_ptr = ArchiveBuilder::current()->to_requested(buffered_native_ptr); diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index c7282f7d97c..3c778cbb523 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -39,6 +39,7 @@ #include "memory/metaspaceUtils.hpp" #include "memory/resourceArea.hpp" #include "oops/compressedOops.inline.hpp" +#include "oops/klass.inline.hpp" #include "runtime/arguments.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/debug.hpp" @@ -370,6 +371,14 @@ void ArchiveUtils::log_to_classlist(BootstrapInfo* bootstrap_specifier, TRAPS) { } } +bool ArchiveUtils::has_aot_initialized_mirror(InstanceKlass* src_ik) { + if (SystemDictionaryShared::is_excluded_class(src_ik)) { + assert(!ArchiveBuilder::current()->has_been_buffered(src_ik), "sanity"); + return false; + } + return ArchiveBuilder::current()->get_buffered_addr(src_ik)->has_aot_initialized_mirror(); +} + size_t HeapRootSegments::size_in_bytes(size_t seg_idx) { assert(seg_idx < _count, "In range"); return objArrayOopDesc::object_size(size_in_elems(seg_idx)) * HeapWordSize; @@ -390,3 +399,188 @@ size_t HeapRootSegments::segment_offset(size_t seg_idx) { return _base_offset + seg_idx * _max_size_in_bytes; } +ArchiveWorkers ArchiveWorkers::_workers; + +ArchiveWorkers::ArchiveWorkers() : + _start_semaphore(0), + _end_semaphore(0), + _num_workers(0), + _started_workers(0), + _waiting_workers(0), + _running_workers(0), + _state(NOT_READY), + _task(nullptr) { +} + +void ArchiveWorkers::initialize() { + assert(Atomic::load(&_state) == NOT_READY, "Should be"); + + Atomic::store(&_num_workers, max_workers()); + Atomic::store(&_state, READY); + + // Kick off pool startup by creating a single worker. + start_worker_if_needed(); +} + +int ArchiveWorkers::max_workers() { + // The pool is used for short-lived bursty tasks. We do not want to spend + // too much time creating and waking up threads unnecessarily. Plus, we do + // not want to overwhelm large machines. This is why we want to be very + // conservative about the number of workers actually needed. + return MAX2(0, log2i_graceful(os::active_processor_count())); +} + +bool ArchiveWorkers::is_parallel() { + return _num_workers > 0; +} + +void ArchiveWorkers::shutdown() { + while (true) { + State state = Atomic::load(&_state); + if (state == SHUTDOWN) { + // Already shut down. + return; + } + if (Atomic::cmpxchg(&_state, state, SHUTDOWN, memory_order_relaxed) == state) { + if (is_parallel()) { + // Execute a shutdown task and block until all workers respond. + run_task(&_shutdown_task); + } + } + } +} + +void ArchiveWorkers::start_worker_if_needed() { + while (true) { + int cur = Atomic::load(&_started_workers); + if (cur >= _num_workers) { + return; + } + if (Atomic::cmpxchg(&_started_workers, cur, cur + 1, memory_order_relaxed) == cur) { + new ArchiveWorkerThread(this); + return; + } + } +} + +void ArchiveWorkers::signal_worker_if_needed() { + while (true) { + int cur = Atomic::load(&_waiting_workers); + if (cur == 0) { + return; + } + if (Atomic::cmpxchg(&_waiting_workers, cur, cur - 1, memory_order_relaxed) == cur) { + _start_semaphore.signal(1); + return; + } + } +} + +void ArchiveWorkers::run_task(ArchiveWorkerTask* task) { + assert((Atomic::load(&_state) == READY) || + ((Atomic::load(&_state) == SHUTDOWN) && (task == &_shutdown_task)), + "Should be in correct state"); + assert(Atomic::load(&_task) == nullptr, "Should not have running tasks"); + + if (is_parallel()) { + run_task_multi(task); + } else { + run_task_single(task); + } +} + +void ArchiveWorkers::run_task_single(ArchiveWorkerTask* task) { + // Single thread needs no chunking. + task->configure_max_chunks(1); + + // Execute the task ourselves, as there are no workers. + task->work(0, 1); +} + +void ArchiveWorkers::run_task_multi(ArchiveWorkerTask* task) { + // Multiple threads can work with multiple chunks. + task->configure_max_chunks(_num_workers * CHUNKS_PER_WORKER); + + // Set up the run and publish the task. + Atomic::store(&_waiting_workers, _num_workers); + Atomic::store(&_running_workers, _num_workers); + Atomic::release_store(&_task, task); + + // Kick off pool wakeup by signaling a single worker, and proceed + // immediately to executing the task locally. + signal_worker_if_needed(); + + // Execute the task ourselves, while workers are catching up. + // This allows us to hide parts of task handoff latency. + task->run(); + + // Done executing task locally, wait for any remaining workers to complete, + // and then do the final housekeeping. + _end_semaphore.wait(); + Atomic::store(&_task, (ArchiveWorkerTask *) nullptr); + OrderAccess::fence(); + + assert(Atomic::load(&_waiting_workers) == 0, "All workers were signaled"); + assert(Atomic::load(&_running_workers) == 0, "No workers are running"); +} + +void ArchiveWorkerTask::run() { + while (true) { + int chunk = Atomic::load(&_chunk); + if (chunk >= _max_chunks) { + return; + } + if (Atomic::cmpxchg(&_chunk, chunk, chunk + 1, memory_order_relaxed) == chunk) { + assert(0 <= chunk && chunk < _max_chunks, "Sanity"); + work(chunk, _max_chunks); + } + } +} + +void ArchiveWorkerTask::configure_max_chunks(int max_chunks) { + if (_max_chunks == 0) { + _max_chunks = max_chunks; + } +} + +bool ArchiveWorkers::run_as_worker() { + assert(is_parallel(), "Should be in parallel mode"); + _start_semaphore.wait(); + + // Avalanche wakeups: each worker signals two others. + signal_worker_if_needed(); + signal_worker_if_needed(); + + ArchiveWorkerTask* task = Atomic::load_acquire(&_task); + task->run(); + + // All work done in threads should be visible to caller. + OrderAccess::fence(); + + // Signal the pool the tasks are complete, if this is the last worker. + if (Atomic::sub(&_running_workers, 1, memory_order_relaxed) == 0) { + _end_semaphore.signal(); + } + + // Continue if task was not a termination task. + return (task != &_shutdown_task); +} + +ArchiveWorkerThread::ArchiveWorkerThread(ArchiveWorkers* pool) : NamedThread(), _pool(pool) { + set_name("ArchiveWorkerThread"); + os::create_thread(this, os::os_thread); + os::start_thread(this); +} + +void ArchiveWorkerThread::run() { + // Avalanche thread startup: each starting worker starts two others. + _pool->start_worker_if_needed(); + _pool->start_worker_if_needed(); + + // Set ourselves up. + os::set_priority(this, NearMaxPriority); + + while (_pool->run_as_worker()) { + // Work until terminated. + } +} diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index 7fb8e538084..128fdc4d33a 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -33,11 +33,16 @@ #include "utilities/bitMap.hpp" #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" +#include "runtime/nonJavaThread.hpp" +#include "runtime/semaphore.hpp" class BootstrapInfo; class ReservedSpace; class VirtualSpace; +template class Array; +template class GrowableArray; + // ArchivePtrMarker is used to mark the location of pointers embedded in a CDS archive. E.g., when an // InstanceKlass k is dumped, we mark the location of the k->_name pointer by effectively calling // mark_pointer(/*ptr_loc=*/&k->_name). It's required that (_prt_base <= ptr_loc < _ptr_end). _ptr_base is @@ -253,6 +258,8 @@ class ArchiveUtils { public: static const uintx MAX_SHARED_DELTA = 0x7FFFFFFF; static void log_to_classlist(BootstrapInfo* bootstrap_specifier, TRAPS) NOT_CDS_RETURN; + static bool has_aot_initialized_mirror(InstanceKlass* src_ik); + template static Array* archive_array(GrowableArray* tmp_array); // offset must represent an object of type T in the mapped shared space. Return // a direct pointer to this object. @@ -314,4 +321,95 @@ class HeapRootSegments { HeapRootSegments& operator=(const HeapRootSegments&) = default; }; +class ArchiveWorkers; + +// A task to be worked on by worker threads +class ArchiveWorkerTask : public CHeapObj { + friend class ArchiveWorkers; + friend class ArchiveWorkerShutdownTask; +private: + const char* _name; + int _max_chunks; + volatile int _chunk; + + void run(); + + void configure_max_chunks(int max_chunks); + +public: + ArchiveWorkerTask(const char* name) : + _name(name), _max_chunks(0), _chunk(0) {} + const char* name() const { return _name; } + virtual void work(int chunk, int max_chunks) = 0; +}; + +class ArchiveWorkerThread : public NamedThread { + friend class ArchiveWorkers; +private: + ArchiveWorkers* const _pool; + +public: + ArchiveWorkerThread(ArchiveWorkers* pool); + const char* type_name() const override { return "Archive Worker Thread"; } + void run() override; +}; + +class ArchiveWorkerShutdownTask : public ArchiveWorkerTask { +public: + ArchiveWorkerShutdownTask() : ArchiveWorkerTask("Archive Worker Shutdown") { + // This task always have only one chunk. + configure_max_chunks(1); + } + void work(int chunk, int max_chunks) override { + // Do nothing. + } +}; + +// Special worker pool for archive workers. The goal for this pool is to +// startup fast, distribute spiky workloads efficiently, and being able to +// shutdown after use. This makes the implementation quite different from +// the normal GC worker pool. +class ArchiveWorkers { + friend class ArchiveWorkerThread; +private: + // Target number of chunks per worker. This should be large enough to even + // out work imbalance, and small enough to keep bookkeeping overheads low. + static constexpr int CHUNKS_PER_WORKER = 4; + static int max_workers(); + + // Global shared instance. Can be uninitialized, can be shut down. + static ArchiveWorkers _workers; + + ArchiveWorkerShutdownTask _shutdown_task; + Semaphore _start_semaphore; + Semaphore _end_semaphore; + + int _num_workers; + int _started_workers; + int _waiting_workers; + int _running_workers; + + typedef enum { NOT_READY, READY, SHUTDOWN } State; + volatile State _state; + + ArchiveWorkerTask* _task; + + bool run_as_worker(); + void start_worker_if_needed(); + void signal_worker_if_needed(); + + void run_task_single(ArchiveWorkerTask* task); + void run_task_multi(ArchiveWorkerTask* task); + + bool is_parallel(); + + ArchiveWorkers(); + +public: + static ArchiveWorkers* workers() { return &_workers; } + void initialize(); + void shutdown(); + void run_task(ArchiveWorkerTask* task); +}; + #endif // SHARE_CDS_ARCHIVEUTILS_HPP diff --git a/src/hotspot/share/cds/archiveUtils.inline.hpp b/src/hotspot/share/cds/archiveUtils.inline.hpp index 7df344e3701..537b3d1670c 100644 --- a/src/hotspot/share/cds/archiveUtils.inline.hpp +++ b/src/hotspot/share/cds/archiveUtils.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -27,7 +27,10 @@ #include "cds/archiveUtils.hpp" +#include "cds/archiveBuilder.hpp" +#include "oops/array.hpp" #include "utilities/bitMap.inline.hpp" +#include "utilities/growableArray.hpp" inline bool SharedDataRelocator::do_bit(size_t offset) { address* p = _patch_base + offset; @@ -47,4 +50,19 @@ inline bool SharedDataRelocator::do_bit(size_t offset) { return true; // keep iterating } +// Returns the address of an Array that's allocated in the ArchiveBuilder "buffer" space. +template +Array* ArchiveUtils::archive_array(GrowableArray* tmp_array) { + Array* archived_array = ArchiveBuilder::new_ro_array(tmp_array->length()); + for (int i = 0; i < tmp_array->length(); i++) { + archived_array->at_put(i, tmp_array->at(i)); + if (std::is_pointer::value) { + ArchivePtrMarker::mark_pointer(archived_array->adr_at(i)); + } + } + + return archived_array; +} + + #endif // SHARE_CDS_ARCHIVEUTILS_INLINE_HPP diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 691a1983732..ba5d12e6450 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -33,19 +33,27 @@ #include "logging/log.hpp" #include "memory/universe.hpp" #include "runtime/arguments.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" +#include "runtime/vmThread.hpp" #include "utilities/defaultStream.hpp" +#include "utilities/formatBuffer.hpp" bool CDSConfig::_is_dumping_static_archive = false; bool CDSConfig::_is_dumping_dynamic_archive = false; bool CDSConfig::_is_using_optimized_module_handling = true; bool CDSConfig::_is_dumping_full_module_graph = true; bool CDSConfig::_is_using_full_module_graph = true; +bool CDSConfig::_has_aot_linked_classes = false; +bool CDSConfig::_has_archived_invokedynamic = false; +bool CDSConfig::_old_cds_flags_used = false; char* CDSConfig::_default_archive_path = nullptr; char* CDSConfig::_static_archive_path = nullptr; char* CDSConfig::_dynamic_archive_path = nullptr; +JavaThread* CDSConfig::_dumper_thread = nullptr; + int CDSConfig::get_status() { assert(Universe::is_fully_initialized(), "status is finalized only after Universe is initialized"); return (is_dumping_archive() ? IS_DUMPING_ARCHIVE : 0) | @@ -54,7 +62,6 @@ int CDSConfig::get_status() { (is_using_archive() ? IS_USING_ARCHIVE : 0); } - void CDSConfig::initialize() { if (is_dumping_static_archive()) { if (RequireSharedSpaces) { @@ -334,7 +341,95 @@ bool CDSConfig::has_unsupported_runtime_module_options() { return false; } +#define CHECK_ALIAS(f) check_flag_alias(FLAG_IS_DEFAULT(f), #f) + +void CDSConfig::check_flag_alias(bool alias_is_default, const char* alias_name) { + if (_old_cds_flags_used && !alias_is_default) { + vm_exit_during_initialization(err_msg("Option %s cannot be used at the same time with " + "-Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, " + "DumpLoadedClassList, SharedClassListFile, or SharedArchiveFile", + alias_name)); + } +} + +void CDSConfig::check_flag_aliases() { + if (!FLAG_IS_DEFAULT(DumpLoadedClassList) || + !FLAG_IS_DEFAULT(SharedClassListFile) || + !FLAG_IS_DEFAULT(SharedArchiveFile)) { + _old_cds_flags_used = true; + } + + CHECK_ALIAS(AOTCache); + CHECK_ALIAS(AOTConfiguration); + CHECK_ALIAS(AOTMode); + + if (FLAG_IS_DEFAULT(AOTCache) && FLAG_IS_DEFAULT(AOTConfiguration) && FLAG_IS_DEFAULT(AOTMode)) { + // Aliases not used. + return; + } + + if (FLAG_IS_DEFAULT(AOTMode) || strcmp(AOTMode, "auto") == 0 || strcmp(AOTMode, "on") == 0) { + if (!FLAG_IS_DEFAULT(AOTConfiguration)) { + vm_exit_during_initialization("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create"); + } + + if (!FLAG_IS_DEFAULT(AOTCache)) { + assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked"); + FLAG_SET_ERGO(SharedArchiveFile, AOTCache); + } + + UseSharedSpaces = true; + if (FLAG_IS_DEFAULT(AOTMode) || (strcmp(AOTMode, "auto") == 0)) { + RequireSharedSpaces = false; + } else { + assert(strcmp(AOTMode, "on") == 0, "already checked"); + RequireSharedSpaces = true; + } + } else if (strcmp(AOTMode, "off") == 0) { + UseSharedSpaces = false; + RequireSharedSpaces = false; + } else { + // AOTMode is record or create + if (FLAG_IS_DEFAULT(AOTConfiguration)) { + vm_exit_during_initialization(err_msg("-XX:AOTMode=%s cannot be used without setting AOTConfiguration", AOTMode)); + } + + if (strcmp(AOTMode, "record") == 0) { + if (!FLAG_IS_DEFAULT(AOTCache)) { + vm_exit_during_initialization("AOTCache must not be specified when using -XX:AOTMode=record"); + } + + assert(FLAG_IS_DEFAULT(DumpLoadedClassList), "already checked"); + FLAG_SET_ERGO(DumpLoadedClassList, AOTConfiguration); + UseSharedSpaces = false; + RequireSharedSpaces = false; + } else { + assert(strcmp(AOTMode, "create") == 0, "checked by AOTModeConstraintFunc"); + if (FLAG_IS_DEFAULT(AOTCache)) { + vm_exit_during_initialization("AOTCache must be specified when using -XX:AOTMode=create"); + } + + assert(FLAG_IS_DEFAULT(SharedClassListFile), "already checked"); + FLAG_SET_ERGO(SharedClassListFile, AOTConfiguration); + assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked"); + FLAG_SET_ERGO(SharedArchiveFile, AOTCache); + + CDSConfig::enable_dumping_static_archive(); + } + } +} + bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) { + check_flag_aliases(); + + if (AOTClassLinking) { + // If AOTClassLinking is specified, enable all AOT optimizations by default. + FLAG_SET_ERGO_IF_DEFAULT(AOTInvokeDynamicLinking, true); + } else { + // AOTInvokeDynamicLinking depends on AOTClassLinking. + FLAG_SET_ERGO(AOTInvokeDynamicLinking, false); + } + if (is_dumping_static_archive()) { if (!mode_flag_cmd_line) { // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive. @@ -353,6 +448,9 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla // run to another which resulting in non-determinstic CDS archives. // Disable UseStringDeduplication while dumping CDS archive. UseStringDeduplication = false; + + // Don't use SoftReferences so that objects used by java.lang.invoke tables can be archived. + Arguments::PropertyList_add(new SystemProperty("java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE", "false", false)); } // RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit @@ -397,6 +495,11 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla return true; } +bool CDSConfig::allow_only_single_java_thread() { + // See comments in JVM_StartThread() + return is_dumping_static_archive(); +} + bool CDSConfig::is_using_archive() { return UseSharedSpaces; } @@ -411,12 +514,32 @@ void CDSConfig::stop_using_optimized_module_handling() { _is_using_full_module_graph = false; // This requires is_using_optimized_module_handling() } + +CDSConfig::DumperThreadMark::DumperThreadMark(JavaThread* current) { + assert(_dumper_thread == nullptr, "sanity"); + _dumper_thread = current; +} + +CDSConfig::DumperThreadMark::~DumperThreadMark() { + assert(_dumper_thread != nullptr, "sanity"); + _dumper_thread = nullptr; +} + +bool CDSConfig::current_thread_is_vm_or_dumper() { + Thread* t = Thread::current(); + return t != nullptr && (t->is_VM_thread() || t == _dumper_thread); +} + #if INCLUDE_CDS_JAVA_HEAP bool CDSConfig::is_dumping_heap() { // heap dump is not supported in dynamic dump return is_dumping_static_archive() && HeapShared::can_write(); } +bool CDSConfig::is_loading_heap() { + return ArchiveHeapLoader::is_in_use(); +} + bool CDSConfig::is_using_full_module_graph() { if (ClassLoaderDataShared::is_full_module_graph_loaded()) { return true; @@ -455,4 +578,39 @@ void CDSConfig::stop_using_full_module_graph(const char* reason) { } } } + +bool CDSConfig::is_dumping_aot_linked_classes() { + if (is_dumping_dynamic_archive()) { + return is_using_full_module_graph() && AOTClassLinking; + } else if (is_dumping_static_archive()) { + return is_dumping_full_module_graph() && AOTClassLinking; + } else { + return false; + } +} + +bool CDSConfig::is_using_aot_linked_classes() { + // Make sure we have the exact same module graph as in the assembly phase, or else + // some aot-linked classes may not be visible so cannot be loaded. + return is_using_full_module_graph() && _has_aot_linked_classes; +} + +void CDSConfig::set_has_aot_linked_classes(bool has_aot_linked_classes) { + _has_aot_linked_classes |= has_aot_linked_classes; +} + +bool CDSConfig::is_initing_classes_at_dump_time() { + return is_dumping_heap() && is_dumping_aot_linked_classes(); +} + +bool CDSConfig::is_dumping_invokedynamic() { + // Requires is_dumping_aot_linked_classes(). Otherwise the classes of some archived heap + // objects used by the archive indy callsites may be replaced at runtime. + return AOTInvokeDynamicLinking && is_dumping_aot_linked_classes() && is_dumping_heap(); +} + +bool CDSConfig::is_loading_invokedynamic() { + return UseSharedSpaces && is_using_full_module_graph() && _has_archived_invokedynamic; +} + #endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp index 7711a2ea1e2..cceaceeb6d7 100644 --- a/src/hotspot/share/cds/cdsConfig.hpp +++ b/src/hotspot/share/cds/cdsConfig.hpp @@ -29,6 +29,8 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" +class JavaThread; + class CDSConfig : public AllStatic { #if INCLUDE_CDS static bool _is_dumping_static_archive; @@ -36,10 +38,16 @@ class CDSConfig : public AllStatic { static bool _is_using_optimized_module_handling; static bool _is_dumping_full_module_graph; static bool _is_using_full_module_graph; + static bool _has_aot_linked_classes; + static bool _has_archived_invokedynamic; static char* _default_archive_path; static char* _static_archive_path; static char* _dynamic_archive_path; + + static bool _old_cds_flags_used; + + static JavaThread* _dumper_thread; #endif static void extract_shared_archive_paths(const char* archive_path, @@ -47,6 +55,9 @@ class CDSConfig : public AllStatic { char** top_archive_path); static void init_shared_archive_paths(); + static void check_flag_alias(bool alias_is_default, const char* alias_name); + static void check_flag_aliases(); + public: // Used by jdk.internal.misc.CDS.getCDSConfigStatus(); static const int IS_DUMPING_ARCHIVE = 1 << 0; @@ -57,6 +68,8 @@ class CDSConfig : public AllStatic { // Initialization and command-line checking static void initialize() NOT_CDS_RETURN; + static void set_old_cds_flags_used() { CDS_ONLY(_old_cds_flags_used = true); } + static bool old_cds_flags_used() { return CDS_ONLY(_old_cds_flags_used) NOT_CDS(false); } static void check_internal_module_property(const char* key, const char* value) NOT_CDS_RETURN; static void check_incompatible_property(const char* key, const char* value) NOT_CDS_RETURN; static void check_unsupported_dumping_module_options() NOT_CDS_RETURN; @@ -79,12 +92,19 @@ class CDSConfig : public AllStatic { static void enable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = true); } static void disable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = false); } + // Misc CDS features + static bool allow_only_single_java_thread() NOT_CDS_RETURN_(false); + // optimized_module_handling -- can we skip some expensive operations related to modules? static bool is_using_optimized_module_handling() { return CDS_ONLY(_is_using_optimized_module_handling) NOT_CDS(false); } static void stop_using_optimized_module_handling() NOT_CDS_RETURN; static bool is_logging_lambda_form_invokers() NOT_CDS_RETURN_(false); + static bool is_dumping_aot_linked_classes() NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_using_aot_linked_classes() NOT_CDS_JAVA_HEAP_RETURN_(false); + static void set_has_aot_linked_classes(bool has_aot_linked_classes) NOT_CDS_JAVA_HEAP_RETURN; + // archive_path // Points to the classes.jsa in $JAVA_HOME @@ -96,13 +116,34 @@ class CDSConfig : public AllStatic { // --- Archived java objects - static bool is_dumping_heap() NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_dumping_heap() NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_loading_heap() NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_initing_classes_at_dump_time() NOT_CDS_JAVA_HEAP_RETURN_(false); + + static bool is_dumping_invokedynamic() NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_loading_invokedynamic() NOT_CDS_JAVA_HEAP_RETURN_(false); + static void set_has_archived_invokedynamic() { CDS_JAVA_HEAP_ONLY(_has_archived_invokedynamic = true); } // full_module_graph (requires optimized_module_handling) static bool is_dumping_full_module_graph() { return CDS_ONLY(_is_dumping_full_module_graph) NOT_CDS(false); } static bool is_using_full_module_graph() NOT_CDS_JAVA_HEAP_RETURN_(false); static void stop_dumping_full_module_graph(const char* reason = nullptr) NOT_CDS_JAVA_HEAP_RETURN; static void stop_using_full_module_graph(const char* reason = nullptr) NOT_CDS_JAVA_HEAP_RETURN; + + + // Some CDS functions assume that they are called only within a single-threaded context. I.e., + // they are called from: + // - The VM thread (e.g., inside VM_PopulateDumpSharedSpace) + // - The thread that performs prepatory steps before switching to the VM thread + // Since these two threads never execute concurrently, we can avoid using locks in these CDS + // function. For safety, these functions should assert with CDSConfig::current_thread_is_vm_or_dumper(). + class DumperThreadMark { + public: + DumperThreadMark(JavaThread* current); + ~DumperThreadMark(); + }; + + static bool current_thread_is_vm_or_dumper() NOT_CDS_RETURN_(false); }; #endif // SHARE_CDS_CDSCONFIG_HPP diff --git a/src/hotspot/share/cds/cdsEnumKlass.cpp b/src/hotspot/share/cds/cdsEnumKlass.cpp index b77f2fd9d16..17438428c80 100644 --- a/src/hotspot/share/cds/cdsEnumKlass.cpp +++ b/src/hotspot/share/cds/cdsEnumKlass.cpp @@ -39,7 +39,7 @@ bool CDSEnumKlass::is_enum_obj(oop orig_obj) { Klass* k = orig_obj->klass(); Klass* buffered_k = ArchiveBuilder::get_buffered_klass(k); return k->is_instance_klass() && - InstanceKlass::cast(k)->java_super() == vmClasses::Enum_klass(); + InstanceKlass::cast(k)->is_enum_subclass(); } // -- Handling of Enum objects diff --git a/src/hotspot/share/cds/cdsHeapVerifier.cpp b/src/hotspot/share/cds/cdsHeapVerifier.cpp index 29e5af97c6a..fbc58e503ca 100644 --- a/src/hotspot/share/cds/cdsHeapVerifier.cpp +++ b/src/hotspot/share/cds/cdsHeapVerifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,10 +23,14 @@ */ #include "precompiled.hpp" +#include "cds/aotClassInitializer.hpp" #include "cds/archiveBuilder.hpp" #include "cds/cdsHeapVerifier.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/javaClasses.inline.hpp" +#include "classfile/moduleEntry.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "classfile/vmSymbols.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" @@ -38,12 +42,13 @@ #if INCLUDE_CDS_JAVA_HEAP // CDSHeapVerifier is used to check for problems where an archived object references a -// static field that may be reinitialized at runtime. In the following example, +// static field that may be get a different value at runtime. In the following example, // Foo.get.test() -// correctly returns true when CDS disabled, but incorrectly returns false when CDS is enabled. +// correctly returns true when CDS disabled, but incorrectly returns false when CDS is enabled, +// because the archived archivedFoo.bar value is different than Bar.bar. // // class Foo { -// final Foo archivedFoo; // this field is archived by CDS +// static final Foo archivedFoo; // this field is archived by CDS // Bar bar; // static { // CDS.initializeFromArchive(Foo.class); @@ -68,8 +73,8 @@ // [2] CDSHeapVerifier::do_entry() checks all the archived objects. None of them // should be in [1] // -// However, it's legal for *some* static fields to be references. This leads to the -// table of ADD_EXCL below. +// However, it's legal for *some* static fields to be referenced. The reasons are explained +// in the table of ADD_EXCL below. // // [A] In most of the cases, the module bootstrap code will update the static field // to point to part of the archived module graph. E.g., @@ -123,6 +128,12 @@ CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0) ADD_EXCL("sun/invoke/util/ValueConversions", "ONE_INT", // E "ZERO_INT"); // E + if (CDSConfig::is_dumping_invokedynamic()) { + ADD_EXCL("java/lang/invoke/InvokerBytecodeGenerator", "MEMBERNAME_FACTORY", // D + "CD_Object_array", // E same as <...>ConstantUtils.CD_Object_array::CD_Object + "INVOKER_SUPER_DESC"); // E same as java.lang.constant.ConstantDescs::CD_Object + } + # undef ADD_EXCL ClassLoaderDataGraph::classes_do(this); @@ -130,15 +141,16 @@ CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0) CDSHeapVerifier::~CDSHeapVerifier() { if (_problems > 0) { - log_warning(cds, heap)("Scanned %d objects. Found %d case(s) where " - "an object points to a static field that may be " - "reinitialized at runtime.", _archived_objs, _problems); + log_error(cds, heap)("Scanned %d objects. Found %d case(s) where " + "an object points to a static field that " + "may hold a different value at runtime.", _archived_objs, _problems); + MetaspaceShared::unrecoverable_writing_error(); } } class CDSHeapVerifier::CheckStaticFields : public FieldClosure { CDSHeapVerifier* _verifier; - InstanceKlass* _ik; + InstanceKlass* _ik; // The class whose static fields are being checked. const char** _exclusions; public: CheckStaticFields(CDSHeapVerifier* verifier, InstanceKlass* ik) @@ -151,9 +163,14 @@ class CDSHeapVerifier::CheckStaticFields : public FieldClosure { return; } + if (fd->signature()->equals("Ljdk/internal/access/JavaLangAccess;")) { + // A few classes have static fields that point to SharedSecrets.getJavaLangAccess(). + // This object carries no state and we can create a new one in the production run. + return; + } oop static_obj_field = _ik->java_mirror()->obj_field(fd->offset()); if (static_obj_field != nullptr) { - Klass* klass = static_obj_field->klass(); + Klass* field_type = static_obj_field->klass(); if (_exclusions != nullptr) { for (const char** p = _exclusions; *p != nullptr; p++) { if (fd->name()->equals(*p)) { @@ -173,11 +190,35 @@ class CDSHeapVerifier::CheckStaticFields : public FieldClosure { // This field points to an archived mirror. return; } - if (klass->has_archived_enum_objs()) { - // This klass is a subclass of java.lang.Enum. If any instance of this klass - // has been archived, we will archive all static fields of this klass. - // See HeapShared::initialize_enum_klass(). - return; + + if (field_type->is_instance_klass()) { + InstanceKlass* field_ik = InstanceKlass::cast(field_type); + if (field_ik->is_enum_subclass()) { + if (field_ik->has_archived_enum_objs() || ArchiveUtils::has_aot_initialized_mirror(field_ik)) { + // This field is an Enum. If any instance of this Enum has been archived, we will archive + // all static fields of this Enum as well. + return; + } + } + + if (field_ik->is_hidden() && ArchiveUtils::has_aot_initialized_mirror(field_ik)) { + // We have a static field in a core-library class that points to a method reference, which + // are safe to archive. + guarantee(_ik->module()->name() == vmSymbols::java_base(), "sanity"); + return; + } + + if (field_ik == vmClasses::MethodType_klass()) { + // The identity of MethodTypes are preserved between assembly phase and production runs + // (by MethodType::AOTHolder::archivedMethodTypes). No need to check. + return; + } + + if (field_ik == vmClasses::internal_Unsafe_klass() && ArchiveUtils::has_aot_initialized_mirror(field_ik)) { + // There's only a single instance of jdk/internal/misc/Unsafe, so all references will + // be pointing to this singleton, which has been archived. + return; + } } // This field *may* be initialized to a different value at runtime. Remember it @@ -188,7 +229,8 @@ class CDSHeapVerifier::CheckStaticFields : public FieldClosure { }; // Remember all the static object fields of every class that are currently -// loaded. +// loaded. Later, we will check if any archived objects reference one of +// these fields. void CDSHeapVerifier::do_klass(Klass* k) { if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k); @@ -200,6 +242,12 @@ void CDSHeapVerifier::do_klass(Klass* k) { return; } + if (ArchiveUtils::has_aot_initialized_mirror(ik)) { + // ik's won't be executed at runtime, the static fields in + // ik will carry their values to runtime. + return; + } + CheckStaticFields csf(this, ik); ik->do_local_static_fields(&csf); } @@ -221,10 +269,15 @@ inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& // should be flagged by CDSHeapVerifier. return true; /* keep on iterating */ } + if (info->_holder->is_hidden()) { + return true; + } ResourceMark rm; + char* class_name = info->_holder->name()->as_C_string(); + char* field_name = info->_name->as_C_string(); LogStream ls(Log(cds, heap)::warning()); - ls.print_cr("Archive heap points to a static field that may be reinitialized at runtime:"); - ls.print_cr("Field: %s::%s", info->_holder->name()->as_C_string(), info->_name->as_C_string()); + ls.print_cr("Archive heap points to a static field that may hold a different value at runtime:"); + ls.print_cr("Field: %s::%s", class_name, field_name); ls.print("Value: "); orig_obj->print_on(&ls); ls.print_cr("--- trace begin ---"); @@ -266,6 +319,29 @@ void CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj) { } } +const char* static_field_name(oop mirror, oop field) { + Klass* k = java_lang_Class::as_Klass(mirror); + if (k->is_instance_klass()) { + for (JavaFieldStream fs(InstanceKlass::cast(k)); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + fieldDescriptor& fd = fs.field_descriptor(); + switch (fd.field_type()) { + case T_OBJECT: + case T_ARRAY: + if (mirror->obj_field(fd.offset()) == field) { + return fs.name()->as_C_string(); + } + break; + default: + break; + } + } + } + } + + return ""; +} + int CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* info) { int level = 0; if (info->orig_referrer() != nullptr) { @@ -280,6 +356,9 @@ int CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj, oop orig_fiel st->print("[%2d] ", level); orig_obj->print_address_on(st); st->print(" %s", k->internal_name()); + if (java_lang_Class::is_instance(orig_obj)) { + st->print(" (%s::%s)", java_lang_Class::as_Klass(orig_obj)->external_name(), static_field_name(orig_obj, orig_field)); + } if (orig_field != nullptr) { if (k->is_instance_klass()) { TraceFields clo(orig_obj, orig_field, st); diff --git a/src/hotspot/share/cds/cds_globals.hpp b/src/hotspot/share/cds/cds_globals.hpp index 828393a7b6b..811740cfbcb 100644 --- a/src/hotspot/share/cds/cds_globals.hpp +++ b/src/hotspot/share/cds/cds_globals.hpp @@ -94,6 +94,33 @@ "(2) always map at preferred address, and if unsuccessful, " \ "do not map the archive") \ range(0, 2) \ + \ + /*========== New "AOT" flags =========================================*/ \ + /* The following 3 flags are aliases of -Xshare:dump, */ \ + /* -XX:SharedArchiveFile=..., etc. See CDSConfig::check_flag_aliases()*/ \ + \ + product(ccstr, AOTMode, nullptr, \ + "Specifies how AOTCache should be created or used. Valid values " \ + "are: off, record, create, auto, on; the default is auto") \ + constraint(AOTModeConstraintFunc, AtParse) \ + \ + product(ccstr, AOTConfiguration, nullptr, \ + "Configuration information used by CreateAOTCache") \ + \ + product(ccstr, AOTCache, nullptr, \ + "Cache for improving start up and warm up") \ + \ + product(bool, AOTInvokeDynamicLinking, false, DIAGNOSTIC, \ + "AOT-link JVM_CONSTANT_InvokeDynamic entries in cached " \ + "ConstantPools") \ + \ + product(bool, AOTClassLinking, false, \ + "Load/link all archived classes for the boot/platform/app " \ + "loaders before application main") \ + \ + product(bool, AOTCacheParallelRelocation, true, DIAGNOSTIC, \ + "Use parallel relocation code to speed up startup.") \ + \ // end of CDS_FLAGS DECLARE_FLAGS(CDS_FLAGS) diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index 694a179d7ee..47925f578ea 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -23,9 +23,9 @@ */ #include "precompiled.hpp" +#include "cds/aotConstantPoolResolver.hpp" #include "cds/archiveUtils.hpp" #include "cds/classListParser.hpp" -#include "cds/classPrelinker.hpp" #include "cds/lambdaFormInvokers.hpp" #include "cds/metaspaceShared.hpp" #include "cds/unregisteredClasses.hpp" @@ -46,6 +46,7 @@ #include "memory/resourceArea.hpp" #include "oops/constantPool.inline.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -69,9 +70,13 @@ ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : log_info(cds)("Parsing %s%s", file, parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : ""); if (!_file_input.is_open()) { - char errmsg[JVM_MAXPATHLEN]; - os::lasterror(errmsg, JVM_MAXPATHLEN); - vm_exit_during_initialization("Loading classlist failed", errmsg); + char reason[JVM_MAXPATHLEN]; + os::lasterror(reason, JVM_MAXPATHLEN); + vm_exit_during_initialization(err_msg("Loading %s %s failed", + FLAG_IS_DEFAULT(AOTConfiguration) ? + "classlist" : "AOTConfiguration file", + file), + reason); } _token = _line = nullptr; _interfaces = new (mtClass) GrowableArray(10, mtClass); @@ -594,9 +599,20 @@ void ClassListParser::resolve_indy(JavaThread* current, Symbol* class_name_symbo } void ClassListParser::resolve_indy_impl(Symbol* class_name_symbol, TRAPS) { + if (CDSConfig::is_dumping_invokedynamic()) { + // The CP entry for the invokedynamic instruction will be resolved. + // No need to do the following. + return; + } + + // This is an older CDS optimization: + // We store a pre-generated version of the lambda proxy class in the AOT cache, + // which will be loaded via JVM_LookupLambdaProxyClassFromArchive(). + // This eliminate dynamic class generation of the proxy class, but we still need to + // resolve the CP entry for the invokedynamic instruction, which may result in + // generation of LambdaForm classes. Handle class_loader(THREAD, SystemDictionary::java_system_loader()); - Handle protection_domain; - Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, protection_domain, true, CHECK); + Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, true, CHECK); if (klass->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(klass); MetaspaceShared::try_link_class(THREAD, ik); @@ -764,8 +780,7 @@ InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* inter InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) { Handle class_loader(current, class_loader_oop); - Handle protection_domain; - return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain); + return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader); } InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) { @@ -836,6 +851,8 @@ void ClassListParser::parse_constant_pool_tag() { case JVM_CONSTANT_InterfaceMethodref: preresolve_fmi = true; break; + case JVM_CONSTANT_InvokeDynamic: + preresolve_indy = true; break; default: constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)", @@ -845,9 +862,12 @@ void ClassListParser::parse_constant_pool_tag() { } if (preresolve_class) { - ClassPrelinker::preresolve_class_cp_entries(THREAD, ik, &preresolve_list); + AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list); } if (preresolve_fmi) { - ClassPrelinker::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list); + AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list); + } + if (preresolve_indy) { + AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list); } } diff --git a/src/hotspot/share/cds/classListWriter.cpp b/src/hotspot/share/cds/classListWriter.cpp index 1b9f589f1c5..78a6857ff73 100644 --- a/src/hotspot/share/cds/classListWriter.cpp +++ b/src/hotspot/share/cds/classListWriter.cpp @@ -128,9 +128,15 @@ void ClassListWriter::write_to_stream(const InstanceKlass* k, outputStream* stre } } - // filter out java/lang/invoke/BoundMethodHandle$Species... - if (cfs != nullptr && cfs->source() != nullptr && strcmp(cfs->source(), "_ClassSpecializer_generateConcreteSpeciesCode") == 0) { - return; + if (cfs != nullptr && cfs->source() != nullptr) { + if (strcmp(cfs->source(), "_ClassSpecializer_generateConcreteSpeciesCode") == 0) { + return; + } + + if (strncmp(cfs->source(), "__", 2) == 0) { + // generated class: __dynamic_proxy__, __JVM_LookupDefineClass__, etc + return; + } } { @@ -256,6 +262,18 @@ void ClassListWriter::write_resolved_constants_for(InstanceKlass* ik) { } if (cp->cache() != nullptr) { + Array* indy_entries = cp->cache()->resolved_indy_entries(); + if (indy_entries != nullptr) { + for (int i = 0; i < indy_entries->length(); i++) { + ResolvedIndyEntry* rie = indy_entries->adr_at(i); + int cp_index = rie->constant_pool_index(); + if (rie->is_resolved()) { + list.at_put(cp_index, true); + print = true; + } + } + } + Array* field_entries = cp->cache()->resolved_field_entries(); if (field_entries != nullptr) { for (int i = 0; i < field_entries->length(); i++) { @@ -274,7 +292,8 @@ void ClassListWriter::write_resolved_constants_for(InstanceKlass* ik) { ResolvedMethodEntry* rme = method_entries->adr_at(i); if (rme->is_resolved(Bytecodes::_invokevirtual) || rme->is_resolved(Bytecodes::_invokespecial) || - rme->is_resolved(Bytecodes::_invokeinterface)) { + rme->is_resolved(Bytecodes::_invokeinterface) || + rme->is_resolved(Bytecodes::_invokehandle)) { list.at_put(rme->constant_pool_index(), true); print = true; } @@ -291,7 +310,8 @@ void ClassListWriter::write_resolved_constants_for(InstanceKlass* ik) { assert(cp_tag.value() == JVM_CONSTANT_Class || cp_tag.value() == JVM_CONSTANT_Fieldref || cp_tag.value() == JVM_CONSTANT_Methodref|| - cp_tag.value() == JVM_CONSTANT_InterfaceMethodref, "sanity"); + cp_tag.value() == JVM_CONSTANT_InterfaceMethodref || + cp_tag.value() == JVM_CONSTANT_InvokeDynamic, "sanity"); stream->print(" %d", i); } } diff --git a/src/hotspot/share/cds/classPrelinker.cpp b/src/hotspot/share/cds/classPrelinker.cpp deleted file mode 100644 index 6b866bac995..00000000000 --- a/src/hotspot/share/cds/classPrelinker.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2022, 2024, 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 "cds/archiveBuilder.hpp" -#include "cds/cdsConfig.hpp" -#include "cds/classPrelinker.hpp" -#include "cds/regeneratedClasses.hpp" -#include "classfile/systemDictionary.hpp" -#include "classfile/systemDictionaryShared.hpp" -#include "classfile/vmClasses.hpp" -#include "interpreter/bytecodeStream.hpp" -#include "interpreter/interpreterRuntime.hpp" -#include "memory/resourceArea.hpp" -#include "oops/constantPool.inline.hpp" -#include "oops/instanceKlass.hpp" -#include "oops/klass.inline.hpp" -#include "runtime/handles.inline.hpp" - -ClassPrelinker::ClassesTable* ClassPrelinker::_processed_classes = nullptr; -ClassPrelinker::ClassesTable* ClassPrelinker::_vm_classes = nullptr; - -bool ClassPrelinker::is_vm_class(InstanceKlass* ik) { - return (_vm_classes->get(ik) != nullptr); -} - -void ClassPrelinker::add_one_vm_class(InstanceKlass* ik) { - bool created; - _vm_classes->put_if_absent(ik, &created); - if (created) { - InstanceKlass* super = ik->java_super(); - if (super != nullptr) { - add_one_vm_class(super); - } - Array* ifs = ik->local_interfaces(); - for (int i = 0; i < ifs->length(); i++) { - add_one_vm_class(ifs->at(i)); - } - } -} - -void ClassPrelinker::initialize() { - assert(_vm_classes == nullptr, "must be"); - _vm_classes = new (mtClass)ClassesTable(); - _processed_classes = new (mtClass)ClassesTable(); - for (auto id : EnumRange{}) { - add_one_vm_class(vmClasses::klass_at(id)); - } -} - -void ClassPrelinker::dispose() { - assert(_vm_classes != nullptr, "must be"); - delete _vm_classes; - delete _processed_classes; - _vm_classes = nullptr; - _processed_classes = nullptr; -} - -// Returns true if we CAN PROVE that cp_index will always resolve to -// the same information at both dump time and run time. This is a -// necessary (but not sufficient) condition for pre-resolving cp_index -// during CDS archive assembly. -bool ClassPrelinker::is_resolution_deterministic(ConstantPool* cp, int cp_index) { - assert(!is_in_archivebuilder_buffer(cp), "sanity"); - - if (cp->tag_at(cp_index).is_klass()) { - // We require cp_index to be already resolved. This is fine for now, are we - // currently archive only CP entries that are already resolved. - Klass* resolved_klass = cp->resolved_klass_at(cp_index); - return resolved_klass != nullptr && is_class_resolution_deterministic(cp->pool_holder(), resolved_klass); - } else if (cp->tag_at(cp_index).is_field() || - cp->tag_at(cp_index).is_method() || - cp->tag_at(cp_index).is_interface_method()) { - int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); - if (!cp->tag_at(klass_cp_index).is_klass()) { - // Not yet resolved - return false; - } - Klass* k = cp->resolved_klass_at(klass_cp_index); - if (!is_class_resolution_deterministic(cp->pool_holder(), k)) { - return false; - } - - if (!k->is_instance_klass()) { - // TODO: support non instance klasses as well. - return false; - } - - // Here, We don't check if this entry can actually be resolved to a valid Field/Method. - // This method should be called by the ConstantPool to check Fields/Methods that - // have already been successfully resolved. - return true; - } else { - return false; - } -} - -bool ClassPrelinker::is_class_resolution_deterministic(InstanceKlass* cp_holder, Klass* resolved_class) { - assert(!is_in_archivebuilder_buffer(cp_holder), "sanity"); - assert(!is_in_archivebuilder_buffer(resolved_class), "sanity"); - - if (resolved_class->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(resolved_class); - - if (!ik->is_shared() && SystemDictionaryShared::is_excluded_class(ik)) { - return false; - } - - if (cp_holder->is_subtype_of(ik)) { - // All super types of ik will be resolved in ik->class_loader() before - // ik is defined in this loader, so it's safe to archive the resolved klass reference. - return true; - } - - if (is_vm_class(ik)) { - if (ik->class_loader() != cp_holder->class_loader()) { - // At runtime, cp_holder() may not be able to resolve to the same - // ik. For example, a different version of ik may be defined in - // cp->pool_holder()'s loader using MethodHandles.Lookup.defineClass(). - return false; - } else { - return true; - } - } - } else if (resolved_class->is_objArray_klass()) { - Klass* elem = ObjArrayKlass::cast(resolved_class)->bottom_klass(); - if (elem->is_instance_klass()) { - return is_class_resolution_deterministic(cp_holder, InstanceKlass::cast(elem)); - } else if (elem->is_typeArray_klass()) { - return true; - } - } else if (resolved_class->is_typeArray_klass()) { - return true; - } - - return false; -} - -void ClassPrelinker::dumptime_resolve_constants(InstanceKlass* ik, TRAPS) { - if (!ik->is_linked()) { - return; - } - bool first_time; - _processed_classes->put_if_absent(ik, &first_time); - if (!first_time) { - // We have already resolved the constants in class, so no need to do it again. - return; - } - - constantPoolHandle cp(THREAD, ik->constants()); - for (int cp_index = 1; cp_index < cp->length(); cp_index++) { // Index 0 is unused - switch (cp->tag_at(cp_index).value()) { - case JVM_CONSTANT_String: - resolve_string(cp, cp_index, CHECK); // may throw OOM when interning strings. - break; - } - } -} - -// This works only for the boot/platform/app loaders -Klass* ClassPrelinker::find_loaded_class(Thread* current, oop class_loader, Symbol* name) { - HandleMark hm(current); - Handle h_loader(current, class_loader); - Klass* k = SystemDictionary::find_instance_or_array_klass(current, name, - h_loader, - Handle()); - if (k != nullptr) { - return k; - } - if (h_loader() == SystemDictionary::java_system_loader()) { - return find_loaded_class(current, SystemDictionary::java_platform_loader(), name); - } else if (h_loader() == SystemDictionary::java_platform_loader()) { - return find_loaded_class(current, nullptr, name); - } else { - assert(h_loader() == nullptr, "This function only works for boot/platform/app loaders %p %p %p", - cast_from_oop
(h_loader()), - cast_from_oop
(SystemDictionary::java_system_loader()), - cast_from_oop
(SystemDictionary::java_platform_loader())); - } - - return nullptr; -} - -Klass* ClassPrelinker::find_loaded_class(Thread* current, ConstantPool* cp, int class_cp_index) { - Symbol* name = cp->klass_name_at(class_cp_index); - return find_loaded_class(current, cp->pool_holder()->class_loader(), name); -} - -#if INCLUDE_CDS_JAVA_HEAP -void ClassPrelinker::resolve_string(constantPoolHandle cp, int cp_index, TRAPS) { - if (CDSConfig::is_dumping_heap()) { - int cache_index = cp->cp_to_object_index(cp_index); - ConstantPool::string_at_impl(cp, cp_index, cache_index, CHECK); - } -} -#endif - -void ClassPrelinker::preresolve_class_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray* preresolve_list) { - if (!SystemDictionaryShared::is_builtin_loader(ik->class_loader_data())) { - return; - } - - JavaThread* THREAD = current; - constantPoolHandle cp(THREAD, ik->constants()); - for (int cp_index = 1; cp_index < cp->length(); cp_index++) { - if (cp->tag_at(cp_index).value() == JVM_CONSTANT_UnresolvedClass) { - if (preresolve_list != nullptr && preresolve_list->at(cp_index) == false) { - // This class was not resolved during trial run. Don't attempt to resolve it. Otherwise - // the compiler may generate less efficient code. - continue; - } - if (find_loaded_class(current, cp(), cp_index) == nullptr) { - // Do not resolve any class that has not been loaded yet - continue; - } - Klass* resolved_klass = cp->klass_at(cp_index, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; // just ignore - } else { - log_trace(cds, resolve)("Resolved class [%3d] %s -> %s", cp_index, ik->external_name(), - resolved_klass->external_name()); - } - } - } -} - -void ClassPrelinker::preresolve_field_and_method_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray* preresolve_list) { - JavaThread* THREAD = current; - constantPoolHandle cp(THREAD, ik->constants()); - if (cp->cache() == nullptr) { - return; - } - for (int i = 0; i < ik->methods()->length(); i++) { - Method* m = ik->methods()->at(i); - BytecodeStream bcs(methodHandle(THREAD, m)); - while (!bcs.is_last_bytecode()) { - bcs.next(); - Bytecodes::Code raw_bc = bcs.raw_code(); - switch (raw_bc) { - case Bytecodes::_getfield: - case Bytecodes::_putfield: - maybe_resolve_fmi_ref(ik, m, raw_bc, bcs.get_index_u2(), preresolve_list, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; // just ignore - } - break; - case Bytecodes::_invokespecial: - case Bytecodes::_invokevirtual: - case Bytecodes::_invokeinterface: - maybe_resolve_fmi_ref(ik, m, raw_bc, bcs.get_index_u2(), preresolve_list, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; // just ignore - } - break; - default: - break; - } - } - } -} - -void ClassPrelinker::maybe_resolve_fmi_ref(InstanceKlass* ik, Method* m, Bytecodes::Code bc, int raw_index, - GrowableArray* preresolve_list, TRAPS) { - methodHandle mh(THREAD, m); - constantPoolHandle cp(THREAD, ik->constants()); - HandleMark hm(THREAD); - int cp_index = cp->to_cp_index(raw_index, bc); - - if (cp->is_resolved(raw_index, bc)) { - return; - } - - if (preresolve_list != nullptr && preresolve_list->at(cp_index) == false) { - // This field wasn't resolved during the trial run. Don't attempt to resolve it. Otherwise - // the compiler may generate less efficient code. - return; - } - - int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); - if (find_loaded_class(THREAD, cp(), klass_cp_index) == nullptr) { - // Do not resolve any field/methods from a class that has not been loaded yet. - return; - } - - Klass* resolved_klass = cp->klass_ref_at(raw_index, bc, CHECK); - - switch (bc) { - case Bytecodes::_getfield: - case Bytecodes::_putfield: - InterpreterRuntime::resolve_get_put(bc, raw_index, mh, cp, false /*initialize_holder*/, CHECK); - break; - - case Bytecodes::_invokevirtual: - case Bytecodes::_invokespecial: - case Bytecodes::_invokeinterface: - InterpreterRuntime::cds_resolve_invoke(bc, raw_index, cp, CHECK); - break; - - default: - ShouldNotReachHere(); - } - - if (log_is_enabled(Trace, cds, resolve)) { - ResourceMark rm(THREAD); - bool resolved = cp->is_resolved(raw_index, bc); - Symbol* name = cp->name_ref_at(raw_index, bc); - Symbol* signature = cp->signature_ref_at(raw_index, bc); - log_trace(cds, resolve)("%s %s [%3d] %s -> %s.%s:%s", - (resolved ? "Resolved" : "Failed to resolve"), - Bytecodes::name(bc), cp_index, ik->external_name(), - resolved_klass->external_name(), - name->as_C_string(), signature->as_C_string()); - } -} - -#ifdef ASSERT -bool ClassPrelinker::is_in_archivebuilder_buffer(address p) { - if (!Thread::current()->is_VM_thread() || ArchiveBuilder::current() == nullptr) { - return false; - } else { - return ArchiveBuilder::current()->is_in_buffer_space(p); - } -} -#endif diff --git a/src/hotspot/share/cds/dumpAllocStats.cpp b/src/hotspot/share/cds/dumpAllocStats.cpp index 25351f78d84..e88a77de7ad 100644 --- a/src/hotspot/share/cds/dumpAllocStats.cpp +++ b/src/hotspot/share/cds/dumpAllocStats.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "cds/aotClassLinker.hpp" #include "cds/dumpAllocStats.hpp" #include "logging/log.hpp" #include "logging/logMessage.hpp" @@ -114,6 +115,12 @@ void DumpAllocStats::print_stats(int ro_all, int rw_all) { _num_method_cp_entries, _num_method_cp_entries_archived, percent_of(_num_method_cp_entries_archived, _num_method_cp_entries), _num_method_cp_entries_reverted); + msg.info("Indy CP entries = %6d, archived = %6d (%5.1f%%), reverted = %6d", + _num_indy_cp_entries, _num_indy_cp_entries_archived, + percent_of(_num_indy_cp_entries_archived, _num_indy_cp_entries), + _num_indy_cp_entries_reverted); + msg.info("Platform loader initiated classes = %5d", AOTClassLinker::num_platform_initiated_classes()); + msg.info("App loader initiated classes = %5d", AOTClassLinker::num_app_initiated_classes()); } #ifdef ASSERT diff --git a/src/hotspot/share/cds/dumpAllocStats.hpp b/src/hotspot/share/cds/dumpAllocStats.hpp index 2ff81c52392..7d651320e6f 100644 --- a/src/hotspot/share/cds/dumpAllocStats.hpp +++ b/src/hotspot/share/cds/dumpAllocStats.hpp @@ -68,6 +68,9 @@ class DumpAllocStats : public StackObj { int _num_field_cp_entries; int _num_field_cp_entries_archived; int _num_field_cp_entries_reverted; + int _num_indy_cp_entries; + int _num_indy_cp_entries_archived; + int _num_indy_cp_entries_reverted; int _num_klass_cp_entries; int _num_klass_cp_entries_archived; int _num_klass_cp_entries_reverted; @@ -84,6 +87,9 @@ class DumpAllocStats : public StackObj { _num_field_cp_entries = 0; _num_field_cp_entries_archived = 0; _num_field_cp_entries_reverted = 0; + _num_indy_cp_entries = 0; + _num_indy_cp_entries_archived = 0; + _num_indy_cp_entries_reverted = 0; _num_klass_cp_entries = 0; _num_klass_cp_entries_archived = 0; _num_klass_cp_entries_reverted = 0; @@ -122,6 +128,12 @@ class DumpAllocStats : public StackObj { _num_field_cp_entries_reverted += reverted ? 1 : 0; } + void record_indy_cp_entry(bool archived, bool reverted) { + _num_indy_cp_entries ++; + _num_indy_cp_entries_archived += archived ? 1 : 0; + _num_indy_cp_entries_reverted += reverted ? 1 : 0; + } + void record_klass_cp_entry(bool archived, bool reverted) { _num_klass_cp_entries ++; _num_klass_cp_entries_archived += archived ? 1 : 0; diff --git a/src/hotspot/share/cds/dumpTimeClassInfo.hpp b/src/hotspot/share/cds/dumpTimeClassInfo.hpp index 5ba79e54c79..c060601f1fb 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.hpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -42,7 +42,8 @@ class DumpTimeClassInfo: public CHeapObj { bool _excluded; bool _is_early_klass; bool _has_checked_exclusion; - + bool _is_required_hidden_class; + bool _has_scanned_constant_pool; class DTLoaderConstraint { Symbol* _name; char _loader_type1; @@ -137,6 +138,8 @@ class DumpTimeClassInfo: public CHeapObj { _failed_verification = false; _is_archived_lambda_proxy = false; _has_checked_exclusion = false; + _is_required_hidden_class = false; + _has_scanned_constant_pool = false; _id = -1; _clsfile_size = -1; _clsfile_crc32 = -1; @@ -214,6 +217,11 @@ class DumpTimeClassInfo: public CHeapObj { InstanceKlass* nest_host() const { return _nest_host; } void set_nest_host(InstanceKlass* nest_host) { _nest_host = nest_host; } + bool is_required_hidden_class() const { return _is_required_hidden_class; } + void set_is_required_hidden_class() { _is_required_hidden_class = true; } + bool has_scanned_constant_pool() const { return _has_scanned_constant_pool; } + void set_has_scanned_constant_pool() { _has_scanned_constant_pool = true; } + size_t runtime_info_bytesize() const; }; diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index 04c60b89580..f102282f682 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -23,12 +23,12 @@ */ #include "precompiled.hpp" +#include "cds/aotClassLinker.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveHeapWriter.hpp" #include "cds/archiveUtils.inline.hpp" #include "cds/cds_globals.hpp" #include "cds/cdsConfig.hpp" -#include "cds/classPrelinker.hpp" #include "cds/dynamicArchive.hpp" #include "cds/regeneratedClasses.hpp" #include "classfile/classLoader.hpp" @@ -47,8 +47,8 @@ #include "runtime/arguments.hpp" #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" -#include "runtime/vmThread.hpp" #include "runtime/vmOperations.hpp" +#include "runtime/vmThread.hpp" #include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" @@ -112,7 +112,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder { // Block concurrent class unloading from changing the _dumptime_table MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); - SystemDictionaryShared::check_excluded_classes(); + SystemDictionaryShared::find_all_archivable_classes(); if (SystemDictionaryShared::is_dumptime_table_empty()) { log_warning(cds, dynamic)("There is no class to be included in the dynamic archive."); @@ -135,6 +135,11 @@ class DynamicArchiveBuilder : public ArchiveBuilder { verify_estimate_size(_estimated_metaspaceobj_bytes, "MetaspaceObjs"); + sort_methods(); + + log_info(cds)("Make classes shareable"); + make_klasses_shareable(); + char* serialized_data; { // Write the symbol table and system dictionaries to the RO space. @@ -147,6 +152,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder { ArchiveBuilder::OtherROAllocMark mark; SystemDictionaryShared::write_to_archive(false); DynamicArchive::dump_array_klasses(); + AOTClassLinker::write_to_archive(); serialized_data = ro_region()->top(); WriteClosure wc(ro_region()); @@ -155,11 +161,6 @@ class DynamicArchiveBuilder : public ArchiveBuilder { verify_estimate_size(_estimated_hashtable_bytes, "Hashtables"); - sort_methods(); - - log_info(cds)("Make classes shareable"); - make_klasses_shareable(); - log_info(cds)("Adjust lambda proxy class dictionary"); SystemDictionaryShared::adjust_lambda_proxy_class_dictionary(); @@ -234,7 +235,7 @@ void DynamicArchiveBuilder::release_header() { void DynamicArchiveBuilder::post_dump() { ArchivePtrMarker::reset_map_and_vs(); - ClassPrelinker::dispose(); + AOTClassLinker::dispose(); } void DynamicArchiveBuilder::sort_methods() { @@ -497,6 +498,7 @@ void DynamicArchive::check_for_dynamic_dump() { void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) { ExceptionMark em(current); ResourceMark rm(current); + CDSConfig::DumperThreadMark dumper_thread_mark(current); if (!CDSConfig::is_dumping_dynamic_archive() || archive_name == nullptr) { return; @@ -526,6 +528,7 @@ void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) // This is called by "jcmd VM.cds dynamic_dump" void DynamicArchive::dump_for_jcmd(const char* archive_name, TRAPS) { + CDSConfig::DumperThreadMark dumper_thread_mark(THREAD); assert(CDSConfig::is_using_archive() && RecordDynamicDumpInfo, "already checked in arguments.cpp"); assert(ArchiveClassesAtExit == nullptr, "already checked in arguments.cpp"); assert(CDSConfig::is_dumping_dynamic_archive(), "already checked by check_for_dynamic_dump() during VM startup"); diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 5e88b3c47e4..d33710a65a3 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -223,7 +223,9 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment, } _max_heap_size = MaxHeapSize; _use_optimized_module_handling = CDSConfig::is_using_optimized_module_handling(); + _has_aot_linked_classes = CDSConfig::is_dumping_aot_linked_classes(); _has_full_module_graph = CDSConfig::is_dumping_full_module_graph(); + _has_archived_invokedynamic = CDSConfig::is_dumping_invokedynamic(); // The following fields are for sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's @@ -313,6 +315,8 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- allow_archiving_with_java_agent:%d", _allow_archiving_with_java_agent); st->print_cr("- use_optimized_module_handling: %d", _use_optimized_module_handling); st->print_cr("- has_full_module_graph %d", _has_full_module_graph); + st->print_cr("- has_aot_linked_classes %d", _has_aot_linked_classes); + st->print_cr("- has_archived_invokedynamic %d", _has_archived_invokedynamic); } void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) { @@ -1060,7 +1064,9 @@ bool FileMapInfo::validate_shared_path_table() { } } - validate_non_existent_class_paths(); + if (!validate_non_existent_class_paths()) { + return false; + } _validating_shared_path_table = false; @@ -1076,7 +1082,7 @@ bool FileMapInfo::validate_shared_path_table() { return true; } -void FileMapInfo::validate_non_existent_class_paths() { +bool FileMapInfo::validate_non_existent_class_paths() { // All of the recorded non-existent paths came from the Class-Path: attribute from the JAR // files on the app classpath. If any of these are found to exist during runtime, // it will change how classes are loading for the app loader. For safety, disable @@ -1089,11 +1095,19 @@ void FileMapInfo::validate_non_existent_class_paths() { i++) { SharedClassPathEntry* ent = shared_path(i); if (!ent->check_non_existent()) { - log_warning(cds)("Archived non-system classes are disabled because the " - "file %s exists", ent->name()); - header()->set_has_platform_or_app_classes(false); + if (header()->has_aot_linked_classes()) { + log_error(cds)("CDS archive has aot-linked classes. It cannot be used because the " + "file %s exists", ent->name()); + return false; + } else { + log_warning(cds)("Archived non-system classes are disabled because the " + "file %s exists", ent->name()); + header()->set_has_platform_or_app_classes(false); + } } } + + return true; } // A utility class for reading/validating the GenericCDSFileMapHeader portion of @@ -1958,6 +1972,32 @@ char* FileMapInfo::map_bitmap_region() { return bitmap_base; } +class SharedDataRelocationTask : public ArchiveWorkerTask { +private: + BitMapView* const _rw_bm; + BitMapView* const _ro_bm; + SharedDataRelocator* const _rw_reloc; + SharedDataRelocator* const _ro_reloc; + +public: + SharedDataRelocationTask(BitMapView* rw_bm, BitMapView* ro_bm, SharedDataRelocator* rw_reloc, SharedDataRelocator* ro_reloc) : + ArchiveWorkerTask("Shared Data Relocation"), + _rw_bm(rw_bm), _ro_bm(ro_bm), _rw_reloc(rw_reloc), _ro_reloc(ro_reloc) {} + + void work(int chunk, int max_chunks) override { + work_on(chunk, max_chunks, _rw_bm, _rw_reloc); + work_on(chunk, max_chunks, _ro_bm, _ro_reloc); + } + + void work_on(int chunk, int max_chunks, BitMapView* bm, SharedDataRelocator* reloc) { + BitMap::idx_t size = bm->size(); + BitMap::idx_t start = MIN2(size, size * chunk / max_chunks); + BitMap::idx_t end = MIN2(size, size * (chunk + 1) / max_chunks); + assert(end > start, "Sanity: no empty slices"); + bm->iterate(reloc, start, end); + } +}; + // This is called when we cannot map the archive at the requested[ base address (usually 0x800000000). // We relocate all pointers in the 2 core regions (ro, rw). bool FileMapInfo::relocate_pointers_in_core_regions(intx addr_delta) { @@ -1996,8 +2036,14 @@ bool FileMapInfo::relocate_pointers_in_core_regions(intx addr_delta) { valid_new_base, valid_new_end, addr_delta); SharedDataRelocator ro_patcher((address*)ro_patch_base + header()->ro_ptrmap_start_pos(), (address*)ro_patch_end, valid_old_base, valid_old_end, valid_new_base, valid_new_end, addr_delta); - rw_ptrmap.iterate(&rw_patcher); - ro_ptrmap.iterate(&ro_patcher); + + if (AOTCacheParallelRelocation) { + SharedDataRelocationTask task(&rw_ptrmap, &ro_ptrmap, &rw_patcher, &ro_patcher); + ArchiveWorkers::workers()->run_task(&task); + } else { + rw_ptrmap.iterate(&rw_patcher); + ro_ptrmap.iterate(&ro_patcher); + } // The MetaspaceShared::bm region will be unmapped in MetaspaceShared::initialize_shared_spaces(). @@ -2074,7 +2120,16 @@ void FileMapInfo::map_or_load_heap_region() { } if (!success) { - CDSConfig::stop_using_full_module_graph(); + if (CDSConfig::is_using_aot_linked_classes()) { + // It's too late to recover -- we have already committed to use the archived metaspace objects, but + // the archived heap objects cannot be loaded, so we don't have the archived FMG to guarantee that + // all AOT-linked classes are visible. + // + // We get here because the heap is too small. The app will fail anyway. So let's quit. + MetaspaceShared::unrecoverable_loading_error("CDS archive has aot-linked classes but the archived " + "heap objects cannot be loaded. Try increasing your heap size."); + } + CDSConfig::stop_using_full_module_graph("archive heap loading failed"); } } @@ -2429,6 +2484,34 @@ bool FileMapInfo::initialize() { return true; } +bool FileMapInfo::validate_aot_class_linking() { + // These checks need to be done after FileMapInfo::initialize(), which gets called before Universe::heap() + // is available. + if (header()->has_aot_linked_classes()) { + CDSConfig::set_has_aot_linked_classes(true); + if (JvmtiExport::should_post_class_file_load_hook()) { + log_error(cds)("CDS archive has aot-linked classes. It cannot be used when JVMTI ClassFileLoadHook is in use."); + return false; + } + if (JvmtiExport::has_early_vmstart_env()) { + log_error(cds)("CDS archive has aot-linked classes. It cannot be used when JVMTI early vm start is in use."); + return false; + } + if (!CDSConfig::is_using_full_module_graph()) { + log_error(cds)("CDS archive has aot-linked classes. It cannot be used when archived full module graph is not used."); + return false; + } + + const char* prop = Arguments::get_property("java.security.manager"); + if (prop != nullptr && strcmp(prop, "disallow") != 0) { + log_error(cds)("CDS archive has aot-linked classes. It cannot be used with -Djava.security.manager=%s.", prop); + return false; + } + } + + return true; +} + // The 2 core spaces are RW->RO FileMapRegion* FileMapInfo::first_core_region() const { return region_at(MetaspaceShared::rw); @@ -2478,6 +2561,11 @@ bool FileMapHeader::validate() { // header data const char* prop = Arguments::get_property("java.system.class.loader"); if (prop != nullptr) { + if (has_aot_linked_classes()) { + log_error(cds)("CDS archive has aot-linked classes. It cannot be used when the " + "java.system.class.loader property is specified."); + return false; + } log_warning(cds)("Archived non-system classes are disabled because the " "java.system.class.loader property is specified (value = \"%s\"). " "To use archived non-system classes, this property must not be set", prop); @@ -2542,9 +2630,15 @@ bool FileMapHeader::validate() { log_info(cds)("optimized module handling: disabled because archive was created without optimized module handling"); } - if (is_static() && !_has_full_module_graph) { + if (is_static()) { // Only the static archive can contain the full module graph. - CDSConfig::stop_using_full_module_graph("archive was created without full module graph"); + if (!_has_full_module_graph) { + CDSConfig::stop_using_full_module_graph("archive was created without full module graph"); + } + + if (_has_archived_invokedynamic) { + CDSConfig::set_has_archived_invokedynamic(); + } } return true; diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 6a15ff03c3a..6319c51f1ce 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -228,7 +228,9 @@ class FileMapHeader: private CDSFileMapHeaderBase { bool _allow_archiving_with_java_agent; // setting of the AllowArchivingWithJavaAgent option bool _use_optimized_module_handling;// No module-relation VM options were specified, so we can skip // some expensive operations. + bool _has_aot_linked_classes; // Was the CDS archive created with -XX:+AOTClassLinking bool _has_full_module_graph; // Does this CDS archive contain the full archived module graph? + bool _has_archived_invokedynamic; // Does the archive have aot-linked invokedynamic CP entries? HeapRootSegments _heap_root_segments; // Heap root segments info size_t _heap_oopmap_start_pos; // The first bit in the oopmap corresponds to this position in the heap. size_t _heap_ptrmap_start_pos; // The first bit in the ptrmap corresponds to this position in the heap. @@ -273,6 +275,7 @@ class FileMapHeader: private CDSFileMapHeaderBase { char* mapped_base_address() const { return _mapped_base_address; } bool has_platform_or_app_classes() const { return _has_platform_or_app_classes; } bool has_non_jar_in_classpath() const { return _has_non_jar_in_classpath; } + bool has_aot_linked_classes() const { return _has_aot_linked_classes; } bool compressed_oops() const { return _compressed_oops; } bool compressed_class_pointers() const { return _compressed_class_ptrs; } int narrow_klass_pointer_bits() const { return _narrow_klass_pointer_bits; } @@ -492,7 +495,8 @@ class FileMapInfo : public CHeapObj { static void check_nonempty_dir_in_shared_path_table(); bool check_module_paths(); bool validate_shared_path_table(); - void validate_non_existent_class_paths(); + bool validate_non_existent_class_paths(); + bool validate_aot_class_linking(); static void set_shared_path_table(FileMapInfo* info) { _shared_path_table = info->header()->shared_path_table(); } diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 22040448770..d2ab109cc72 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "cds/aotClassInitializer.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveHeapLoader.hpp" #include "cds/archiveHeapWriter.hpp" @@ -97,7 +98,7 @@ size_t HeapShared::_total_obj_size; #define ARCHIVE_TEST_FIELD_NAME "archivedObjects" static Array* _archived_ArchiveHeapTestClass = nullptr; static const char* _test_class_name = nullptr; -static const Klass* _test_class = nullptr; +static Klass* _test_class = nullptr; static const ArchivedKlassSubGraphInfoRecord* _test_class_record = nullptr; #endif @@ -119,6 +120,7 @@ static ArchivableStaticFieldInfo archive_subgraph_entry_fields[] = { {"java/lang/ModuleLayer", "EMPTY_LAYER"}, {"java/lang/module/Configuration", "EMPTY_CONFIGURATION"}, {"jdk/internal/math/FDBigInteger", "archivedCaches"}, + #ifndef PRODUCT {nullptr, nullptr}, // Extra slot for -XX:ArchiveHeapTestClass #endif @@ -133,7 +135,8 @@ static ArchivableStaticFieldInfo fmg_archive_subgraph_entry_fields[] = { {nullptr, nullptr}, }; -KlassSubGraphInfo* HeapShared::_default_subgraph_info; +KlassSubGraphInfo* HeapShared::_dump_time_special_subgraph; +ArchivedKlassSubGraphInfoRecord* HeapShared::_run_time_special_subgraph; GrowableArrayCHeap* HeapShared::_pending_roots = nullptr; GrowableArrayCHeap* HeapShared::_root_segments; int HeapShared::_root_segment_max_size_elems; @@ -298,6 +301,7 @@ bool HeapShared::archive_object(oop obj) { if (ArchiveHeapWriter::is_too_large_to_archive(obj->size())) { log_debug(cds, heap)("Cannot archive, object (" PTR_FORMAT ") is too large: " SIZE_FORMAT, p2i(obj), obj->size()); + debug_trace(); return false; } else { count_allocation(obj->size()); @@ -309,8 +313,19 @@ bool HeapShared::archive_object(oop obj) { if (log_is_enabled(Debug, cds, heap)) { ResourceMark rm; - log_debug(cds, heap)("Archived heap object " PTR_FORMAT " : %s", - p2i(obj), obj->klass()->external_name()); + LogTarget(Debug, cds, heap) log; + LogStream out(log); + out.print("Archived heap object " PTR_FORMAT " : %s ", + p2i(obj), obj->klass()->external_name()); + if (java_lang_Class::is_instance(obj)) { + Klass* k = java_lang_Class::as_Klass(obj); + if (k != nullptr) { + out.print("%s", k->external_name()); + } else { + out.print("primitive"); + } + } + out.cr(); } if (java_lang_Module::is_instance(obj) && Modules::check_archived_module_oop(obj)) { @@ -371,6 +386,31 @@ void HeapShared::init_scratch_objects(TRAPS) { _scratch_references_table = new (mtClass)MetaspaceObjToOopHandleTable(); } +// Given java_mirror that represents a (primitive or reference) type T, +// return the "scratch" version that represents the same type T. +// Note that if java_mirror will be returned if it's already a +// scratch mirror. +// +// See java_lang_Class::create_scratch_mirror() for more info. +oop HeapShared::scratch_java_mirror(oop java_mirror) { + assert(java_lang_Class::is_instance(java_mirror), "must be"); + + for (int i = T_BOOLEAN; i < T_VOID+1; i++) { + BasicType bt = (BasicType)i; + if (!is_reference_type(bt)) { + if (_scratch_basic_type_mirrors[i].resolve() == java_mirror) { + return java_mirror; + } + } + } + + if (java_lang_Class::is_primitive(java_mirror)) { + return scratch_java_mirror(java_lang_Class::as_BasicType(java_mirror)); + } else { + return scratch_java_mirror(java_lang_Class::as_Klass(java_mirror)); + } +} + oop HeapShared::scratch_java_mirror(BasicType t) { assert((uint)t < T_VOID+1, "range check"); assert(!is_reference_type(t), "sanity"); @@ -399,13 +439,134 @@ void HeapShared::remove_scratch_objects(Klass* k) { } } +//TODO: we eventually want a more direct test for these kinds of things. +//For example the JVM could record some bit of context from the creation +//of the klass, such as who called the hidden class factory. Using +//string compares on names is fragile and will break as soon as somebody +//changes the names in the JDK code. See discussion in JDK-8342481 for +//related ideas about marking AOT-related classes. +bool HeapShared::is_lambda_form_klass(InstanceKlass* ik) { + return ik->is_hidden() && + (ik->name()->starts_with("java/lang/invoke/LambdaForm$MH+") || + ik->name()->starts_with("java/lang/invoke/LambdaForm$DMH+") || + ik->name()->starts_with("java/lang/invoke/LambdaForm$BMH+") || + ik->name()->starts_with("java/lang/invoke/LambdaForm$VH+")); +} + +bool HeapShared::is_lambda_proxy_klass(InstanceKlass* ik) { + return ik->is_hidden() && (ik->name()->index_of_at(0, "$$Lambda+", 9) > 0); +} + +bool HeapShared::is_string_concat_klass(InstanceKlass* ik) { + return ik->is_hidden() && ik->name()->starts_with("java/lang/String$$StringConcat"); +} + +bool HeapShared::is_archivable_hidden_klass(InstanceKlass* ik) { + return CDSConfig::is_dumping_invokedynamic() && + (is_lambda_form_klass(ik) || is_lambda_proxy_klass(ik) || is_string_concat_klass(ik)); +} + +void HeapShared::copy_aot_initialized_mirror(Klass* orig_k, oop orig_mirror, oop m) { + assert(orig_k->is_instance_klass(), "sanity"); + InstanceKlass* ik = InstanceKlass::cast(orig_k); + InstanceKlass* buffered_ik = ArchiveBuilder::current()->get_buffered_addr(ik); + + assert(ik->is_initialized(), "must be"); + + int nfields = 0; + for (JavaFieldStream fs(ik); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + fieldDescriptor& fd = fs.field_descriptor(); + int offset = fd.offset(); + switch (fd.field_type()) { + case T_OBJECT: + case T_ARRAY: + m->obj_field_put(offset, orig_mirror->obj_field(offset)); + break; + case T_BOOLEAN: + m->bool_field_put(offset, orig_mirror->bool_field(offset)); + break; + case T_BYTE: + m->byte_field_put(offset, orig_mirror->byte_field(offset)); + break; + case T_SHORT: + m->short_field_put(offset, orig_mirror->short_field(offset)); + break; + case T_CHAR: + m->char_field_put(offset, orig_mirror->char_field(offset)); + break; + case T_INT: + m->int_field_put(offset, orig_mirror->int_field(offset)); + break; + case T_LONG: + m->long_field_put(offset, orig_mirror->long_field(offset)); + break; + case T_FLOAT: + m->float_field_put(offset, orig_mirror->float_field(offset)); + break; + case T_DOUBLE: + m->double_field_put(offset, orig_mirror->double_field(offset)); + break; + default: + ShouldNotReachHere(); + } + nfields ++; + } + } + + java_lang_Class::set_class_data(m, java_lang_Class::class_data(orig_mirror)); + + // Class::reflectData use SoftReference, which cannot be archived. Set it + // to null and it will be recreated at runtime. + java_lang_Class::set_reflection_data(m, nullptr); + + if (log_is_enabled(Info, cds, init)) { + ResourceMark rm; + log_debug(cds, init)("copied %3d field(s) in aot-initialized mirror %s%s", nfields, ik->external_name(), + ik->is_hidden() ? " (hidden)" : ""); + } +} + +static void copy_java_mirror_hashcode(oop orig_mirror, oop scratch_m) { + // We need to retain the identity_hash, because it may have been used by some hashtables + // in the shared heap. + if (!orig_mirror->fast_no_hash_check()) { + intptr_t src_hash = orig_mirror->identity_hash(); + if (UseCompactObjectHeaders) { + narrowKlass nk = CompressedKlassPointers::encode(orig_mirror->klass()); + scratch_m->set_mark(markWord::prototype().set_narrow_klass(nk).copy_set_hash(src_hash)); + } else { + scratch_m->set_mark(markWord::prototype().copy_set_hash(src_hash)); + } + assert(scratch_m->mark().is_unlocked(), "sanity"); + + DEBUG_ONLY(intptr_t archived_hash = scratch_m->identity_hash()); + assert(src_hash == archived_hash, "Different hash codes: original " INTPTR_FORMAT ", archived " INTPTR_FORMAT, src_hash, archived_hash); + } +} + +static objArrayOop get_archived_resolved_references(InstanceKlass* src_ik) { + InstanceKlass* buffered_ik = ArchiveBuilder::current()->get_buffered_addr(src_ik); + if (buffered_ik->is_shared_boot_class() || + buffered_ik->is_shared_platform_class() || + buffered_ik->is_shared_app_class()) { + objArrayOop rr = src_ik->constants()->resolved_references_or_null(); + if (rr != nullptr && !ArchiveHeapWriter::is_too_large_to_archive(rr)) { + return HeapShared::scratch_resolved_references(src_ik->constants()); + } + } + return nullptr; +} + void HeapShared::archive_java_mirrors() { for (int i = T_BOOLEAN; i < T_VOID+1; i++) { BasicType bt = (BasicType)i; if (!is_reference_type(bt)) { + oop orig_mirror = Universe::java_mirror(bt); oop m = _scratch_basic_type_mirrors[i].resolve(); assert(m != nullptr, "sanity"); - bool success = archive_reachable_objects_from(1, _default_subgraph_info, m); + copy_java_mirror_hashcode(orig_mirror, m); + bool success = archive_reachable_objects_from(1, _dump_time_special_subgraph, m); assert(success, "sanity"); log_trace(cds, heap, mirror)( @@ -418,12 +579,23 @@ void HeapShared::archive_java_mirrors() { GrowableArray* klasses = ArchiveBuilder::current()->klasses(); assert(klasses != nullptr, "sanity"); + for (int i = 0; i < klasses->length(); i++) { Klass* orig_k = klasses->at(i); + oop orig_mirror = orig_k->java_mirror(); + oop m = scratch_java_mirror(orig_k); + if (m != nullptr) { + copy_java_mirror_hashcode(orig_mirror, m); + } + } + + for (int i = 0; i < klasses->length(); i++) { + Klass* orig_k = klasses->at(i); + oop orig_mirror = orig_k->java_mirror(); oop m = scratch_java_mirror(orig_k); if (m != nullptr) { Klass* buffered_k = ArchiveBuilder::get_buffered_klass(orig_k); - bool success = archive_reachable_objects_from(1, _default_subgraph_info, m); + bool success = archive_reachable_objects_from(1, _dump_time_special_subgraph, m); guarantee(success, "scratch mirrors must point to only archivable objects"); buffered_k->set_archived_java_mirror(append_root(m)); ResourceMark rm; @@ -434,9 +606,9 @@ void HeapShared::archive_java_mirrors() { // archive the resolved_referenes array if (buffered_k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(buffered_k); - oop rr = ik->constants()->prepare_resolved_references_for_archiving(); - if (rr != nullptr && !ArchiveHeapWriter::is_too_large_to_archive(rr)) { - bool success = HeapShared::archive_reachable_objects_from(1, _default_subgraph_info, rr); + objArrayOop rr = get_archived_resolved_references(InstanceKlass::cast(orig_k)); + if (rr != nullptr) { + bool success = HeapShared::archive_reachable_objects_from(1, _dump_time_special_subgraph, rr); assert(success, "must be"); int root_index = append_root(rr); ik->constants()->cache()->set_archived_references(root_index); @@ -448,7 +620,7 @@ void HeapShared::archive_java_mirrors() { void HeapShared::archive_strings() { oop shared_strings_array = StringTable::init_shared_table(_dumped_interned_strings); - bool success = archive_reachable_objects_from(1, _default_subgraph_info, shared_strings_array); + bool success = archive_reachable_objects_from(1, _dump_time_special_subgraph, shared_strings_array); // We must succeed because: // - _dumped_interned_strings do not contain any large strings. // - StringTable::init_shared_table() doesn't create any large arrays. @@ -457,7 +629,7 @@ void HeapShared::archive_strings() { } int HeapShared::archive_exception_instance(oop exception) { - bool success = archive_reachable_objects_from(1, _default_subgraph_info, exception); + bool success = archive_reachable_objects_from(1, _dump_time_special_subgraph, exception); assert(success, "sanity"); return append_root(exception); } @@ -466,6 +638,8 @@ void HeapShared::mark_native_pointers(oop orig_obj) { if (java_lang_Class::is_instance(orig_obj)) { ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::klass_offset()); ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::array_klass_offset()); + } else if (java_lang_invoke_ResolvedMethodName::is_instance(orig_obj)) { + ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_invoke_ResolvedMethodName::vmtarget_offset()); } } @@ -482,11 +656,121 @@ void HeapShared::set_has_native_pointers(oop src_obj) { info->set_has_native_pointers(); } +void HeapShared::start_finding_required_hidden_classes() { + if (!CDSConfig::is_dumping_invokedynamic()) { + return; + } + NoSafepointVerifier nsv; + + init_seen_objects_table(); + + // We first scan the objects that are known to be archived (from the archive_subgraph + // tables) + find_required_hidden_classes_helper(archive_subgraph_entry_fields); + if (CDSConfig::is_dumping_full_module_graph()) { + find_required_hidden_classes_helper(fmg_archive_subgraph_entry_fields); + } + + // Later, SystemDictionaryShared::find_all_archivable_classes_impl() will start + // scanning the constant pools of all classes that it decides to archive. +} + +void HeapShared::end_finding_required_hidden_classes() { + if (!CDSConfig::is_dumping_invokedynamic()) { + return; + } + NoSafepointVerifier nsv; + + delete_seen_objects_table(); +} + +void HeapShared::find_required_hidden_classes_helper(ArchivableStaticFieldInfo fields[]) { + if (!CDSConfig::is_dumping_heap()) { + return; + } + for (int i = 0; fields[i].valid(); i++) { + ArchivableStaticFieldInfo* f = &fields[i]; + InstanceKlass* k = f->klass; + oop m = k->java_mirror(); + oop o = m->obj_field(f->offset); + if (o != nullptr) { + find_required_hidden_classes_in_object(o); + } + } +} + +class HeapShared::FindRequiredHiddenClassesOopClosure: public BasicOopIterateClosure { + GrowableArray _stack; + template void do_oop_work(T *p) { + // Recurse on a GrowableArray to avoid overflowing the C stack. + oop o = RawAccess<>::oop_load(p); + if (o != nullptr) { + _stack.append(o); + } + } + + public: + + void do_oop(narrowOop *p) { FindRequiredHiddenClassesOopClosure::do_oop_work(p); } + void do_oop( oop *p) { FindRequiredHiddenClassesOopClosure::do_oop_work(p); } + + FindRequiredHiddenClassesOopClosure(oop o) { + _stack.append(o); + } + oop pop() { + if (_stack.length() == 0) { + return nullptr; + } else { + return _stack.pop(); + } + } +}; + +static void mark_required_if_hidden_class(Klass* k) { + if (k != nullptr && k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->is_hidden()) { + SystemDictionaryShared::mark_required_hidden_class(ik); + } + } +} + + +void HeapShared::find_required_hidden_classes_in_object(oop root) { + ResourceMark rm; + FindRequiredHiddenClassesOopClosure c(root); + oop o; + while ((o = c.pop()) != nullptr) { + if (!has_been_seen_during_subgraph_recording(o)) { + set_has_been_seen_during_subgraph_recording(o); + + // Mark the klass of this object + mark_required_if_hidden_class(o->klass()); + + // For special objects, mark the klass that they contain information about. + // - a Class that refers to an hidden class + // - a ResolvedMethodName that refers to a method declared in a hidden class + if (java_lang_Class::is_instance(o)) { + mark_required_if_hidden_class(java_lang_Class::as_Klass(o)); + } else if (java_lang_invoke_ResolvedMethodName::is_instance(o)) { + Method* m = java_lang_invoke_ResolvedMethodName::vmtarget(o); + if (m != nullptr) { + mark_required_if_hidden_class(m->method_holder()); + } + } + + o->oop_iterate(&c); + } + } +} + void HeapShared::archive_objects(ArchiveHeapInfo *heap_info) { { NoSafepointVerifier nsv; - _default_subgraph_info = init_subgraph_info(vmClasses::Object_klass(), false); + // The special subgraph doesn't belong to any class. We use Object_klass() here just + // for convenience. + _dump_time_special_subgraph = init_subgraph_info(vmClasses::Object_klass(), false); // Cache for recording where the archived objects are copied to create_archived_object_cache(); @@ -501,7 +785,7 @@ void HeapShared::archive_objects(ArchiveHeapInfo *heap_info) { copy_objects(); CDSHeapVerifier::verify(); - check_default_subgraph_classes(); + check_special_subgraph_classes(); } ArchiveHeapWriter::write(_pending_roots, heap_info); @@ -513,7 +797,7 @@ void HeapShared::copy_interned_strings() { auto copier = [&] (oop s, bool value_ignored) { assert(s != nullptr, "sanity"); assert(!ArchiveHeapWriter::is_string_too_large_to_archive(s), "large strings must have been filtered"); - bool success = archive_reachable_objects_from(1, _default_subgraph_info, s); + bool success = archive_reachable_objects_from(1, _dump_time_special_subgraph, s); assert(success, "must be"); // Prevent string deduplication from changing the value field to // something not in the archive. @@ -524,20 +808,35 @@ void HeapShared::copy_interned_strings() { delete_seen_objects_table(); } -void HeapShared::copy_special_objects() { - // Archive special objects that do not belong to any subgraphs +void HeapShared::copy_special_subgraph() { + copy_interned_strings(); + init_seen_objects_table(); - archive_java_mirrors(); - archive_strings(); - Universe::archive_exception_instances(); + { + archive_java_mirrors(); + archive_strings(); + Universe::archive_exception_instances(); + } delete_seen_objects_table(); } +void HeapShared::prepare_resolved_references() { + GrowableArray* klasses = ArchiveBuilder::current()->klasses(); + for (int i = 0; i < klasses->length(); i++) { + Klass* src_k = klasses->at(i); + if (src_k->is_instance_klass()) { + InstanceKlass* buffered_ik = ArchiveBuilder::current()->get_buffered_addr(InstanceKlass::cast(src_k)); + buffered_ik->constants()->prepare_resolved_references_for_archiving(); + } + } +} + void HeapShared::copy_objects() { assert(HeapShared::can_write(), "must be"); - copy_interned_strings(); - copy_special_objects(); + prepare_resolved_references(); + find_all_aot_initialized_classes(); + copy_special_subgraph(); archive_object_subgraphs(archive_subgraph_entry_fields, false /* is_full_module_graph */); @@ -549,6 +848,198 @@ void HeapShared::copy_objects() { } } +// Closure used by HeapShared::scan_for_aot_initialized_classes() to look for all objects +// that are reachable from a given root. +class HeapShared::AOTInitializedClassScanner : public BasicOopIterateClosure { + bool _made_progress; + + template void check(T *p) { + oop obj = HeapAccess<>::oop_load(p); + if (!java_lang_Class::is_instance(obj)) { + // Don't scan the mirrors, as we may see an orig_mirror while scanning + // the object graph, .... TODO more info + _made_progress |= HeapShared::scan_for_aot_initialized_classes(obj); + } + } + +public: + AOTInitializedClassScanner() : _made_progress(false) {} + void do_oop(narrowOop *p) { check(p); } + void do_oop( oop *p) { check(p); } + bool made_progress() { return _made_progress; } +}; + +// If has been initialized during the assembly phase, mark its +// has_aot_initialized_mirror bit. And then do the same for all supertypes of +// . +// +// Note: a super interface of may not have been initialized, if +// has not declared any default methods. +// +// Note: this function doesn not call InstanceKlass::initialize() -- we are inside +// a safepoint. +// +// Returns true if one or more classes have been newly marked. +static bool mark_for_aot_initialization(InstanceKlass* buffered_ik) { + assert(SafepointSynchronize::is_at_safepoint(), "sanity"); + assert(ArchiveBuilder::current()->is_in_buffer_space(buffered_ik), "sanity"); + + if (buffered_ik->has_aot_initialized_mirror()) { // already marked + return false; + } + + bool made_progress = false; + if (buffered_ik->is_initialized()) { + if (log_is_enabled(Info, cds, init)) { + ResourceMark rm; + log_info(cds, init)("Mark class for aot-init: %s", buffered_ik->external_name()); + } + + InstanceKlass* src_ik = ArchiveBuilder::current()->get_source_addr(buffered_ik); + + // If we get here with a "wild" user class, which may have + // uncontrolled code, exit with an error. Obviously + // filtering logic upstream needs to detect APP classes and not mark + // them for aot-init in the first place, but this will be the final + // firewall. + +#ifndef PRODUCT + // ArchiveHeapTestClass is used for a very small number of internal regression + // tests (non-product builds only). It may initialize some unexpected classes. + if (ArchiveHeapTestClass == nullptr) +#endif + { + if (!src_ik->in_javabase_module()) { + // Class/interface types in the boot loader may have been initialized as side effects + // of JVM bootstrap code, so they are fine. But we need to check all other classes. + if (buffered_ik->is_interface()) { + // This probably means a bug in AOTConstantPoolResolver.::is_indy_resolution_deterministic() + guarantee(!buffered_ik->interface_needs_clinit_execution_as_super(), + "should not have initialized an interface whose might have unpredictable side effects"); + } else { + // "normal" classes + guarantee(HeapShared::is_archivable_hidden_klass(buffered_ik), + "should not have initialized any non-interface, non-hidden classes outside of java.base"); + } + } + } + + buffered_ik->set_has_aot_initialized_mirror(); + if (AOTClassInitializer::is_runtime_setup_required(src_ik)) { + buffered_ik->set_is_runtime_setup_required(); + } + made_progress = true; + + InstanceKlass* super = buffered_ik->java_super(); + if (super != nullptr) { + mark_for_aot_initialization(super); + } + + Array* interfaces = buffered_ik->transitive_interfaces(); + for (int i = 0; i < interfaces->length(); i++) { + InstanceKlass* intf = interfaces->at(i); + mark_for_aot_initialization(intf); + if (!intf->is_initialized()) { + assert(!intf->interface_needs_clinit_execution_as_super(/*also_check_supers*/false), "sanity"); + assert(!intf->has_aot_initialized_mirror(), "must not be marked"); + } + } + } + + return made_progress; +} + +void HeapShared::find_all_aot_initialized_classes() { + if (!CDSConfig::is_dumping_aot_linked_classes()) { + return; + } + + init_seen_objects_table(); + find_all_aot_initialized_classes_helper(); + delete_seen_objects_table(); +} + +// Recursively find all class that should be aot-initialized: +// - the class has at least one instance that can be reachable from the special subgraph; or +// - the class is hard-coded in AOTClassInitializer::can_archive_initialized_mirror() +void HeapShared::find_all_aot_initialized_classes_helper() { + GrowableArray* klasses = ArchiveBuilder::current()->klasses(); + assert(klasses != nullptr, "sanity"); + + // First scan all resolved constant pools references. + for (int i = 0; i < klasses->length(); i++) { + Klass* src_k = klasses->at(i); + if (src_k->is_instance_klass()) { + InstanceKlass* src_ik = InstanceKlass::cast(src_k); + InstanceKlass* buffered_ik = ArchiveBuilder::current()->get_buffered_addr(src_ik); + objArrayOop rr = get_archived_resolved_references(src_ik); + if (rr != nullptr) { + objArrayOop scratch_rr = scratch_resolved_references(src_ik->constants()); + for (int i = 0; i < scratch_rr->length(); i++) { + scan_for_aot_initialized_classes(scratch_rr->obj_at(i)); + } + } + + // If a class is hard-coded to be aot-initialize, mark it as such. + if (AOTClassInitializer::can_archive_initialized_mirror(src_ik)) { + mark_for_aot_initialization(buffered_ik); + } + } + } + + // These objects also belong to the special subgraph + scan_for_aot_initialized_classes(Universe::null_ptr_exception_instance()); + scan_for_aot_initialized_classes(Universe::arithmetic_exception_instance()); + scan_for_aot_initialized_classes(Universe::internal_error_instance()); + scan_for_aot_initialized_classes(Universe::array_index_out_of_bounds_exception_instance()); + scan_for_aot_initialized_classes(Universe::array_store_exception_instance()); + scan_for_aot_initialized_classes(Universe::class_cast_exception_instance()); + + bool made_progress; + do { + // In each pass, we copy the scratch mirrors of the classes that were marked + // as aot-init in the previous pass. We then scan these mirrors, which may + // mark more classes. Keep iterating until no more progress can be made. + made_progress = false; + for (int i = 0; i < klasses->length(); i++) { + Klass* orig_k = klasses->at(i); + if (orig_k->is_instance_klass()) { + InstanceKlass* orig_ik = InstanceKlass::cast(orig_k); + if (ArchiveBuilder::current()->get_buffered_addr(orig_ik)->has_aot_initialized_mirror()) { + oop orig_mirror = orig_ik->java_mirror(); + oop scratch_mirror = scratch_java_mirror(orig_k); + if (!has_been_seen_during_subgraph_recording(scratch_mirror)) { + // Scan scratch_mirror instead of orig_mirror (which has fields like ClassLoader that + // are not archived). + copy_aot_initialized_mirror(orig_k, orig_mirror, scratch_mirror); + made_progress |= scan_for_aot_initialized_classes(scratch_mirror); + } + } + } + } + } while (made_progress); +} + +bool HeapShared::scan_for_aot_initialized_classes(oop obj) { + if (obj == nullptr || has_been_seen_during_subgraph_recording(obj)) { + return false; + } + set_has_been_seen_during_subgraph_recording(obj); + + bool made_progress = false; + Klass* k = obj->klass(); + if (k->is_instance_klass()) { + InstanceKlass* orig_ik = InstanceKlass::cast(k); + InstanceKlass* buffered_ik = ArchiveBuilder::current()->get_buffered_addr(orig_ik); + made_progress = mark_for_aot_initialization(buffered_ik); + } + + AOTInitializedClassScanner scanner; + obj->oop_iterate(&scanner); + made_progress |= scanner.made_progress(); + return made_progress; +} + // // Subgraph archiving support // @@ -607,8 +1098,14 @@ void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k) { } if (buffered_k->is_instance_klass()) { - assert(InstanceKlass::cast(buffered_k)->is_shared_boot_class(), - "must be boot class"); + if (CDSConfig::is_dumping_invokedynamic()) { + assert(InstanceKlass::cast(buffered_k)->is_shared_boot_class() || + HeapShared::is_lambda_proxy_klass(InstanceKlass::cast(buffered_k)), + "we can archive only instances of boot classes or lambda proxy classes"); + } else { + assert(InstanceKlass::cast(buffered_k)->is_shared_boot_class(), + "must be boot class"); + } // vmClasses::xxx_klass() are not updated, need to check // the original Klass* if (orig_k == vmClasses::String_klass() || @@ -617,6 +1114,10 @@ void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k) { // to the sub-graph object class list. return; } + if (buffered_k->has_aot_initialized_mirror()) { + // No need to add to the runtime-init list. + return; + } check_allowed_klass(InstanceKlass::cast(orig_k)); } else if (buffered_k->is_objArray_klass()) { Klass* abk = ObjArrayKlass::cast(buffered_k)->bottom_klass(); @@ -653,19 +1154,30 @@ void KlassSubGraphInfo::check_allowed_klass(InstanceKlass* ik) { return; } + const char* lambda_msg = ""; + if (CDSConfig::is_dumping_invokedynamic()) { + lambda_msg = ", or a lambda proxy class"; + if (HeapShared::is_lambda_proxy_klass(ik) && + (ik->class_loader() == nullptr || + ik->class_loader() == SystemDictionary::java_platform_loader() || + ik->class_loader() == SystemDictionary::java_system_loader())) { + return; + } + } + #ifndef PRODUCT - if (!ik->module()->is_named() && ik->package() == nullptr) { + if (!ik->module()->is_named() && ik->package() == nullptr && ArchiveHeapTestClass != nullptr) { // This class is loaded by ArchiveHeapTestClass return; } - const char* extra_msg = ", or in an unnamed package of an unnamed module"; + const char* testcls_msg = ", or a test class in an unnamed package of an unnamed module"; #else - const char* extra_msg = ""; + const char* testcls_msg = ""; #endif ResourceMark rm; - log_error(cds, heap)("Class %s not allowed in archive heap. Must be in java.base%s", - ik->external_name(), extra_msg); + log_error(cds, heap)("Class %s not allowed in archive heap. Must be in java.base%s%s", + ik->external_name(), lambda_msg, testcls_msg); MetaspaceShared::unrecoverable_writing_error(); } @@ -727,13 +1239,18 @@ void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) { int num_subgraphs_klasses = subgraph_object_klasses->length(); _subgraph_object_klasses = ArchiveBuilder::new_ro_array(num_subgraphs_klasses); + bool is_special = (_k == ArchiveBuilder::get_buffered_klass(vmClasses::Object_klass())); for (int i = 0; i < num_subgraphs_klasses; i++) { Klass* subgraph_k = subgraph_object_klasses->at(i); if (log_is_enabled(Info, cds, heap)) { ResourceMark rm; + const char* owner_name = is_special ? "" : _k->external_name(); + if (subgraph_k->is_instance_klass()) { + InstanceKlass* src_ik = InstanceKlass::cast(ArchiveBuilder::current()->get_source_addr(subgraph_k)); + } log_info(cds, heap)( "Archived object klass %s (%2d) => %s", - _k->external_name(), i, subgraph_k->external_name()); + owner_name, i, subgraph_k->external_name()); } _subgraph_object_klasses->at_put(i, subgraph_k); ArchivePtrMarker::mark_pointer(_subgraph_object_klasses->adr_at(i)); @@ -745,16 +1262,14 @@ void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) { ArchivePtrMarker::mark_pointer(&_subgraph_object_klasses); } -struct CopyKlassSubGraphInfoToArchive : StackObj { +class HeapShared::CopyKlassSubGraphInfoToArchive : StackObj { CompactHashtableWriter* _writer; +public: CopyKlassSubGraphInfoToArchive(CompactHashtableWriter* writer) : _writer(writer) {} bool do_entry(Klass* klass, KlassSubGraphInfo& info) { if (info.subgraph_object_klasses() != nullptr || info.subgraph_entry_fields() != nullptr) { - ArchivedKlassSubGraphInfoRecord* record = - (ArchivedKlassSubGraphInfoRecord*)ArchiveBuilder::ro_region_alloc(sizeof(ArchivedKlassSubGraphInfoRecord)); - record->init(&info); - + ArchivedKlassSubGraphInfoRecord* record = HeapShared::archive_subgraph_info(&info); Klass* buffered_k = ArchiveBuilder::get_buffered_klass(klass); unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary((address)buffered_k); u4 delta = ArchiveBuilder::current()->any_to_offset_u4(record); @@ -764,6 +1279,16 @@ struct CopyKlassSubGraphInfoToArchive : StackObj { } }; +ArchivedKlassSubGraphInfoRecord* HeapShared::archive_subgraph_info(KlassSubGraphInfo* info) { + ArchivedKlassSubGraphInfoRecord* record = + (ArchivedKlassSubGraphInfoRecord*)ArchiveBuilder::ro_region_alloc(sizeof(ArchivedKlassSubGraphInfoRecord)); + record->init(info); + if (info == _dump_time_special_subgraph) { + _run_time_special_subgraph = record; + } + return record; +} + // Build the records of archived subgraph infos, which include: // - Entry points to all subgraphs from the containing class mirror. The entry // points are static fields in the mirror. For each entry point, the field @@ -820,6 +1345,7 @@ void HeapShared::serialize_tables(SerializeClosure* soc) { #endif _run_time_subgraph_info_table.serialize_header(soc); + soc->do_ptr(&_run_time_special_subgraph); } static void verify_the_heap(Klass* k, const char* which) { @@ -887,6 +1413,65 @@ void HeapShared::resolve_classes_for_subgraph_of(JavaThread* current, Klass* k) } } +void HeapShared::initialize_java_lang_invoke(TRAPS) { + if (CDSConfig::is_loading_invokedynamic() || CDSConfig::is_dumping_invokedynamic()) { + resolve_or_init("java/lang/invoke/Invokers$Holder", true, CHECK); + resolve_or_init("java/lang/invoke/MethodHandle", true, CHECK); + resolve_or_init("java/lang/invoke/MethodHandleNatives", true, CHECK); + resolve_or_init("java/lang/invoke/DirectMethodHandle$Holder", true, CHECK); + resolve_or_init("java/lang/invoke/DelegatingMethodHandle$Holder", true, CHECK); + resolve_or_init("java/lang/invoke/LambdaForm$Holder", true, CHECK); + resolve_or_init("java/lang/invoke/BoundMethodHandle$Species_L", true, CHECK); + } +} + +// Initialize the InstanceKlasses of objects that are reachable from the following roots: +// - interned strings +// - Klass::java_mirror() -- including aot-initialized mirrors such as those of Enum klasses. +// - ConstantPool::resolved_references() +// - Universe::_exception_instance() +// +// For example, if this enum class is initialized at AOT cache assembly time: +// +// enum Fruit { +// APPLE, ORANGE, BANANA; +// static final Set HAVE_SEEDS = new HashSet<>(Arrays.asList(APPLE, ORANGE)); +// } +// +// the aot-initialized mirror of Fruit has a static field that references HashSet, which +// should be initialized before any Java code can access the Fruit class. Note that +// HashSet itself doesn't necessary need to be an aot-initialized class. +void HeapShared::init_classes_for_special_subgraph(Handle class_loader, TRAPS) { + if (!ArchiveHeapLoader::is_in_use()) { + return; + } + + assert( _run_time_special_subgraph != nullptr, "must be"); + Array* klasses = _run_time_special_subgraph->subgraph_object_klasses(); + if (klasses != nullptr) { + for (int pass = 0; pass < 2; pass ++) { + for (int i = 0; i < klasses->length(); i++) { + Klass* k = klasses->at(i); + if (k->class_loader_data() == nullptr) { + // This class is not yet loaded. We will initialize it in a later phase. + // For example, we have loaded only AOTLinkedClassCategory::BOOT1 classes + // but k is part of AOTLinkedClassCategory::BOOT2. + continue; + } + if (k->class_loader() == class_loader()) { + if (pass == 0) { + if (k->is_instance_klass()) { + InstanceKlass::cast(k)->link_class(CHECK); + } + } else { + resolve_or_init(k, /*do_init*/true, CHECK); + } + } + } + } + } +} + void HeapShared::initialize_from_archived_subgraph(JavaThread* current, Klass* k) { JavaThread* THREAD = current; if (!ArchiveHeapLoader::is_in_use()) { @@ -990,6 +1575,19 @@ HeapShared::resolve_or_init_classes_for_subgraph_of(Klass* k, bool do_init, TRAP return record; } +void HeapShared::resolve_or_init(const char* klass_name, bool do_init, TRAPS) { + TempNewSymbol klass_name_sym = SymbolTable::new_symbol(klass_name); + InstanceKlass* k = SystemDictionaryShared::find_builtin_class(klass_name_sym); + if (k == nullptr) { + return; + } + assert(k->is_shared_boot_class(), "sanity"); + resolve_or_init(k, false, CHECK); + if (do_init) { + resolve_or_init(k, true, CHECK); + } +} + void HeapShared::resolve_or_init(Klass* k, bool do_init, TRAPS) { if (!do_init) { if (k->class_loader_data() == nullptr) { @@ -1022,7 +1620,11 @@ void HeapShared::init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphI int field_offset = entry_field_records->at(i); int root_index = entry_field_records->at(i+1); oop v = get_root(root_index, /*clear=*/true); - m->obj_field_put(field_offset, v); + if (k->has_aot_initialized_mirror()) { + assert(v == m->obj_field(field_offset), "must be aot-initialized"); + } else { + m->obj_field_put(field_offset, v); + } log_debug(cds, heap)(" " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v)); } @@ -1030,8 +1632,9 @@ void HeapShared::init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphI // mirror after this point. if (log_is_enabled(Info, cds, heap)) { ResourceMark rm; - log_info(cds, heap)("initialize_from_archived_subgraph %s " PTR_FORMAT "%s", - k->external_name(), p2i(k), JvmtiExport::is_early_phase() ? " (early)" : ""); + log_info(cds, heap)("initialize_from_archived_subgraph %s " PTR_FORMAT "%s%s", + k->external_name(), p2i(k), JvmtiExport::is_early_phase() ? " (early)" : "", + k->has_aot_initialized_mirror() ? " (aot-inited)" : ""); } } @@ -1137,6 +1740,20 @@ HeapShared::CachedOopInfo HeapShared::make_cached_oop_info(oop obj) { return CachedOopInfo(referrer, points_to_oops_checker.result()); } +void HeapShared::init_box_classes(TRAPS) { + if (ArchiveHeapLoader::is_in_use()) { + vmClasses::Boolean_klass()->initialize(CHECK); + vmClasses::Character_klass()->initialize(CHECK); + vmClasses::Float_klass()->initialize(CHECK); + vmClasses::Double_klass()->initialize(CHECK); + vmClasses::Byte_klass()->initialize(CHECK); + vmClasses::Short_klass()->initialize(CHECK); + vmClasses::Integer_klass()->initialize(CHECK); + vmClasses::Long_klass()->initialize(CHECK); + vmClasses::Void_klass()->initialize(CHECK); + } +} + // (1) If orig_obj has not been archived yet, archive it. // (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called), // trace all objects that are reachable from it, and make sure these objects are archived. @@ -1151,25 +1768,56 @@ bool HeapShared::archive_reachable_objects_from(int level, // If you get an error here, you probably made a change in the JDK library that has added // these objects that are referenced (directly or indirectly) by static fields. ResourceMark rm; - log_error(cds, heap)("Cannot archive object of class %s", orig_obj->klass()->external_name()); - if (log_is_enabled(Trace, cds, heap)) { - WalkOopAndArchiveClosure* walker = WalkOopAndArchiveClosure::current(); - if (walker != nullptr) { - LogStream ls(Log(cds, heap)::trace()); - CDSHeapVerifier::trace_to_root(&ls, walker->referencing_obj()); - } - } + log_error(cds, heap)("Cannot archive object " PTR_FORMAT " of class %s", p2i(orig_obj), orig_obj->klass()->external_name()); + debug_trace(); MetaspaceShared::unrecoverable_writing_error(); } - // java.lang.Class instances cannot be included in an archived object sub-graph. We only support - // them as Klass::_archived_mirror because they need to be specially restored at run time. - // - // If you get an error here, you probably made a change in the JDK library that has added a Class - // object that is referenced (directly or indirectly) by static fields. - if (java_lang_Class::is_instance(orig_obj) && subgraph_info != _default_subgraph_info) { - log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level); - MetaspaceShared::unrecoverable_writing_error(); + if (log_is_enabled(Debug, cds, heap) && java_lang_Class::is_instance(orig_obj)) { + ResourceMark rm; + LogTarget(Debug, cds, heap) log; + LogStream out(log); + out.print("Found java mirror " PTR_FORMAT " ", p2i(orig_obj)); + Klass* k = java_lang_Class::as_Klass(orig_obj); + if (k != nullptr) { + out.print("%s", k->external_name()); + } else { + out.print("primitive"); + } + out.print_cr("; scratch mirror = " PTR_FORMAT, + p2i(scratch_java_mirror(orig_obj))); + } + + if (CDSConfig::is_initing_classes_at_dump_time()) { + if (java_lang_Class::is_instance(orig_obj)) { + orig_obj = scratch_java_mirror(orig_obj); + assert(orig_obj != nullptr, "must be archived"); + } + } else if (java_lang_Class::is_instance(orig_obj) && subgraph_info != _dump_time_special_subgraph) { + // Without CDSConfig::is_initing_classes_at_dump_time(), we only allow archived objects to + // point to the mirrors of (1) j.l.Object, (2) primitive classes, and (3) box classes. These are initialized + // very early by HeapShared::init_box_classes(). + if (orig_obj == vmClasses::Object_klass()->java_mirror() + || java_lang_Class::is_primitive(orig_obj) + || orig_obj == vmClasses::Boolean_klass()->java_mirror() + || orig_obj == vmClasses::Character_klass()->java_mirror() + || orig_obj == vmClasses::Float_klass()->java_mirror() + || orig_obj == vmClasses::Double_klass()->java_mirror() + || orig_obj == vmClasses::Byte_klass()->java_mirror() + || orig_obj == vmClasses::Short_klass()->java_mirror() + || orig_obj == vmClasses::Integer_klass()->java_mirror() + || orig_obj == vmClasses::Long_klass()->java_mirror() + || orig_obj == vmClasses::Void_klass()->java_mirror()) { + orig_obj = scratch_java_mirror(orig_obj); + assert(orig_obj != nullptr, "must be archived"); + } else { + // If you get an error here, you probably made a change in the JDK library that has added a Class + // object that is referenced (directly or indirectly) by an ArchivableStaticFieldInfo + // defined at the top of this file. + log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level); + debug_trace(); + MetaspaceShared::unrecoverable_writing_error(); + } } if (has_been_seen_during_subgraph_recording(orig_obj)) { @@ -1209,9 +1857,15 @@ bool HeapShared::archive_reachable_objects_from(int level, WalkOopAndArchiveClosure walker(level, record_klasses_only, subgraph_info, orig_obj); orig_obj->oop_iterate(&walker); - if (CDSEnumKlass::is_enum_obj(orig_obj)) { - CDSEnumKlass::handle_enum_obj(level + 1, subgraph_info, orig_obj); + if (CDSConfig::is_initing_classes_at_dump_time()) { + // The enum klasses are archived with aot-initialized mirror. + // See AOTClassInitializer::can_archive_initialized_mirror(). + } else { + if (CDSEnumKlass::is_enum_obj(orig_obj)) { + CDSEnumKlass::handle_enum_obj(level + 1, subgraph_info, orig_obj); + } } + return true; } @@ -1329,6 +1983,10 @@ void HeapShared::verify_subgraph_from(oop orig_obj) { void HeapShared::verify_reachable_objects_from(oop obj) { _num_total_verifications ++; + if (java_lang_Class::is_instance(obj)) { + obj = scratch_java_mirror(obj); + assert(obj != nullptr, "must be"); + } if (!has_been_seen_during_subgraph_recording(obj)) { set_has_been_seen_during_subgraph_recording(obj); assert(has_been_archived(obj), "must be"); @@ -1338,35 +1996,35 @@ void HeapShared::verify_reachable_objects_from(oop obj) { } #endif -// The "default subgraph" contains special objects (see heapShared.hpp) that -// can be accessed before we load any Java classes (including java/lang/Class). -// Make sure that these are only instances of the very few specific types -// that we can handle. -void HeapShared::check_default_subgraph_classes() { - GrowableArray* klasses = _default_subgraph_info->subgraph_object_klasses(); - int num = klasses->length(); - for (int i = 0; i < num; i++) { - Klass* subgraph_k = klasses->at(i); - if (log_is_enabled(Info, cds, heap)) { - ResourceMark rm; - log_info(cds, heap)( - "Archived object klass (default subgraph %d) => %s", - i, subgraph_k->external_name()); +void HeapShared::check_special_subgraph_classes() { + if (CDSConfig::is_initing_classes_at_dump_time()) { + // We can have aot-initialized classes (such as Enums) that can reference objects + // of arbitrary types. Currently, we trust the JEP 483 implementation to only + // aot-initialize classes that are "safe". + // + // TODO: we need an automatic tool that checks the safety of aot-initialized + // classes (when we extend the set of aot-initialized classes beyond JEP 483) + return; + } else { + // In this case, the special subgraph should contain a few specific types + GrowableArray* klasses = _dump_time_special_subgraph->subgraph_object_klasses(); + int num = klasses->length(); + for (int i = 0; i < num; i++) { + Klass* subgraph_k = klasses->at(i); + Symbol* name = ArchiveBuilder::current()->get_source_addr(subgraph_k->name()); + if (subgraph_k->is_instance_klass() && + name != vmSymbols::java_lang_Class() && + name != vmSymbols::java_lang_String() && + name != vmSymbols::java_lang_ArithmeticException() && + name != vmSymbols::java_lang_ArrayIndexOutOfBoundsException() && + name != vmSymbols::java_lang_ArrayStoreException() && + name != vmSymbols::java_lang_ClassCastException() && + name != vmSymbols::java_lang_InternalError() && + name != vmSymbols::java_lang_NullPointerException()) { + ResourceMark rm; + fatal("special subgraph cannot have objects of type %s", subgraph_k->external_name()); + } } - - Symbol* name = ArchiveBuilder::current()->get_source_addr(subgraph_k->name()); - guarantee(name == vmSymbols::java_lang_Class() || - name == vmSymbols::java_lang_String() || - name == vmSymbols::java_lang_ArithmeticException() || - name == vmSymbols::java_lang_NullPointerException() || - name == vmSymbols::java_lang_InternalError() || - name == vmSymbols::java_lang_ArrayIndexOutOfBoundsException() || - name == vmSymbols::java_lang_ArrayStoreException() || - name == vmSymbols::java_lang_ClassCastException() || - name == vmSymbols::object_array_signature() || - name == vmSymbols::byte_array_signature() || - name == vmSymbols::char_array_signature(), - "default subgraph can have only these objects"); } } @@ -1572,8 +2230,8 @@ bool HeapShared::is_a_test_class_in_unnamed_module(Klass* ik) { return false; } - // See KlassSubGraphInfo::check_allowed_klass() - only two types of - // classes are allowed: + // See KlassSubGraphInfo::check_allowed_klass() - we only allow test classes + // to be: // (A) java.base classes (which must not be in the unnamed module) // (B) test classes which must be in the unnamed package of the unnamed module. // So if we see a '/' character in the class name, it must be in (A); @@ -1589,6 +2247,25 @@ bool HeapShared::is_a_test_class_in_unnamed_module(Klass* ik) { return false; } + +void HeapShared::initialize_test_class_from_archive(JavaThread* current) { + Klass* k = _test_class; + if (k != nullptr && ArchiveHeapLoader::is_in_use()) { + JavaThread* THREAD = current; + ExceptionMark em(THREAD); + const ArchivedKlassSubGraphInfoRecord* record = + resolve_or_init_classes_for_subgraph_of(k, /*do_init=*/false, THREAD); + + // The _test_class is in the unnamed module, so it can't call CDS.initializeFromArchive() + // from its method. So we set up its "archivedObjects" field first, before + // calling its . This is not strictly clean, but it's a convenient way to write unit + // test cases (see test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java). + if (record != nullptr) { + init_archived_fields_for(k, record); + } + resolve_or_init_classes_for_subgraph_of(k, /*do_init=*/true, THREAD); + } +} #endif void HeapShared::init_for_dumping(TRAPS) { @@ -1664,6 +2341,15 @@ void HeapShared::add_to_dumped_interned_strings(oop string) { } } +void HeapShared::debug_trace() { + ResourceMark rm; + WalkOopAndArchiveClosure* walker = WalkOopAndArchiveClosure::current(); + if (walker != nullptr) { + LogStream ls(Log(cds, heap)::error()); + CDSHeapVerifier::trace_to_root(&ls, walker->referencing_obj()); + } +} + #ifndef PRODUCT // At dump-time, find the location of all the non-null oop pointers in an archived heap // region. This way we can quickly relocate all the pointers without using @@ -1750,7 +2436,7 @@ void HeapShared::print_stats() { bool HeapShared::is_archived_boot_layer_available(JavaThread* current) { TempNewSymbol klass_name = SymbolTable::new_symbol(ARCHIVED_BOOT_LAYER_CLASS); - InstanceKlass* k = SystemDictionary::find_instance_klass(current, klass_name, Handle(), Handle()); + InstanceKlass* k = SystemDictionary::find_instance_klass(current, klass_name, Handle()); if (k == nullptr) { return false; } else { diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index 317b791f5d3..618adeb308f 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -166,10 +166,16 @@ class HeapShared: AllStatic { static bool is_subgraph_root_class(InstanceKlass* ik); // Scratch objects for archiving Klass::java_mirror() - static oop scratch_java_mirror(BasicType t) NOT_CDS_JAVA_HEAP_RETURN_(nullptr); - static oop scratch_java_mirror(Klass* k) NOT_CDS_JAVA_HEAP_RETURN_(nullptr); + static oop scratch_java_mirror(BasicType t) NOT_CDS_JAVA_HEAP_RETURN_(nullptr); + static oop scratch_java_mirror(Klass* k) NOT_CDS_JAVA_HEAP_RETURN_(nullptr); + static oop scratch_java_mirror(oop java_mirror) NOT_CDS_JAVA_HEAP_RETURN_(nullptr); static bool is_archived_boot_layer_available(JavaThread* current) NOT_CDS_JAVA_HEAP_RETURN_(false); + // Look for all hidden classes that are referenced by archived objects. + static void start_finding_required_hidden_classes() NOT_CDS_JAVA_HEAP_RETURN; + static void find_required_hidden_classes_in_object(oop o) NOT_CDS_JAVA_HEAP_RETURN; + static void end_finding_required_hidden_classes() NOT_CDS_JAVA_HEAP_RETURN; + private: #if INCLUDE_CDS_JAVA_HEAP static bool _disable_writing; @@ -184,12 +190,15 @@ class HeapShared: AllStatic { static void count_allocation(size_t size); static void print_stats(); + static void debug_trace(); public: static unsigned oop_hash(oop const& p); static unsigned string_oop_hash(oop const& string) { return java_lang_String::hash_code(string); } + class CopyKlassSubGraphInfoToArchive; + class CachedOopInfo { // Used by CDSHeapVerifier. oop _orig_referrer; @@ -251,7 +260,11 @@ class HeapShared: AllStatic { static DumpTimeKlassSubGraphInfoTable* _dump_time_subgraph_info_table; static RunTimeKlassSubGraphInfoTable _run_time_subgraph_info_table; + class FindRequiredHiddenClassesOopClosure; + static void find_required_hidden_classes_helper(ArchivableStaticFieldInfo fields[]); + static CachedOopInfo make_cached_oop_info(oop obj); + static ArchivedKlassSubGraphInfoRecord* archive_subgraph_info(KlassSubGraphInfo* info); static void archive_object_subgraphs(ArchivableStaticFieldInfo fields[], bool is_full_module_graph); @@ -265,7 +278,7 @@ class HeapShared: AllStatic { InstanceKlass* k, int field_offset) PRODUCT_RETURN; static void verify_reachable_objects_from(oop obj) PRODUCT_RETURN; static void verify_subgraph_from(oop orig_obj) PRODUCT_RETURN; - static void check_default_subgraph_classes(); + static void check_special_subgraph_classes(); static KlassSubGraphInfo* init_subgraph_info(Klass *k, bool is_full_module_graph); static KlassSubGraphInfo* get_subgraph_info(Klass *k); @@ -287,12 +300,14 @@ class HeapShared: AllStatic { static SeenObjectsTable *_seen_objects_table; - // The "default subgraph" is the root of all archived objects that do not belong to any - // of the classes defined in the _archive_subgraph_entry_fields[] arrays: + // The "special subgraph" contains all the archived objects that are reachable + // from the following roots: // - interned strings - // - Klass::java_mirror() + // - Klass::java_mirror() -- including aot-initialized mirrors such as those of Enum klasses. // - ConstantPool::resolved_references() - static KlassSubGraphInfo* _default_subgraph_info; + // - Universe::_exception_instance() + static KlassSubGraphInfo* _dump_time_special_subgraph; // for collecting info during dump time + static ArchivedKlassSubGraphInfoRecord* _run_time_special_subgraph; // for initializing classes during run time. static GrowableArrayCHeap* _pending_roots; static GrowableArrayCHeap* _root_segments; @@ -330,7 +345,7 @@ class HeapShared: AllStatic { static bool has_been_seen_during_subgraph_recording(oop obj); static void set_has_been_seen_during_subgraph_recording(oop obj); static bool archive_object(oop obj); - + static void copy_aot_initialized_mirror(Klass* orig_k, oop orig_mirror, oop m); static void copy_interned_strings(); static void resolve_classes_for_subgraphs(JavaThread* current, ArchivableStaticFieldInfo fields[]); @@ -338,6 +353,7 @@ class HeapShared: AllStatic { static void clear_archived_roots_of(Klass* k); static const ArchivedKlassSubGraphInfoRecord* resolve_or_init_classes_for_subgraph_of(Klass* k, bool do_init, TRAPS); + static void resolve_or_init(const char* klass_name, bool do_init, TRAPS); static void resolve_or_init(Klass* k, bool do_init, TRAPS); static void init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record); @@ -352,8 +368,16 @@ class HeapShared: AllStatic { static void fill_failed_loaded_region(); static void mark_native_pointers(oop orig_obj); static bool has_been_archived(oop orig_obj); + static void prepare_resolved_references(); static void archive_java_mirrors(); static void archive_strings(); + static void copy_special_subgraph(); + + class AOTInitializedClassScanner; + static void find_all_aot_initialized_classes(); + static void find_all_aot_initialized_classes_helper(); + static bool scan_for_aot_initialized_classes(oop obj); + public: static void reset_archived_object_states(TRAPS); static void create_archived_object_cache() { @@ -371,7 +395,6 @@ class HeapShared: AllStatic { static int archive_exception_instance(oop exception); static void archive_objects(ArchiveHeapInfo* heap_info); static void copy_objects(); - static void copy_special_objects(); static bool archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, @@ -420,6 +443,7 @@ class HeapShared: AllStatic { static objArrayOop scratch_resolved_references(ConstantPool* src); static void add_scratch_resolved_references(ConstantPool* src, objArrayOop dest) NOT_CDS_JAVA_HEAP_RETURN; static void init_scratch_objects(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; + static void init_box_classes(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; static bool is_heap_region(int idx) { CDS_JAVA_HEAP_ONLY(return (idx == MetaspaceShared::hp);) NOT_CDS_JAVA_HEAP_RETURN_(false); @@ -436,7 +460,16 @@ class HeapShared: AllStatic { #ifndef PRODUCT static bool is_a_test_class_in_unnamed_module(Klass* ik) NOT_CDS_JAVA_HEAP_RETURN_(false); + static void initialize_test_class_from_archive(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; #endif + + static void initialize_java_lang_invoke(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; + static void init_classes_for_special_subgraph(Handle loader, TRAPS) NOT_CDS_JAVA_HEAP_RETURN; + + static bool is_lambda_form_klass(InstanceKlass* ik) NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_lambda_proxy_klass(InstanceKlass* ik) NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_string_concat_klass(InstanceKlass* ik) NOT_CDS_JAVA_HEAP_RETURN_(false); + static bool is_archivable_hidden_klass(InstanceKlass* ik) NOT_CDS_JAVA_HEAP_RETURN_(false); }; #if INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index 88b1f9277ff..5455a5e66f2 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -27,8 +27,8 @@ #include "cds/lambdaFormInvokers.hpp" #include "cds/metaspaceShared.hpp" #include "cds/regeneratedClasses.hpp" -#include "classfile/classLoadInfo.hpp" #include "classfile/classFileStream.hpp" +#include "classfile/classLoadInfo.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/klassFactory.hpp" #include "classfile/symbolTable.hpp" @@ -96,6 +96,21 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) { return; } + if (CDSConfig::is_dumping_static_archive() && CDSConfig::is_dumping_invokedynamic()) { + // Work around JDK-8310831, as some methods in lambda form holder classes may not get generated. + log_info(cds)("Archived MethodHandles may refer to lambda form holder classes. Cannot regenerate."); + return; + } + + if (CDSConfig::is_dumping_dynamic_archive() && CDSConfig::is_dumping_aot_linked_classes() && + CDSConfig::is_using_aot_linked_classes()) { + // The base archive may have some pre-resolved CP entries that point to the lambda form holder + // classes in the base archive. If we generate new versions of these classes, those CP entries + // will be pointing to invalid classes. + log_info(cds)("Base archive already has aot-linked lambda form holder classes. Cannot regenerate."); + return; + } + ResourceMark rm(THREAD); Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS(); @@ -166,7 +181,7 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) { // make a copy of class bytes so GC will not affect us. char *buf = NEW_RESOURCE_ARRAY(char, len); memcpy(buf, (char*)h_bytes->byte_at_addr(0), len); - ClassFileStream st((u1*)buf, len, nullptr, ClassFileStream::verify); + ClassFileStream st((u1*)buf, len, nullptr); regenerate_class(class_name, st, CHECK); } } diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 3cb1374efb1..a8c10e38577 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -23,16 +23,17 @@ */ #include "precompiled.hpp" +#include "cds/aotClassLinker.hpp" +#include "cds/aotConstantPoolResolver.hpp" +#include "cds/aotLinkedClassBulkLoader.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveHeapLoader.hpp" #include "cds/archiveHeapWriter.hpp" #include "cds/cds_globals.hpp" #include "cds/cdsConfig.hpp" #include "cds/cdsProtectionDomain.hpp" -#include "cds/cds_globals.hpp" #include "cds/classListParser.hpp" #include "cds/classListWriter.hpp" -#include "cds/classPrelinker.hpp" #include "cds/cppVtables.hpp" #include "cds/dumpAllocStats.hpp" #include "cds/dynamicArchive.hpp" @@ -98,6 +99,7 @@ bool MetaspaceShared::_remapped_readwrite = false; void* MetaspaceShared::_shared_metaspace_static_top = nullptr; intx MetaspaceShared::_relocation_delta; char* MetaspaceShared::_requested_base_address; +Array* MetaspaceShared::_archived_method_handle_intrinsics = nullptr; bool MetaspaceShared::_use_optimized_module_handling = true; // The CDS archive is divided into the following regions: @@ -308,8 +310,12 @@ void MetaspaceShared::post_initialize(TRAPS) { } } +// Extra java.lang.Strings to be added to the archive static GrowableArrayCHeap* _extra_interned_strings = nullptr; +// Extra Symbols to be added to the archive static GrowableArrayCHeap* _extra_symbols = nullptr; +// Methods managed by SystemDictionary::find_method_handle_intrinsic() to be added to the archive +static GrowableArray* _pending_method_handle_intrinsics = NULL; void MetaspaceShared::read_extra_data(JavaThread* current, const char* filename) { _extra_interned_strings = new GrowableArrayCHeap(10000); @@ -360,6 +366,30 @@ void MetaspaceShared::read_extra_data(JavaThread* current, const char* filename) } } +void MetaspaceShared::make_method_handle_intrinsics_shareable() { + for (int i = 0; i < _pending_method_handle_intrinsics->length(); i++) { + Method* m = ArchiveBuilder::current()->get_buffered_addr(_pending_method_handle_intrinsics->at(i)); + m->remove_unshareable_info(); + // Each method has its own constant pool (which is distinct from m->method_holder()->constants()); + m->constants()->remove_unshareable_info(); + } +} + +void MetaspaceShared::write_method_handle_intrinsics() { + int len = _pending_method_handle_intrinsics->length(); + _archived_method_handle_intrinsics = ArchiveBuilder::new_ro_array(len); + int word_size = _archived_method_handle_intrinsics->size(); + for (int i = 0; i < len; i++) { + Method* m = _pending_method_handle_intrinsics->at(i); + ArchiveBuilder::current()->write_pointer_in_buffer(_archived_method_handle_intrinsics->adr_at(i), m); + word_size += m->size() + m->constMethod()->size() + m->constants()->size(); + if (m->constants()->cache() != nullptr) { + word_size += m->constants()->cache()->size(); + } + } + log_info(cds)("Archived %d method handle intrinsics (%d bytes)", len, word_size * BytesPerWord); +} + // About "serialize" -- // // This is (probably a badly named) way to read/write a data stream of pointers and @@ -431,7 +461,7 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { StringTable::serialize_shared_table_header(soc); HeapShared::serialize_tables(soc); SystemDictionaryShared::serialize_dictionary_headers(soc); - + AOTLinkedClassBulkLoader::serialize(soc, true); InstanceMirrorKlass::serialize_offsets(soc); // Dump/restore well known classes (pointers) @@ -439,6 +469,7 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { soc->do_tag(--tag); CDS_JAVA_HEAP_ONLY(ClassLoaderDataShared::serialize(soc);) + soc->do_ptr((void**)&_archived_method_handle_intrinsics); LambdaFormInvokers::serialize(soc); soc->do_tag(666); @@ -526,6 +557,10 @@ class StaticArchiveBuilder : public ArchiveBuilder { it->push(_extra_symbols->adr_at(i)); } } + + for (int i = 0; i < _pending_method_handle_intrinsics->length(); i++) { + it->push(_pending_method_handle_intrinsics->adr_at(i)); + } } }; @@ -548,6 +583,8 @@ char* VM_PopulateDumpSharedSpace::dump_read_only_tables() { ArchiveBuilder::OtherROAllocMark mark; SystemDictionaryShared::write_to_archive(); + AOTClassLinker::write_to_archive(); + MetaspaceShared::write_method_handle_intrinsics(); // Write lambform lines into archive LambdaFormInvokers::dump_static_archive_invokers(); @@ -566,13 +603,20 @@ void VM_PopulateDumpSharedSpace::doit() { DEBUG_ONLY(SystemDictionaryShared::NoClassLoadingMark nclm); + _pending_method_handle_intrinsics = new (mtClassShared) GrowableArray(256, mtClassShared); + if (CDSConfig::is_dumping_aot_linked_classes()) { + // When dumping AOT-linked classes, some classes may have direct references to a method handle + // intrinsic. The easiest thing is to save all of them into the AOT cache. + SystemDictionary::get_all_method_handle_intrinsics(_pending_method_handle_intrinsics); + } + FileMapInfo::check_nonempty_dir_in_shared_path_table(); NOT_PRODUCT(SystemDictionary::verify();) // Block concurrent class unloading from changing the _dumptime_table MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); - SystemDictionaryShared::check_excluded_classes(); + SystemDictionaryShared::find_all_archivable_classes(); _builder.gather_source_objs(); _builder.reserve_buffer(); @@ -589,6 +633,7 @@ void VM_PopulateDumpSharedSpace::doit() { log_info(cds)("Make classes shareable"); _builder.make_klasses_shareable(); + MetaspaceShared::make_method_handle_intrinsics_shareable(); char* early_serialized_data = dump_early_read_only_tables(); char* serialized_data = dump_read_only_tables(); @@ -656,12 +701,12 @@ bool MetaspaceShared::link_class_for_cds(InstanceKlass* ik, TRAPS) { // cpcache to be created. Class verification is done according // to -Xverify setting. bool res = MetaspaceShared::try_link_class(THREAD, ik); - ClassPrelinker::dumptime_resolve_constants(ik, CHECK_(false)); + AOTConstantPoolResolver::dumptime_resolve_constants(ik, CHECK_(false)); return res; } void MetaspaceShared::link_shared_classes(bool jcmd_request, TRAPS) { - ClassPrelinker::initialize(); + AOTClassLinker::initialize(); if (!jcmd_request) { LambdaFormInvokers::regenerate_holder_classes(CHECK); @@ -709,6 +754,7 @@ void MetaspaceShared::prepare_for_dumping() { // Preload classes from a list, populate the shared spaces and dump to a // file. void MetaspaceShared::preload_and_dump(TRAPS) { + CDSConfig::DumperThreadMark dumper_thread_mark(THREAD); ResourceMark rm(THREAD); StaticArchiveBuilder builder; preload_and_dump_impl(builder, THREAD); @@ -723,6 +769,15 @@ void MetaspaceShared::preload_and_dump(TRAPS) { MetaspaceShared::writing_error("Unexpected exception, use -Xlog:cds,exceptions=trace for detail"); } } + + if (!CDSConfig::old_cds_flags_used()) { + // The JLI launcher only recognizes the "old" -Xshare:dump flag. + // When the new -XX:AOTMode=create flag is used, we can't return + // to the JLI launcher, as the launcher will fail when trying to + // run the main class, which is not what we want. + tty->print_cr("AOTCache creation is complete: %s", AOTCache); + vm_exit(0); + } } #if INCLUDE_CDS_JAVA_HEAP && defined(_LP64) @@ -851,6 +906,29 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS HeapShared::reset_archived_object_states(CHECK); } + if (CDSConfig::is_dumping_invokedynamic()) { + // This assert means that the MethodType and MethodTypeForm tables won't be + // updated concurrently when we are saving their contents into a side table. + assert(CDSConfig::allow_only_single_java_thread(), "Required"); + + JavaValue result(T_VOID); + JavaCalls::call_static(&result, vmClasses::MethodType_klass(), + vmSymbols::createArchivedObjects(), + vmSymbols::void_method_signature(), + CHECK); + + // java.lang.Class::reflectionFactory cannot be archived yet. We set this field + // to null, and it will be initialized again at runtime. + log_debug(cds)("Resetting Class::reflectionFactory"); + TempNewSymbol method_name = SymbolTable::new_symbol("resetArchivedStates"); + Symbol* method_sig = vmSymbols::void_method_signature(); + JavaCalls::call_static(&result, vmClasses::Class_klass(), + method_name, method_sig, CHECK); + + // Perhaps there is a way to avoid hard-coding these names here. + // See discussion in JDK-8342481. + } + // Do this at the very end, when no Java code will be executed. Otherwise // some new strings may be added to the intern table. StringTable::allocate_shared_strings_array(CHECK); @@ -1010,6 +1088,9 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() { assert(CDSConfig::is_using_archive(), "Must be called when UseSharedSpaces is enabled"); MapArchiveResult result = MAP_ARCHIVE_OTHER_FAILURE; + // We are about to open the archives. Initialize workers now. + ArchiveWorkers::workers()->initialize(); + FileMapInfo* static_mapinfo = open_static_archive(); FileMapInfo* dynamic_mapinfo = nullptr; @@ -1536,6 +1617,11 @@ MapArchiveResult MetaspaceShared::map_archive(FileMapInfo* mapinfo, char* mapped early_serialize(&rc); } + if (!mapinfo->validate_aot_class_linking()) { + unmap_archive(mapinfo); + return MAP_ARCHIVE_OTHER_FAILURE; + } + mapinfo->set_is_mapped(true); return MAP_ARCHIVE_SUCCESS; } @@ -1596,6 +1682,21 @@ void MetaspaceShared::initialize_shared_spaces() { dynamic_mapinfo->unmap_region(MetaspaceShared::bm); } + // Archive was fully read. Workers are no longer needed. + ArchiveWorkers::workers()->shutdown(); + + LogStreamHandle(Info, cds) lsh; + if (lsh.is_enabled()) { + lsh.print("Using AOT-linked classes: %s (static archive: %s aot-linked classes", + BOOL_TO_STR(CDSConfig::is_using_aot_linked_classes()), + static_mapinfo->header()->has_aot_linked_classes() ? "has" : "no"); + if (dynamic_mapinfo != nullptr) { + lsh.print(", dynamic archive: %s aot-linked classes", + dynamic_mapinfo->header()->has_aot_linked_classes() ? "has" : "no"); + } + lsh.print_cr(")"); + } + // Set up LambdaFormInvokers::_lambdaform_lines for dynamic dump if (CDSConfig::is_dumping_dynamic_archive()) { // Read stored LF format lines stored in static archive diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp index 0b4f6f2ecd4..aaa649d3c0f 100644 --- a/src/hotspot/share/cds/metaspaceShared.hpp +++ b/src/hotspot/share/cds/metaspaceShared.hpp @@ -34,10 +34,12 @@ class ArchiveBuilder; class ArchiveHeapInfo; class FileMapInfo; +class Method; class outputStream; class SerializeClosure; class StaticArchiveBuilder; +template class Array; template class GrowableArray; enum MapArchiveResult { @@ -56,6 +58,7 @@ class MetaspaceShared : AllStatic { static intx _relocation_delta; static char* _requested_base_address; static bool _use_optimized_module_handling; + static Array* _archived_method_handle_intrinsics; public: enum { @@ -111,6 +114,9 @@ class MetaspaceShared : AllStatic { static void unrecoverable_writing_error(const char* message = nullptr); static void writing_error(const char* message = nullptr); + static void make_method_handle_intrinsics_shareable() NOT_CDS_RETURN; + static void write_method_handle_intrinsics() NOT_CDS_RETURN; + static Array* archived_method_handle_intrinsics() { return _archived_method_handle_intrinsics; } static void early_serialize(SerializeClosure* sc) NOT_CDS_RETURN; static void serialize(SerializeClosure* sc) NOT_CDS_RETURN; diff --git a/src/hotspot/share/cds/runTimeClassInfo.cpp b/src/hotspot/share/cds/runTimeClassInfo.cpp index e1329d9d2f9..5ad9c14d13e 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.cpp +++ b/src/hotspot/share/cds/runTimeClassInfo.cpp @@ -62,7 +62,7 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { } } - if (k->is_hidden()) { + if (k->is_hidden() && info.nest_host() != nullptr) { _nest_host_offset = builder->any_to_offset_u4(info.nest_host()); } if (k->has_archived_enum_objs()) { diff --git a/src/hotspot/share/cds/runTimeClassInfo.hpp b/src/hotspot/share/cds/runTimeClassInfo.hpp index d0f02d1c095..e3c1ad4f8fe 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.hpp +++ b/src/hotspot/share/cds/runTimeClassInfo.hpp @@ -177,7 +177,11 @@ class RunTimeClassInfo { InstanceKlass* nest_host() { assert(!ArchiveBuilder::is_active(), "not called when dumping archive"); - return ArchiveUtils::from_offset(_nest_host_offset); + if (_nest_host_offset == 0) { + return nullptr; + } else { + return ArchiveUtils::from_offset(_nest_host_offset); + } } RTLoaderConstraint* loader_constraints() { diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index 6bf8f44553d..eb7d1eaf64d 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -462,14 +462,12 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, } Handle loader; - Handle domain; if (accessing_klass != nullptr) { loader = Handle(current, accessing_klass->loader()); - domain = Handle(current, accessing_klass->protection_domain()); } Klass* found_klass = require_local ? - SystemDictionary::find_instance_or_array_klass(current, sym, loader, domain) : + SystemDictionary::find_instance_or_array_klass(current, sym, loader) : SystemDictionary::find_constrained_instance_or_array_klass(current, sym, loader); // If we fail to find an array klass, look again for its element type. @@ -1611,8 +1609,7 @@ void ciEnv::dump_replay_data_helper(outputStream* out) { GrowableArray* objects = _factory->get_ci_metadata(); out->print_cr("# %d ciObject found", objects->length()); - // The very first entry is the InstanceKlass of the root method of the current compilation in order to get the right - // protection domain to load subsequent classes during replay compilation. + // The very first entry is the InstanceKlass of the root method of the current compilation. ciInstanceKlass::dump_replay_instanceKlass(out, task()->method()->method_holder()); for (int i = 0; i < objects->length(); i++) { diff --git a/src/hotspot/share/ci/ciReplay.cpp b/src/hotspot/share/ci/ciReplay.cpp index fd29e0cf857..c4127263df1 100644 --- a/src/hotspot/share/ci/ciReplay.cpp +++ b/src/hotspot/share/ci/ciReplay.cpp @@ -114,8 +114,6 @@ class CompileReplay : public StackObj { private: FILE* _stream; Thread* _thread; - Handle _protection_domain; - bool _protection_domain_initialized; Handle _loader; int _version; @@ -144,8 +142,6 @@ class CompileReplay : public StackObj { CompileReplay(const char* filename, TRAPS) { _thread = THREAD; _loader = Handle(_thread, SystemDictionary::java_system_loader()); - _protection_domain = Handle(); - _protection_domain_initialized = false; _stream = os::fopen(filename, "rt"); if (_stream == nullptr) { @@ -558,7 +554,7 @@ class CompileReplay : public StackObj { if (_iklass != nullptr) { k = (Klass*)_iklass->find_klass(ciSymbol::make(klass_name->as_C_string()))->constant_encoding(); } else { - k = SystemDictionary::resolve_or_fail(klass_name, _loader, _protection_domain, true, THREAD); + k = SystemDictionary::resolve_or_fail(klass_name, _loader, true, THREAD); } if (HAS_PENDING_EXCEPTION) { oop throwable = PENDING_EXCEPTION; @@ -579,7 +575,7 @@ class CompileReplay : public StackObj { // Lookup a klass Klass* resolve_klass(const char* klass, TRAPS) { Symbol* klass_name = SymbolTable::new_symbol(klass); - return SystemDictionary::resolve_or_fail(klass_name, _loader, _protection_domain, true, THREAD); + return SystemDictionary::resolve_or_fail(klass_name, _loader, true, THREAD); } // Parse the standard tuple of @@ -896,18 +892,6 @@ class CompileReplay : public StackObj { // just load the referenced class Klass* k = parse_klass(CHECK); - if (_version >= 1) { - if (!_protection_domain_initialized && k != nullptr) { - assert(_protection_domain() == nullptr, "must be uninitialized"); - // The first entry is the holder class of the method for which a replay compilation is requested. - // Use the same protection domain to load all subsequent classes in order to resolve all classes - // in signatures of inlinees. This ensures that inlining can be done as stated in the replay file. - _protection_domain = Handle(_thread, k->protection_domain()); - } - - _protection_domain_initialized = true; - } - if (k == nullptr) { return; } diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index eb2d1b684d2..12e7cf1ae9d 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -822,7 +822,6 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, interf = SystemDictionary::resolve_super_or_fail(_class_name, unresolved_klass, Handle(THREAD, _loader_data->class_loader()), - _protection_domain, false, CHECK); } @@ -4659,7 +4658,7 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature, // Checks if name is a legal class name. void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPS) const { - if (!_need_verify || _relax_verify) { return; } + if (!_need_verify) { return; } assert(name->refcount() > 0, "symbol must be kept alive"); char* bytes = (char*)name->bytes(); @@ -4699,7 +4698,7 @@ void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPS) const { // Checks if name is a legal field name. void ClassFileParser::verify_legal_field_name(const Symbol* name, TRAPS) const { - if (!_need_verify || _relax_verify) { return; } + if (!_need_verify) { return; } char* bytes = (char*)name->bytes(); unsigned int length = name->utf8_length(); @@ -4732,7 +4731,7 @@ void ClassFileParser::verify_legal_field_name(const Symbol* name, TRAPS) const { // Checks if name is a legal method name. void ClassFileParser::verify_legal_method_name(const Symbol* name, TRAPS) const { - if (!_need_verify || _relax_verify) { return; } + if (!_need_verify) { return; } assert(name != nullptr, "method name is null"); char* bytes = (char*)name->bytes(); @@ -5236,17 +5235,6 @@ void ClassFileParser::update_class_name(Symbol* new_class_name) { _class_name->increment_refcount(); } -static bool relax_format_check_for(ClassLoaderData* loader_data) { - bool trusted = loader_data->is_boot_class_loader_data() || - loader_data->is_platform_class_loader_data(); - bool need_verify = - // verifyAll - (BytecodeVerificationLocal && BytecodeVerificationRemote) || - // verifyRemote - (!BytecodeVerificationLocal && BytecodeVerificationRemote && !trusted); - return !need_verify; -} - ClassFileParser::ClassFileParser(ClassFileStream* stream, Symbol* name, ClassLoaderData* loader_data, @@ -5303,7 +5291,6 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, _itfs_len(0), _java_fields_count(0), _need_verify(false), - _relax_verify(false), _has_nonstatic_concrete_methods(false), _declares_nonstatic_concrete_methods(false), _has_localvariable_table(false), @@ -5324,24 +5311,10 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, assert(0 == _access_flags.as_int(), "invariant"); // Figure out whether we can skip format checking (matching classic VM behavior) - if (CDSConfig::is_dumping_static_archive()) { - // verify == true means it's a 'remote' class (i.e., non-boot class) - // Verification decision is based on BytecodeVerificationRemote flag - // for those classes. - _need_verify = (stream->need_verify()) ? BytecodeVerificationRemote : - BytecodeVerificationLocal; - } - else { - _need_verify = Verifier::should_verify_for(_loader_data->class_loader(), - stream->need_verify()); - } - - // synch back verification state to stream - stream->set_verify(_need_verify); + _need_verify = Verifier::should_verify_for(_loader_data->class_loader()); - // Check if verification needs to be relaxed for this class file - // Do not restrict it to jdk1.0 or jdk1.1 to maintain backward compatibility (4982376) - _relax_verify = relax_format_check_for(_loader_data); + // synch back verification state to stream to check for truncation. + stream->set_need_verify(_need_verify); parse_stream(stream, CHECK); @@ -5717,7 +5690,6 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st SystemDictionary::resolve_super_or_fail(_class_name, super_class_name, loader, - _protection_domain, true, CHECK); } diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp index 18cdeec7d8e..e993120d140 100644 --- a/src/hotspot/share/classfile/classFileParser.hpp +++ b/src/hotspot/share/classfile/classFileParser.hpp @@ -185,7 +185,6 @@ class ClassFileParser { u2 _java_fields_count; bool _need_verify; - bool _relax_verify; bool _has_nonstatic_concrete_methods; bool _declares_nonstatic_concrete_methods; diff --git a/src/hotspot/share/classfile/classFileStream.cpp b/src/hotspot/share/classfile/classFileStream.cpp index ed67481396d..a934cbafa45 100644 --- a/src/hotspot/share/classfile/classFileStream.cpp +++ b/src/hotspot/share/classfile/classFileStream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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,8 +28,6 @@ #include "classfile/vmSymbols.hpp" #include "memory/resourceArea.hpp" -const bool ClassFileStream::verify = true; - void ClassFileStream::truncated_file_error(TRAPS) const { THROW_MSG(vmSymbols::java_lang_ClassFormatError(), "Truncated class file"); } @@ -37,13 +35,12 @@ void ClassFileStream::truncated_file_error(TRAPS) const { ClassFileStream::ClassFileStream(const u1* buffer, int length, const char* source, - bool verify_stream, bool from_boot_loader_modules_image) : _buffer_start(buffer), _buffer_end(buffer + length), _current(buffer), _source(source), - _need_verify(verify_stream), + _need_verify(true), // may be reset by ClassFileParser when this stream is parsed. _from_boot_loader_modules_image(from_boot_loader_modules_image) { assert(buffer != nullptr, "caller should throw NPE"); } @@ -72,6 +69,5 @@ const ClassFileStream* ClassFileStream::clone() const { return new ClassFileStream(new_buffer_start, length(), clone_source(), - need_verify(), from_boot_loader_modules_image()); } diff --git a/src/hotspot/share/classfile/classFileStream.hpp b/src/hotspot/share/classfile/classFileStream.hpp index 41a7df68bd5..67d66bb74a1 100644 --- a/src/hotspot/share/classfile/classFileStream.hpp +++ b/src/hotspot/share/classfile/classFileStream.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ class ClassFileStream: public ResourceObj { const u1* const _buffer_end; // Buffer top (one past last element) mutable const u1* _current; // Current buffer position const char* const _source; // Source of stream (directory name, ZIP/JAR archive name) - bool _need_verify; // True if verification is on for the class file + bool _need_verify; // True if we need to verify and check truncation of stream bytes. bool _from_boot_loader_modules_image; // True if this was created by ClassPathImageEntry. void truncated_file_error(TRAPS) const ; @@ -52,12 +52,9 @@ class ClassFileStream: public ResourceObj { const char* clone_source() const; public: - static const bool verify; - ClassFileStream(const u1* buffer, int length, const char* source, - bool verify_stream = verify, // to be verified by default bool from_boot_loader_modules_image = false); virtual const ClassFileStream* clone() const; @@ -77,7 +74,7 @@ class ClassFileStream: public ResourceObj { } const char* source() const { return _source; } bool need_verify() const { return _need_verify; } - void set_verify(bool flag) { _need_verify = flag; } + void set_need_verify(bool flag) { _need_verify = flag; } bool from_boot_loader_modules_image() const { return _from_boot_loader_modules_image; } void check_truncated_file(bool b, TRAPS) const { diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index cb155bdeb19..1b34f2ebede 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -26,16 +26,17 @@ #include "cds/cds_globals.hpp" #include "cds/cdsConfig.hpp" #include "cds/filemap.hpp" +#include "cds/heapShared.hpp" #include "classfile/classFileStream.hpp" #include "classfile/classLoader.inline.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderExt.hpp" #include "classfile/classLoadInfo.hpp" #include "classfile/javaClasses.hpp" +#include "classfile/klassFactory.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/modules.hpp" #include "classfile/packageEntry.hpp" -#include "classfile/klassFactory.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" @@ -140,20 +141,16 @@ PerfCounter* ClassLoader::_perf_resolve_mh_count = nullptr; PerfCounter* ClassLoader::_perf_resolve_mt_count = nullptr; void ClassLoader::print_counters(outputStream *st) { - // The counters are only active if the logging is enabled, but - // we print to the passed in outputStream as requested. - if (log_is_enabled(Info, perf, class, link)) { - st->print_cr("ClassLoader:"); - st->print_cr(" clinit: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", ClassLoader::class_init_time_ms(), ClassLoader::class_init_count()); - st->print_cr(" link methods: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_ik_link_methods_time->get_value()) , _perf_ik_link_methods_count->get_value()); - st->print_cr(" method adapters: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_method_adapters_time->get_value()) , _perf_method_adapters_count->get_value()); - st->print_cr(" resolve..."); - st->print_cr(" invokedynamic: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_indy_time->get_value()) , _perf_resolve_indy_count->get_value()); - st->print_cr(" invokehandle: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_invokehandle_time->get_value()) , _perf_resolve_invokehandle_count->get_value()); - st->print_cr(" CP_MethodHandle: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_mh_time->get_value()) , _perf_resolve_mh_count->get_value()); - st->print_cr(" CP_MethodType: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_mt_time->get_value()) , _perf_resolve_mt_count->get_value()); - st->cr(); - } + st->print_cr("ClassLoader:"); + st->print_cr(" clinit: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", ClassLoader::class_init_time_ms(), ClassLoader::class_init_count()); + st->print_cr(" link methods: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_ik_link_methods_time->get_value()) , _perf_ik_link_methods_count->get_value()); + st->print_cr(" method adapters: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_method_adapters_time->get_value()) , _perf_method_adapters_count->get_value()); + st->print_cr(" resolve..."); + st->print_cr(" invokedynamic: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_indy_time->get_value()) , _perf_resolve_indy_count->get_value()); + st->print_cr(" invokehandle: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_invokehandle_time->get_value()) , _perf_resolve_invokehandle_count->get_value()); + st->print_cr(" CP_MethodHandle: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_mh_time->get_value()) , _perf_resolve_mh_count->get_value()); + st->print_cr(" CP_MethodType: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_mt_time->get_value()) , _perf_resolve_mt_count->get_value()); + st->cr(); } GrowableArray* ClassLoader::_patch_mod_entries = nullptr; @@ -297,8 +294,7 @@ ClassFileStream* ClassPathDirEntry::open_stream(JavaThread* current, const char* // Resource allocated return new ClassFileStream(buffer, checked_cast(st.st_size), - _dir, - ClassFileStream::verify); + _dir); } } } @@ -366,8 +362,7 @@ ClassFileStream* ClassPathZipEntry::open_stream(JavaThread* current, const char* // Resource allocated return new ClassFileStream(buffer, filesize, - _zip_name, - ClassFileStream::verify); + _zip_name); } DEBUG_ONLY(ClassPathImageEntry* ClassPathImageEntry::_singleton = nullptr;) @@ -449,7 +444,6 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(JavaThread* current return new ClassFileStream((u1*)data, checked_cast(size), _name, - ClassFileStream::verify, true); // from_boot_loader_modules_image } @@ -1198,8 +1192,6 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, PackageEntry* pkg_entry, bo return nullptr; } - stream->set_verify(ClassLoaderExt::should_verify(classpath_index)); - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); Handle protection_domain; ClassLoadInfo cl_info(protection_domain); @@ -1282,7 +1274,7 @@ void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, assert(stream != nullptr, "sanity"); if (ik->is_hidden()) { - // We do not archive hidden classes. + record_hidden_class(ik); return; } @@ -1384,6 +1376,44 @@ void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, assert(file_name != nullptr, "invariant"); ClassLoaderExt::record_result(checked_cast(classpath_index), ik, redefined); } + +void ClassLoader::record_hidden_class(InstanceKlass* ik) { + assert(ik->is_hidden(), "must be"); + + s2 classloader_type; + if (HeapShared::is_lambda_form_klass(ik)) { + classloader_type = ClassLoader::BOOT_LOADER; + } else { + oop loader = ik->class_loader(); + + if (loader == nullptr) { + classloader_type = ClassLoader::BOOT_LOADER; + } else if (SystemDictionary::is_platform_class_loader(loader)) { + classloader_type = ClassLoader::PLATFORM_LOADER; + } else if (SystemDictionary::is_system_class_loader(loader)) { + classloader_type = ClassLoader::APP_LOADER; + } else { + // This class won't be archived, so no need to update its + // classloader_type/classpath_index. + return; + } + } + ik->set_shared_class_loader_type(classloader_type); + + if (HeapShared::is_lambda_proxy_klass(ik)) { + InstanceKlass* nest_host = ik->nest_host_not_null(); + ik->set_shared_classpath_index(nest_host->shared_classpath_index()); + } else if (HeapShared::is_lambda_form_klass(ik)) { + ik->set_shared_classpath_index(0); + } else { + // Generated invoker classes. + if (classloader_type == ClassLoader::APP_LOADER) { + ik->set_shared_classpath_index(ClassLoaderExt::app_class_paths_start_index()); + } else { + ik->set_shared_classpath_index(0); + } + } +} #endif // INCLUDE_CDS // Initialize the class loader's access to methods in libzip. Parse and diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index e44059b7247..d6780054904 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -140,6 +140,7 @@ class ModuleClassPathList : public CHeapObj { class ClassLoader: AllStatic { public: enum ClassLoaderType { + OTHER = 0, BOOT_LOADER = 1, /* boot loader */ PLATFORM_LOADER = 2, /* PlatformClassLoader */ APP_LOADER = 3 /* AppClassLoader */ @@ -385,6 +386,7 @@ class ClassLoader: AllStatic { static char* uri_to_path(const char* uri); static void record_result(JavaThread* current, InstanceKlass* ik, const ClassFileStream* stream, bool redefined); + static void record_hidden_class(InstanceKlass* ik); #endif static char* lookup_vm_options(); diff --git a/src/hotspot/share/classfile/classLoaderExt.hpp b/src/hotspot/share/classfile/classLoaderExt.hpp index 1f1b38cd312..ce0013b9d49 100644 --- a/src/hotspot/share/classfile/classLoaderExt.hpp +++ b/src/hotspot/share/classfile/classLoaderExt.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -33,11 +33,6 @@ class ClassListParser; class ClassLoaderExt: public ClassLoader { // AllStatic public: - static bool should_verify(int classpath_index) { - CDS_ONLY(return (classpath_index >= _app_class_paths_start_index);) - NOT_CDS(return false;) - } - #if INCLUDE_CDS private: enum SomeConstants { diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp index eecfc9e88a0..92f362860eb 100644 --- a/src/hotspot/share/classfile/dictionary.cpp +++ b/src/hotspot/share/classfile/dictionary.cpp @@ -26,26 +26,14 @@ #include "cds/cdsConfig.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/dictionary.hpp" -#include "classfile/javaClasses.hpp" -#include "classfile/protectionDomainCache.hpp" -#include "classfile/systemDictionary.hpp" -#include "classfile/vmSymbols.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/iterator.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" -#include "memory/universe.hpp" -#include "oops/klass.inline.hpp" -#include "oops/method.hpp" -#include "oops/oop.inline.hpp" -#include "oops/oopHandle.inline.hpp" -#include "runtime/handles.inline.hpp" -#include "runtime/javaCalls.hpp" -#include "runtime/mutexLocker.hpp" -#include "runtime/safepointVerifiers.hpp" +#include "oops/instanceKlass.hpp" #include "utilities/concurrentHashTable.inline.hpp" -#include "utilities/growableArray.hpp" +#include "utilities/ostream.hpp" #include "utilities/tableStatistics.hpp" // 2^24 is max size, like StringTable. @@ -56,7 +44,7 @@ const size_t REHASH_LEN = 100; Dictionary::Dictionary(ClassLoaderData* loader_data, size_t table_size) : _number_of_entries(0), _loader_data(loader_data) { - size_t start_size_log_2 = MAX2(ceil_log2(table_size), (size_t)2); // 2 is minimum size even though some dictionaries only have one entry + size_t start_size_log_2 = MAX2(ceil_log2(table_size), 2); // 2 is minimum size even though some dictionaries only have one entry size_t current_size = ((size_t)1) << start_size_log_2; log_info(class, loader, data)("Dictionary start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", current_size, start_size_log_2); @@ -69,7 +57,7 @@ Dictionary::~Dictionary() { } uintx Dictionary::Config::get_hash(Value const& value, bool* is_dead) { - return value->instance_klass()->name()->identity_hash(); + return value->name()->identity_hash(); } void* Dictionary::Config::allocate_node(void* context, size_t size, Value const& value) { @@ -77,26 +65,9 @@ void* Dictionary::Config::allocate_node(void* context, size_t size, Value const& } void Dictionary::Config::free_node(void* context, void* memory, Value const& value) { - delete value; // Call DictionaryEntry destructor FreeHeap(memory); } -DictionaryEntry::DictionaryEntry(InstanceKlass* klass) : _instance_klass(klass) { - release_set_package_access_cache(nullptr); -} - -DictionaryEntry::~DictionaryEntry() { - // avoid recursion when deleting linked list - // package_access_cache is accessed during a safepoint. - // This doesn't require a lock because nothing is reading this - // entry anymore. The ClassLoader is dead. - while (package_access_cache_acquire() != nullptr) { - ProtectionDomainEntry* to_delete = package_access_cache_acquire(); - release_set_package_access_cache(to_delete->next_acquire()); - delete to_delete; - } -} - const int _resize_load_trigger = 5; // load factor that will trigger the resize int Dictionary::table_size() const { @@ -108,86 +79,10 @@ bool Dictionary::check_if_needs_resize() { !_table->is_max_size_reached()); } -bool DictionaryEntry::has_package_access_been_granted(Handle protection_domain) { - return protection_domain() == nullptr || !java_lang_System::allow_security_manager() - ? true - : is_in_package_access_cache(protection_domain()); -} - -// Reading the package_access_cache on each DictionaryEntry is lock free and cannot safepoint. -// Adding and deleting entries is under the SystemDictionary_lock -// Deleting unloaded entries on ClassLoaderData for dictionaries that are not unloaded -// is a three step process: -// moving the entries to a separate list, handshake to wait for -// readers to complete (see NSV here), and then actually deleting the entries. -// Deleting entries is done by the ServiceThread when triggered by class unloading. - -bool DictionaryEntry::is_in_package_access_cache(oop protection_domain) const { - assert(Thread::current()->is_Java_thread() || SafepointSynchronize::is_at_safepoint(), - "can only be called by a JavaThread or at safepoint"); - // This cannot safepoint while reading the protection domain set. - NoSafepointVerifier nsv; -#ifdef ASSERT - if (protection_domain == instance_klass()->protection_domain()) { - // Ensure this doesn't show up in the package_access_cache (invariant) - bool in_package_access_cache = false; - for (ProtectionDomainEntry* current = package_access_cache_acquire(); - current != nullptr; - current = current->next_acquire()) { - if (current->object_no_keepalive() == protection_domain) { - in_package_access_cache = true; - break; - } - } - if (in_package_access_cache) { - assert(false, "A klass's protection domain should not show up " - "in its sys. dict. PD set"); - } - } -#endif /* ASSERT */ - - if (protection_domain == instance_klass()->protection_domain()) { - // Succeeds trivially - return true; - } - - for (ProtectionDomainEntry* current = package_access_cache_acquire(); - current != nullptr; - current = current->next_acquire()) { - if (current->object_no_keepalive() == protection_domain) { - return true; - } - } - return false; -} - -void DictionaryEntry::add_to_package_access_cache(ClassLoaderData* loader_data, Handle protection_domain) { - assert_lock_strong(SystemDictionary_lock); - if (!is_in_package_access_cache(protection_domain())) { - WeakHandle obj = ProtectionDomainCacheTable::add_if_absent(protection_domain); - // Additions and deletions hold the SystemDictionary_lock, readers are lock-free - ProtectionDomainEntry* new_head = new ProtectionDomainEntry(obj, _package_access_cache); - release_set_package_access_cache(new_head); - } - LogTarget(Trace, protectiondomain) lt; - if (lt.is_enabled()) { - ResourceMark rm; - LogStream ls(lt); - ls.print("adding protection domain that can access class %s", instance_klass()->name()->as_C_string()); - ls.print(" class loader: "); - loader_data->class_loader()->print_value_on(&ls); - ls.print(" protection domain: "); - protection_domain->print_value_on(&ls); - ls.print(" "); - print_count(&ls); - ls.cr(); - } -} - // Just the classes from defining class loaders void Dictionary::classes_do(void f(InstanceKlass*)) { - auto doit = [&] (DictionaryEntry** value) { - InstanceKlass* k = (*value)->instance_klass(); + auto doit = [&] (InstanceKlass** value) { + InstanceKlass* k = (*value); if (loader_data() == k->class_loader_data()) { f(k); } @@ -199,8 +94,8 @@ void Dictionary::classes_do(void f(InstanceKlass*)) { // All classes, and their class loaders, including initiating class loaders void Dictionary::all_entries_do(KlassClosure* closure) { - auto all_doit = [&] (DictionaryEntry** value) { - InstanceKlass* k = (*value)->instance_klass(); + auto all_doit = [&] (InstanceKlass** value) { + InstanceKlass* k = (*value); closure->do_klass(k); return true; }; @@ -212,9 +107,8 @@ void Dictionary::all_entries_do(KlassClosure* closure) { void Dictionary::classes_do(MetaspaceClosure* it) { assert(CDSConfig::is_dumping_archive(), "sanity"); - auto push = [&] (DictionaryEntry** value) { - InstanceKlass** k = (*value)->instance_klass_addr(); - it->push(k); + auto push = [&] (InstanceKlass** value) { + it->push(value); return true; }; _table->do_scan(Thread::current(), push); @@ -228,26 +122,25 @@ class DictionaryLookup : StackObj { uintx get_hash() const { return _name->identity_hash(); } - bool equals(DictionaryEntry** value) { - DictionaryEntry *entry = *value; - return (entry->instance_klass()->name() == _name); + bool equals(InstanceKlass** value) { + InstanceKlass* entry = *value; + return (entry->name() == _name); } - bool is_dead(DictionaryEntry** value) { + bool is_dead(InstanceKlass** value) { return false; } }; // Add a loaded class to the dictionary. void Dictionary::add_klass(JavaThread* current, Symbol* class_name, - InstanceKlass* obj) { + InstanceKlass* klass) { assert_locked_or_safepoint(SystemDictionary_lock); // doesn't matter now - assert(obj != nullptr, "adding nullptr obj"); - assert(obj->name() == class_name, "sanity check on name"); + assert(klass != nullptr, "adding nullptr obj"); + assert(klass->name() == class_name, "sanity check on name"); - DictionaryEntry* entry = new DictionaryEntry(obj); DictionaryLookup lookup(class_name); bool needs_rehashing, clean_hint; - bool created = _table->insert(current, lookup, entry, &needs_rehashing, &clean_hint); + bool created = _table->insert(current, lookup, klass, &needs_rehashing, &clean_hint); assert(created, "should be because we have a lock"); assert (!needs_rehashing, "should never need rehashing"); assert(!clean_hint, "no class should be unloaded"); @@ -277,11 +170,10 @@ void Dictionary::add_klass(JavaThread* current, Symbol* class_name, // Callers should be aware that an entry could be added just after // the table is read here, so the caller will not see the new entry. // The entry may be accessed by the VM thread in verification. -DictionaryEntry* Dictionary::get_entry(Thread* current, - Symbol* class_name) { +InstanceKlass* Dictionary::find_class(Thread* current, Symbol* class_name) { DictionaryLookup lookup(class_name); - DictionaryEntry* result = nullptr; - auto get = [&] (DictionaryEntry** value) { + InstanceKlass* result = nullptr; + auto get = [&] (InstanceKlass** value) { // function called if value is found so is never null result = (*value); }; @@ -291,137 +183,6 @@ DictionaryEntry* Dictionary::get_entry(Thread* current, return result; } -// If SecurityManager is allowed, return the class ONLY IF the protection_domain has been -// granted access to this class by a previous call to Dictionary::check_package_access() -InstanceKlass* Dictionary::find(Thread* current, Symbol* name, - Handle protection_domain) { - NoSafepointVerifier nsv; - - DictionaryEntry* entry = get_entry(current, name); - if (entry != nullptr && entry->has_package_access_been_granted(protection_domain)) { - return entry->instance_klass(); - } else { - return nullptr; - } -} - -InstanceKlass* Dictionary::find_class(Thread* current, - Symbol* name) { - assert_locked_or_safepoint(SystemDictionary_lock); - DictionaryEntry* entry = get_entry(current, name); - return (entry != nullptr) ? entry->instance_klass() : nullptr; -} - -void Dictionary::add_to_package_access_cache(JavaThread* current, - InstanceKlass* klass, - Handle protection_domain) { - assert(java_lang_System::allow_security_manager(), "only needed if security manager allowed"); - Symbol* klass_name = klass->name(); - DictionaryEntry* entry = get_entry(current, klass_name); - - assert(entry != nullptr,"entry must be present, we just created it"); - assert(protection_domain() != nullptr, - "real protection domain should be present"); - - entry->add_to_package_access_cache(loader_data(), protection_domain); - -#ifdef ASSERT - assert(loader_data() != ClassLoaderData::the_null_class_loader_data(), "doesn't make sense"); -#endif - - assert(entry->is_in_package_access_cache(protection_domain()), - "now protection domain should be present"); -} - -inline bool Dictionary::is_in_package_access_cache(JavaThread* current, - Symbol* name, - Handle protection_domain) { - DictionaryEntry* entry = get_entry(current, name); - return entry->has_package_access_been_granted(protection_domain); -} - -void Dictionary::check_package_access(InstanceKlass* klass, - Handle class_loader, - Handle protection_domain, - TRAPS) { - - assert(class_loader() != nullptr, "Should not call this"); - assert(protection_domain() != nullptr, "Should not call this"); -} - -// During class loading we may have cached a protection domain that has -// since been unreferenced, so this entry should be cleared. -void Dictionary::remove_from_package_access_cache(GrowableArray* delete_list) { - assert(Thread::current()->is_Java_thread(), "only called by JavaThread"); - assert_lock_strong(SystemDictionary_lock); - assert(!loader_data()->has_class_mirror_holder(), "cld should have a ClassLoader holder not a Class holder"); - - if (loader_data()->is_the_null_class_loader_data()) { - // Classes in the boot loader are not loaded with protection domains - return; - } - - auto clean_entries = [&] (DictionaryEntry** value) { - DictionaryEntry* probe = *value; - Klass* e = probe->instance_klass(); - - ProtectionDomainEntry* current = probe->package_access_cache_acquire(); - ProtectionDomainEntry* prev = nullptr; - while (current != nullptr) { - if (current->object_no_keepalive() == nullptr) { - LogTarget(Debug, protectiondomain) lt; - if (lt.is_enabled()) { - ResourceMark rm; - // Print out trace information - LogStream ls(lt); - ls.print_cr("PD in set is not alive:"); - ls.print("class loader: "); _loader_data->class_loader()->print_value_on(&ls); - ls.print(" loading: "); probe->instance_klass()->print_value_on(&ls); - ls.cr(); - } - if (probe->package_access_cache_acquire() == current) { - probe->release_set_package_access_cache(current->next_acquire()); - } else { - assert(prev != nullptr, "should be set by alive entry"); - prev->release_set_next(current->next_acquire()); - } - // Mark current for deletion but in the meantime it can still be - // traversed. - delete_list->push(current); - current = current->next_acquire(); - } else { - prev = current; - current = current->next_acquire(); - } - } - return true; - }; - - _table->do_scan(Thread::current(), clean_entries); -} - -void DictionaryEntry::verify_package_access_cache() { - assert(SafepointSynchronize::is_at_safepoint(), "must only be called as safepoint"); - for (ProtectionDomainEntry* current = package_access_cache_acquire(); // accessed at a safepoint - current != nullptr; - current = current->next_acquire()) { - guarantee(oopDesc::is_oop_or_null(current->object_no_keepalive()), "Invalid oop"); - } -} - -void DictionaryEntry::print_count(outputStream *st) { - assert_locked_or_safepoint(SystemDictionary_lock); - int count = 0; - for (ProtectionDomainEntry* current = package_access_cache_acquire(); - current != nullptr; - current = current->next_acquire()) { - count++; - } - st->print("pd set count = #%d", count); -} - -// ---------------------------------------------------------------------------- - void Dictionary::print_size(outputStream* st) const { st->print_cr("Java dictionary (table_size=%d, classes=%d)", table_size(), _number_of_entries); @@ -435,9 +196,8 @@ void Dictionary::print_on(outputStream* st) const { print_size(st); st->print_cr("^ indicates that initiating loader is different from defining loader"); - auto printer = [&] (DictionaryEntry** entry) { - DictionaryEntry* probe = *entry; - Klass* e = probe->instance_klass(); + auto printer = [&] (InstanceKlass** entry) { + InstanceKlass* e = *entry; bool is_defining_class = (_loader_data == e->class_loader_data()); st->print(" %s%s", is_defining_class ? " " : "^", e->external_name()); @@ -448,7 +208,6 @@ void Dictionary::print_on(outputStream* st) const { st->print(", "); cld->print_value_on(st); st->print(", "); - probe->print_count(st); } st->cr(); return true; @@ -462,14 +221,6 @@ void Dictionary::print_on(outputStream* st) const { tty->cr(); } -void DictionaryEntry::verify() { - Klass* e = instance_klass(); - guarantee(e->is_instance_klass(), - "Verify of dictionary failed"); - e->verify(); - verify_package_access_cache(); -} - void Dictionary::verify() { guarantee(_number_of_entries >= 0, "Verify of dictionary failed"); @@ -480,7 +231,7 @@ void Dictionary::verify() { (cld->is_the_null_class_loader_data() || cld->class_loader_no_keepalive()->is_instance()), "checking type of class_loader"); - auto verifier = [&] (DictionaryEntry** val) { + auto verifier = [&] (InstanceKlass** val) { (*val)->verify(); return true; }; @@ -490,7 +241,7 @@ void Dictionary::verify() { void Dictionary::print_table_statistics(outputStream* st, const char* table_name) { static TableStatistics ts; - auto sz = [&] (DictionaryEntry** val) { + auto sz = [&] (InstanceKlass** val) { return sizeof(**val); }; ts = _table->statistics_get(Thread::current(), sz, ts); diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp index fc2747e916a..3f7f381b466 100644 --- a/src/hotspot/share/classfile/dictionary.hpp +++ b/src/hotspot/share/classfile/dictionary.hpp @@ -25,27 +25,21 @@ #ifndef SHARE_CLASSFILE_DICTIONARY_HPP #define SHARE_CLASSFILE_DICTIONARY_HPP -#include "oops/instanceKlass.hpp" -#include "oops/oop.hpp" -#include "oops/oopHandle.hpp" #include "utilities/concurrentHashTable.hpp" -#include "utilities/ostream.hpp" -class DictionaryEntry; -class ProtectionDomainEntry; -template class GrowableArray; +class ClassLoaderData; +class InstanceKlass; +class outputStream; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // The data structure for the class loader data dictionaries. -class DictionaryEntry; - class Dictionary : public CHeapObj { int _number_of_entries; class Config { public: - using Value = DictionaryEntry*; + using Value = InstanceKlass*; static uintx get_hash(Value const& value, bool* is_dead); static void* allocate_node(void* context, size_t size, Value const& value); static void free_node(void* context, void* memory, Value const& value); @@ -57,7 +51,6 @@ class Dictionary : public CHeapObj { ClassLoaderData* _loader_data; // backpointer to owning loader ClassLoaderData* loader_data() const { return _loader_data; } - DictionaryEntry* get_entry(Thread* current, Symbol* name); bool check_if_needs_resize(); int table_size() const; @@ -73,58 +66,11 @@ class Dictionary : public CHeapObj { void all_entries_do(KlassClosure* closure); void classes_do(MetaspaceClosure* it); - void remove_from_package_access_cache(GrowableArray* delete_list); - - InstanceKlass* find(Thread* current, Symbol* name, Handle protection_domain); - - // May make Java upcalls to ClassLoader.checkPackageAccess() when a SecurityManager - // is installed. - void check_package_access(InstanceKlass* klass, - Handle class_loader, - Handle protection_domain, - TRAPS); - void print_table_statistics(outputStream* st, const char* table_name); void print_on(outputStream* st) const; void print_size(outputStream* st) const; void verify(); - - private: - bool is_in_package_access_cache(JavaThread* current, Symbol* name, - Handle protection_domain); - void add_to_package_access_cache(JavaThread* current, InstanceKlass* klass, - Handle protection_domain); -}; - -class DictionaryEntry : public CHeapObj { - private: - InstanceKlass* _instance_klass; - - // A cache of the ProtectionDomains that have been granted - // access to the package of _instance_klass by Java up-calls to - // ClassLoader.checkPackageAccess(). See Dictionary::check_package_access(). - // - // We use a cache to avoid repeat Java up-calls that can be expensive. - ProtectionDomainEntry* volatile _package_access_cache; - - public: - DictionaryEntry(InstanceKlass* instance_klass); - ~DictionaryEntry(); - - bool is_in_package_access_cache(oop protection_domain) const; - void add_to_package_access_cache(ClassLoaderData* loader_data, Handle protection_domain); - inline bool has_package_access_been_granted(Handle protection_domain); - void verify_package_access_cache(); - - InstanceKlass* instance_klass() const { return _instance_klass; } - InstanceKlass** instance_klass_addr() { return &_instance_klass; } - - ProtectionDomainEntry* package_access_cache_acquire() const { return Atomic::load_acquire(&_package_access_cache); } - void release_set_package_access_cache(ProtectionDomainEntry* entry) { Atomic::release_store(&_package_access_cache, entry); } - - void print_count(outputStream *st); - void verify(); }; #endif // SHARE_CLASSFILE_DICTIONARY_HPP diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 0dd183e06d4..c8f6276cb01 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -347,7 +347,7 @@ Handle java_lang_String::create_from_str(const char* utf8_str, TRAPS) { #ifdef ASSERT // This check is too strict when the input string is not a valid UTF8. // For example, it may be created with arbitrary content via jni_NewStringUTF. - if (UTF8::is_legal_utf8((const unsigned char*)utf8_str, strlen(utf8_str), false)) { + if (UTF8::is_legal_utf8((const unsigned char*)utf8_str, strlen(utf8_str), /*version_leq_47*/false)) { ResourceMark rm; const char* expected = utf8_str; char* actual = as_utf8_string(h_obj()); @@ -365,7 +365,7 @@ oop java_lang_String::create_oop_from_str(const char* utf8_str, TRAPS) { return h_obj(); } -Handle java_lang_String::create_from_symbol(Symbol* symbol, TRAPS) { +Handle java_lang_String::create_from_symbol(const Symbol* symbol, TRAPS) { const char* utf8_str = (char*)symbol->bytes(); int utf8_len = symbol->utf8_length(); @@ -389,6 +389,8 @@ Handle java_lang_String::create_from_symbol(Symbol* symbol, TRAPS) { } #ifdef ASSERT + // This check is too strict on older classfile versions + if (UTF8::is_legal_utf8((const unsigned char*)utf8_str, utf8_len, /*version_leq_47*/false)) { ResourceMark rm; const char* expected = symbol->as_utf8(); @@ -755,6 +757,35 @@ bool java_lang_String::equals(oop java_string, const jchar* chars, int len) { return true; } +bool java_lang_String::equals(oop java_string, const char* utf8_string, size_t utf8_len) { + assert(java_string->klass() == vmClasses::String_klass(), + "must be java_string"); + typeArrayOop value = java_lang_String::value_no_keepalive(java_string); + int length = java_lang_String::length(java_string, value); + int unicode_length = UTF8::unicode_length(utf8_string, utf8_len); + if (length != unicode_length) { + return false; + } + bool is_latin1 = java_lang_String::is_latin1(java_string); + jchar c; + if (!is_latin1) { + for (int i = 0; i < unicode_length; i++) { + utf8_string = UTF8::next(utf8_string, &c); + if (value->char_at(i) != c) { + return false; + } + } + } else { + for (int i = 0; i < unicode_length; i++) { + utf8_string = UTF8::next(utf8_string, &c); + if ((((jchar) value->byte_at(i)) & 0xff) != c) { + return false; + } + } + } + return true; +} + bool java_lang_String::equals(oop str1, oop str2) { assert(str1->klass() == vmClasses::String_klass(), "must be java String"); @@ -836,6 +867,7 @@ int java_lang_Class::_name_offset; int java_lang_Class::_source_file_offset; int java_lang_Class::_classData_offset; int java_lang_Class::_classRedefinedCount_offset; +int java_lang_Class::_reflectionData_offset; bool java_lang_Class::_offsets_computed = false; GrowableArray* java_lang_Class::_fixup_mirror_list = nullptr; @@ -1272,6 +1304,11 @@ void java_lang_Class::set_class_data(oop java_class, oop class_data) { java_class->obj_field_put(_classData_offset, class_data); } +void java_lang_Class::set_reflection_data(oop java_class, oop reflection_data) { + assert(_reflectionData_offset != 0, "must be set"); + java_class->obj_field_put(_reflectionData_offset, reflection_data); +} + void java_lang_Class::set_class_loader(oop java_class, oop loader) { assert(_class_loader_offset != 0, "offsets should have been initialized"); java_class->obj_field_put(_class_loader_offset, loader); @@ -1462,6 +1499,7 @@ oop java_lang_Class::primitive_mirror(BasicType t) { macro(_module_offset, k, "module", module_signature, false); \ macro(_name_offset, k, "name", string_signature, false); \ macro(_classData_offset, k, "classData", object_signature, false); \ + macro(_reflectionData_offset, k, "reflectionData", java_lang_ref_SoftReference_signature, false); \ macro(_signers_offset, k, "signers", object_array_signature, false); void java_lang_Class::compute_offsets() { @@ -1608,7 +1646,7 @@ JFR_ONLY(int java_lang_Thread::_jfr_epoch_offset;) #define THREAD_FIELDS_DO(macro) \ macro(_holder_offset, k, "holder", thread_fieldholder_signature, false); \ macro(_name_offset, k, vmSymbols::name_name(), string_signature, false); \ - macro(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), classloader_signature, false); \ + macro(_contextClassLoader_offset, k, "contextClassLoader", classloader_signature, false); \ macro(_eetop_offset, k, "eetop", long_signature, false); \ macro(_interrupted_offset, k, "interrupted", bool_signature, false); \ macro(_interruptLock_offset, k, "interruptLock", object_signature, false); \ @@ -2014,6 +2052,7 @@ int java_lang_VirtualThread::_next_offset; int java_lang_VirtualThread::_onWaitingList_offset; int java_lang_VirtualThread::_notified_offset; int java_lang_VirtualThread::_timeout_offset; +int java_lang_VirtualThread::_objectWaiter_offset; #define VTHREAD_FIELDS_DO(macro) \ macro(static_vthread_scope_offset, k, "VTHREAD_SCOPE", continuationscope_signature, true); \ @@ -2029,6 +2068,7 @@ int java_lang_VirtualThread::_timeout_offset; void java_lang_VirtualThread::compute_offsets() { InstanceKlass* k = vmClasses::VirtualThread_klass(); VTHREAD_FIELDS_DO(FIELD_COMPUTE_OFFSET); + VTHREAD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } bool java_lang_VirtualThread::is_instance(oop obj) { @@ -2144,6 +2184,22 @@ JavaThreadStatus java_lang_VirtualThread::map_state_to_thread_status(int state) return status; } +ObjectMonitor* java_lang_VirtualThread::current_pending_monitor(oop vthread) { + ObjectWaiter* waiter = objectWaiter(vthread); + if (waiter != nullptr && waiter->at_monitorenter()) { + return waiter->monitor(); + } + return nullptr; +} + +ObjectMonitor* java_lang_VirtualThread::current_waiting_monitor(oop vthread) { + ObjectWaiter* waiter = objectWaiter(vthread); + if (waiter != nullptr && waiter->is_wait()) { + return waiter->monitor(); + } + return nullptr; +} + bool java_lang_VirtualThread::is_preempted(oop vthread) { oop continuation = java_lang_VirtualThread::continuation(vthread); assert(continuation != nullptr, "vthread with no continuation"); @@ -2154,6 +2210,7 @@ bool java_lang_VirtualThread::is_preempted(oop vthread) { #if INCLUDE_CDS void java_lang_VirtualThread::serialize_offsets(SerializeClosure* f) { VTHREAD_FIELDS_DO(FIELD_SERIALIZE_OFFSET); + VTHREAD_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); } #endif @@ -4683,47 +4740,6 @@ DependencyContext java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdepend return dep_ctx; } -// Support for java_security_AccessControlContext - -int java_security_AccessControlContext::_context_offset; -int java_security_AccessControlContext::_privilegedContext_offset; -int java_security_AccessControlContext::_isPrivileged_offset; -int java_security_AccessControlContext::_isAuthorized_offset; - -#define ACCESSCONTROLCONTEXT_FIELDS_DO(macro) \ - macro(_context_offset, k, "context", protectiondomain_signature, false); \ - macro(_privilegedContext_offset, k, "privilegedContext", accesscontrolcontext_signature, false); \ - macro(_isPrivileged_offset, k, "isPrivileged", bool_signature, false); \ - macro(_isAuthorized_offset, k, "isAuthorized", bool_signature, false) - -void java_security_AccessControlContext::compute_offsets() { - assert(_isPrivileged_offset == 0, "offsets should be initialized only once"); - InstanceKlass* k = vmClasses::AccessControlContext_klass(); - ACCESSCONTROLCONTEXT_FIELDS_DO(FIELD_COMPUTE_OFFSET); -} - -#if INCLUDE_CDS -void java_security_AccessControlContext::serialize_offsets(SerializeClosure* f) { - ACCESSCONTROLCONTEXT_FIELDS_DO(FIELD_SERIALIZE_OFFSET); -} -#endif - -oop java_security_AccessControlContext::create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS) { - assert(_isPrivileged_offset != 0, "offsets should have been initialized"); - assert(_isAuthorized_offset != 0, "offsets should have been initialized"); - // Ensure klass is initialized - vmClasses::AccessControlContext_klass()->initialize(CHECK_NULL); - // Allocate result - oop result = vmClasses::AccessControlContext_klass()->allocate_instance(CHECK_NULL); - // Fill in values - result->obj_field_put(_context_offset, context()); - result->obj_field_put(_privilegedContext_offset, privileged_context()); - result->bool_field_put(_isPrivileged_offset, isPrivileged); - result->bool_field_put(_isAuthorized_offset, true); - return result; -} - - // Support for java_lang_ClassLoader int java_lang_ClassLoader::_loader_data_offset; @@ -4860,17 +4876,6 @@ void java_lang_System::compute_offsets() { SYSTEM_FIELDS_DO(FIELD_COMPUTE_OFFSET); } -// This field tells us that a security manager can never be installed so we -// can completely skip populating the ProtectionDomainCacheTable. -bool java_lang_System::allow_security_manager() { - return false; -} - -// This field tells us that a security manager is installed. -bool java_lang_System::has_security_manager() { - return false; -} - #if INCLUDE_CDS void java_lang_System::serialize_offsets(SerializeClosure* f) { SYSTEM_FIELDS_DO(FIELD_SERIALIZE_OFFSET); @@ -5385,7 +5390,6 @@ void java_lang_InternalError::serialize_offsets(SerializeClosure* f) { f(java_lang_invoke_CallSite) \ f(java_lang_invoke_ConstantCallSite) \ f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \ - f(java_security_AccessControlContext) \ f(java_lang_reflect_AccessibleObject) \ f(java_lang_reflect_Method) \ f(java_lang_reflect_Constructor) \ @@ -5448,20 +5452,18 @@ void JavaClasses::serialize_offsets(SerializeClosure* soc) { bool JavaClasses::is_supported_for_archiving(oop obj) { Klass* klass = obj->klass(); - if (klass == vmClasses::ClassLoader_klass() || // ClassLoader::loader_data is malloc'ed. - // The next 3 classes are used to implement java.lang.invoke, and are not used directly in - // regular Java code. The implementation of java.lang.invoke uses generated hidden classes - // (e.g., as referenced by ResolvedMethodName::vmholder) that are not yet supported by CDS. - // So for now we cannot not support these classes for archiving. - // - // These objects typically are not referenced by static fields, but rather by resolved - // constant pool entries, so excluding them shouldn't affect the archiving of static fields. - klass == vmClasses::ResolvedMethodName_klass() || - klass == vmClasses::MemberName_klass() || - klass == vmClasses::Context_klass() || - // It's problematic to archive Reference objects. One of the reasons is that - // Reference::discovered may pull in unwanted objects (see JDK-8284336) - klass->is_subclass_of(vmClasses::Reference_klass())) { + if (!CDSConfig::is_dumping_invokedynamic()) { + // These are supported by CDS only when CDSConfig::is_dumping_invokedynamic() is enabled. + if (klass == vmClasses::ResolvedMethodName_klass() || + klass == vmClasses::MemberName_klass() || + klass == vmClasses::Context_klass()) { + return false; + } + } + + if (klass->is_subclass_of(vmClasses::Reference_klass())) { + // It's problematic to archive Reference objects. One of the reasons is that + // Reference::discovered may pull in unwanted objects (see JDK-8284336) return false; } diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index e0123595810..0d0fa5954b1 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -32,11 +32,14 @@ #include "runtime/handles.hpp" #include "runtime/os.hpp" #include "utilities/macros.hpp" +#include "utilities/utf8.hpp" #include "utilities/vmEnums.hpp" class JvmtiThreadState; class RecordComponent; class SerializeClosure; +class ObjectWaiter; +class ObjectMonitor; #define CHECK_INIT(offset) assert(offset != 0, "should be initialized"); return offset; @@ -99,7 +102,7 @@ class java_lang_String : AllStatic { static oop create_oop_from_unicode(const jchar* unicode, int len, TRAPS); static Handle create_from_str(const char* utf8_str, TRAPS); static oop create_oop_from_str(const char* utf8_str, TRAPS); - static Handle create_from_symbol(Symbol* symbol, TRAPS); + static Handle create_from_symbol(const Symbol* symbol, TRAPS); static Handle create_from_platform_dependent_str(const char* str, TRAPS); static void set_compact_strings(bool value); @@ -180,10 +183,24 @@ class java_lang_String : AllStatic { return h; } + static unsigned int hash_code(const char* utf8_str, size_t utf8_len) { + unsigned int h = 0; + int unicode_length = UTF8::unicode_length(utf8_str, utf8_len); + + jchar c; + while (unicode_length-- > 0) { + utf8_str = UTF8::next(utf8_str, &c); + h = 31 * h + ((unsigned int)c); + } + return h; + } + static unsigned int hash_code(oop java_string); static unsigned int hash_code_noupdate(oop java_string); + // Compare strings (of different types/encodings), length is the string (array) length static bool equals(oop java_string, const jchar* chars, int len); + static bool equals(oop java_string, const char* utf8_str, size_t utf8_len); static bool equals(oop str1, oop str2); static inline bool value_equals(typeArrayOop str_value1, typeArrayOop str_value2); @@ -239,6 +256,7 @@ class java_lang_Class : AllStatic { static int _source_file_offset; static int _classData_offset; static int _classRedefinedCount_offset; + static int _reflectionData_offset; static bool _offsets_computed; @@ -306,6 +324,7 @@ class java_lang_Class : AllStatic { static objArrayOop signers(oop java_class); static oop class_data(oop java_class); static void set_class_data(oop java_class, oop classData); + static void set_reflection_data(oop java_class, oop reflection_data); static int component_mirror_offset() { return _component_mirror_offset; } @@ -520,6 +539,8 @@ class java_lang_ThreadGroup : AllStatic { // Interface to java.lang.VirtualThread objects +#define VTHREAD_INJECTED_FIELDS(macro) \ + macro(java_lang_VirtualThread, objectWaiter, intptr_signature, false) class java_lang_VirtualThread : AllStatic { private: @@ -532,6 +553,7 @@ class java_lang_VirtualThread : AllStatic { static int _notified_offset; static int _recheckInterval_offset; static int _timeout_offset; + static int _objectWaiter_offset; JFR_ONLY(static int _jfr_epoch_offset;) public: enum { @@ -583,6 +605,11 @@ class java_lang_VirtualThread : AllStatic { static void set_notified(oop vthread, jboolean value); static bool is_preempted(oop vthread); static JavaThreadStatus map_state_to_thread_status(int state); + + static inline ObjectWaiter* objectWaiter(oop vthread); + static inline void set_objectWaiter(oop vthread, ObjectWaiter* waiter); + static ObjectMonitor* current_pending_monitor(oop vthread); + static ObjectMonitor* current_waiting_monitor(oop vthread); }; @@ -1463,27 +1490,6 @@ class java_lang_invoke_MethodHandleNatives_CallSiteContext : AllStatic { static bool is_instance(oop obj); }; -// Interface to java.security.AccessControlContext objects - -class java_security_AccessControlContext: AllStatic { - private: - // Note that for this class the layout changed between JDK1.2 and JDK1.3, - // so we compute the offsets at startup rather than hard-wiring them. - static int _context_offset; - static int _privilegedContext_offset; - static int _isPrivileged_offset; - static int _isAuthorized_offset; - - static void compute_offsets(); - public: - static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; - static oop create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS); - - // Debugging/initialization - friend class JavaClasses; -}; - - // Interface to java.lang.ClassLoader objects #define CLASSLOADER_INJECTED_FIELDS(macro) \ @@ -1540,16 +1546,11 @@ class java_lang_System : AllStatic { static int _static_in_offset; static int _static_out_offset; static int _static_err_offset; - static int _static_security_offset; - static int _static_allow_security_offset; - static int _static_never_offset; public: static int in_offset() { CHECK_INIT(_static_in_offset); } static int out_offset() { CHECK_INIT(_static_out_offset); } static int err_offset() { CHECK_INIT(_static_err_offset); } - static bool allow_security_manager(); - static bool has_security_manager(); static void compute_offsets(); static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; diff --git a/src/hotspot/share/classfile/javaClasses.inline.hpp b/src/hotspot/share/classfile/javaClasses.inline.hpp index 0476f0185ca..f27f1feba6d 100644 --- a/src/hotspot/share/classfile/javaClasses.inline.hpp +++ b/src/hotspot/share/classfile/javaClasses.inline.hpp @@ -220,6 +220,14 @@ inline oop java_lang_VirtualThread::vthread_scope() { return base->obj_field(static_vthread_scope_offset); } +inline ObjectWaiter* java_lang_VirtualThread::objectWaiter(oop vthread) { + return (ObjectWaiter*)vthread->address_field(_objectWaiter_offset); +} + +inline void java_lang_VirtualThread::set_objectWaiter(oop vthread, ObjectWaiter* value) { + vthread->address_field_put(_objectWaiter_offset, (address)value); +} + #if INCLUDE_JFR inline u2 java_lang_Thread::jfr_epoch(oop ref) { return ref->short_field(_jfr_epoch_offset); diff --git a/src/hotspot/share/classfile/javaClassesImpl.hpp b/src/hotspot/share/classfile/javaClassesImpl.hpp index 618189aa0f1..235334a388b 100644 --- a/src/hotspot/share/classfile/javaClassesImpl.hpp +++ b/src/hotspot/share/classfile/javaClassesImpl.hpp @@ -40,6 +40,7 @@ STACKFRAMEINFO_INJECTED_FIELDS(macro) \ MODULE_INJECTED_FIELDS(macro) \ THREAD_INJECTED_FIELDS(macro) \ + VTHREAD_INJECTED_FIELDS(macro) \ INTERNALERROR_INJECTED_FIELDS(macro) \ STACKCHUNK_INJECTED_FIELDS(macro) diff --git a/src/hotspot/share/classfile/klassFactory.cpp b/src/hotspot/share/classfile/klassFactory.cpp index cfcf7d9ea32..493fc27dd43 100644 --- a/src/hotspot/share/classfile/klassFactory.cpp +++ b/src/hotspot/share/classfile/klassFactory.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 2024, 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 @@ -77,8 +77,7 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook( s2 path_index = ik->shared_classpath_index(); ClassFileStream* stream = new ClassFileStream(ptr, pointer_delta_as_int(end_ptr, ptr), - cfs->source(), - ClassFileStream::verify); + cfs->source()); ClassLoadInfo cl_info(protection_domain); ClassFileParser parser(stream, class_name, @@ -157,8 +156,7 @@ static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream, // Set new class file stream using JVMTI agent modified class file data. stream = new ClassFileStream(ptr, pointer_delta_as_int(end_ptr, ptr), - stream->source(), - stream->need_verify()); + stream->source()); } } diff --git a/src/hotspot/share/classfile/protectionDomainCache.cpp b/src/hotspot/share/classfile/protectionDomainCache.cpp deleted file mode 100644 index d6c83253ee7..00000000000 --- a/src/hotspot/share/classfile/protectionDomainCache.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2017, 2024, 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 "classfile/classLoaderDataGraph.hpp" -#include "classfile/dictionary.hpp" -#include "classfile/javaClasses.hpp" -#include "classfile/protectionDomainCache.hpp" -#include "logging/log.hpp" -#include "logging/logStream.hpp" -#include "memory/iterator.hpp" -#include "memory/resourceArea.hpp" -#include "memory/universe.hpp" -#include "oops/oop.inline.hpp" -#include "oops/weakHandle.inline.hpp" -#include "runtime/atomic.hpp" -#include "runtime/mutexLocker.hpp" -#include "utilities/growableArray.hpp" -#include "utilities/resourceHash.hpp" - -unsigned int ProtectionDomainCacheTable::compute_hash(const WeakHandle& protection_domain) { - // The protection domain in the hash computation is passed from a Handle so cannot resolve to null. - assert(protection_domain.peek() != nullptr, "Must be live"); - return (unsigned int)(protection_domain.resolve()->identity_hash()); -} - -bool ProtectionDomainCacheTable::equals(const WeakHandle& protection_domain1, const WeakHandle& protection_domain2) { - return protection_domain1.peek() == protection_domain2.peek(); -} - -// WeakHandle is both the key and the value. We need it as the key to compare the oops that each point to -// for equality. We need it as the value to return the one that already exists to link in the DictionaryEntry. -using InternalProtectionDomainCacheTable = ResourceHashtable; -static InternalProtectionDomainCacheTable* _pd_cache_table; - -bool ProtectionDomainCacheTable::_dead_entries = false; -int ProtectionDomainCacheTable::_total_oops_removed = 0; - -void ProtectionDomainCacheTable::initialize(){ - _pd_cache_table = new (mtClass) InternalProtectionDomainCacheTable(); -} -void ProtectionDomainCacheTable::trigger_cleanup() { - MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); - _dead_entries = true; - Service_lock->notify_all(); -} - -class CleanProtectionDomainEntries : public CLDClosure { - GrowableArray* _delete_list; - public: - CleanProtectionDomainEntries(GrowableArray* delete_list) : - _delete_list(delete_list) {} - - void do_cld(ClassLoaderData* data) { - Dictionary* dictionary = data->dictionary(); - if (dictionary != nullptr) { - dictionary->remove_from_package_access_cache(_delete_list); - } - } -}; - -static GrowableArray* _delete_list = nullptr; - -class HandshakeForPD : public HandshakeClosure { - public: - HandshakeForPD() : HandshakeClosure("HandshakeForPD") {} - - void do_thread(Thread* thread) { - log_trace(protectiondomain)("HandshakeForPD::do_thread: thread=" - INTPTR_FORMAT, p2i(thread)); - } -}; - -static void purge_deleted_entries() { - // If there are any deleted entries, Handshake-all then they'll be - // safe to remove since traversing the package_access_cache list does not stop for - // safepoints and only JavaThreads will read the package_access_cache. - // This is actually quite rare because the protection domain is generally associated - // with the caller class and class loader, which if still alive will keep this - // protection domain entry alive. - if (_delete_list->length() >= 10) { - HandshakeForPD hs_pd; - Handshake::execute(&hs_pd); - - for (int i = _delete_list->length() - 1; i >= 0; i--) { - ProtectionDomainEntry* entry = _delete_list->at(i); - _delete_list->remove_at(i); - delete entry; - } - assert(_delete_list->length() == 0, "should be cleared"); - } -} - -void ProtectionDomainCacheTable::unlink() { - // DictionaryEntry::_package_access_cache should be null also, so nothing to do. - assert(java_lang_System::allow_security_manager(), "should not be called otherwise"); - - // Create a list for holding deleted entries - if (_delete_list == nullptr) { - _delete_list = new (mtClass) - GrowableArray(20, mtClass); - } - - { - // First clean cached pd lists in loaded CLDs - // It's unlikely, but some loaded classes in a dictionary might - // point to a protection_domain that has been unloaded. - // DictionaryEntry::_package_access_cache points at entries in the ProtectionDomainCacheTable. - MutexLocker ml(ClassLoaderDataGraph_lock); - MutexLocker mldict(SystemDictionary_lock); // need both. - CleanProtectionDomainEntries clean(_delete_list); - ClassLoaderDataGraph::loaded_cld_do(&clean); - } - - // Purge any deleted entries outside of the SystemDictionary_lock. - purge_deleted_entries(); - - // Reacquire the lock to remove entries from the hashtable. - MutexLocker ml(SystemDictionary_lock); - - struct Deleter { - int _oops_removed; - Deleter() : _oops_removed(0) {} - - bool do_entry(WeakHandle& key, WeakHandle& value) { - oop pd = value.peek(); - if (value.peek() == nullptr) { - _oops_removed++; - LogTarget(Debug, protectiondomain, table) lt; - if (lt.is_enabled()) { - LogStream ls(lt); - ls.print_cr("protection domain unlinked %d", _oops_removed); - } - value.release(Universe::vm_weak()); - return true; - } else { - return false; - } - } - }; - - Deleter deleter; - _pd_cache_table->unlink(&deleter); - - _total_oops_removed += deleter._oops_removed; - _dead_entries = false; -} - -void ProtectionDomainCacheTable::print_on(outputStream* st) { - assert_locked_or_safepoint(SystemDictionary_lock); - auto printer = [&] (WeakHandle& key, WeakHandle& value) { - st->print_cr(" protection_domain: " PTR_FORMAT, p2i(value.peek())); - }; - st->print_cr("Protection domain cache table (table_size=%d, protection domains=%d)", - _pd_cache_table->table_size(), _pd_cache_table->number_of_entries()); - _pd_cache_table->iterate_all(printer); -} - -void ProtectionDomainCacheTable::verify() { - auto verifier = [&] (WeakHandle& key, WeakHandle& value) { - guarantee(value.peek() == nullptr || oopDesc::is_oop(value.peek()), "must be an oop"); - }; - _pd_cache_table->iterate_all(verifier); -} - -// The object_no_keepalive() call peeks at the phantomly reachable oop without -// keeping it alive. This is used for traversing DictionaryEntry::_package_access_cache. -oop ProtectionDomainEntry::object_no_keepalive() { - return _object.peek(); -} - -WeakHandle ProtectionDomainCacheTable::add_if_absent(Handle protection_domain) { - assert_locked_or_safepoint(SystemDictionary_lock); - WeakHandle w(Universe::vm_weak(), protection_domain); - bool created; - WeakHandle* wk = _pd_cache_table->put_if_absent(w, w, &created); - if (!created) { - // delete the one created since we already had it in the table - w.release(Universe::vm_weak()); - } else { - LogTarget(Debug, protectiondomain, table) lt; - if (lt.is_enabled()) { - LogStream ls(lt); - ls.print("protection domain added "); - protection_domain->print_value_on(&ls); - ls.cr(); - } - } - // Keep entry alive - (void)wk->resolve(); - return *wk; -} - -void ProtectionDomainCacheTable::print_table_statistics(outputStream* st) { - auto size = [&] (WeakHandle& key, WeakHandle& value) { - // The only storage is in OopStorage for an oop - return sizeof(oop); - }; - TableStatistics ts = _pd_cache_table->statistics_calculate(size); - ts.print(st, "ProtectionDomainCacheTable"); -} - -int ProtectionDomainCacheTable::number_of_entries() { - return _pd_cache_table->number_of_entries(); -} diff --git a/src/hotspot/share/classfile/protectionDomainCache.hpp b/src/hotspot/share/classfile/protectionDomainCache.hpp deleted file mode 100644 index 8ba69d9ab66..00000000000 --- a/src/hotspot/share/classfile/protectionDomainCache.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2017, 2024, 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_CLASSFILE_PROTECTIONDOMAINCACHE_HPP -#define SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP - -#include "oops/oop.hpp" -#include "oops/weakHandle.hpp" -#include "runtime/atomic.hpp" - -// The ProtectionDomainCacheTable maps all java.security.ProtectionDomain objects that are -// registered by DictionaryEntry::add_to_package_access_cache() to a unique WeakHandle. -// The amount of different protection domains used is typically magnitudes smaller -// than the number of system dictionary entries (loaded classes). -class ProtectionDomainCacheTable : public AllStatic { - - static bool _dead_entries; - static int _total_oops_removed; - -public: - static void initialize(); - static unsigned int compute_hash(const WeakHandle& protection_domain); - static bool equals(const WeakHandle& protection_domain1, const WeakHandle& protection_domain2); - - static WeakHandle add_if_absent(Handle protection_domain); - static void unlink(); - - static void print_on(outputStream* st); - static void verify(); - - static bool has_work() { return _dead_entries; } - static void trigger_cleanup(); - - static int removed_entries_count() { return _total_oops_removed; }; - static int number_of_entries(); - static void print_table_statistics(outputStream* st); -}; - - -// This describes the linked list protection domain for each DictionaryEntry in its package_access_cache. -class ProtectionDomainEntry :public CHeapObj { - WeakHandle _object; - ProtectionDomainEntry* volatile _next; - public: - - ProtectionDomainEntry(WeakHandle obj, - ProtectionDomainEntry* head) : _object(obj), _next(head) {} - - ProtectionDomainEntry* next_acquire() { return Atomic::load_acquire(&_next); } - void release_set_next(ProtectionDomainEntry* entry) { Atomic::release_store(&_next, entry); } - oop object_no_keepalive(); -}; -#endif // SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index 3a6cf166ff5..4de4b8e333c 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -99,9 +99,9 @@ inline oop StringTable::read_string_from_compact_hashtable(address base_address, } typedef CompactHashtable< - const jchar*, oop, + const StringTable::StringWrapper&, oop, StringTable::read_string_from_compact_hashtable, - java_lang_String::equals> SharedStringTable; + StringTable::wrapped_string_equals> SharedStringTable; static SharedStringTable _shared_table; #endif @@ -123,12 +123,69 @@ volatile bool _alt_hash = false; static bool _rehashed = false; static uint64_t _alt_hash_seed = 0; +enum class StringType { + OopStr, UnicodeStr, SymbolStr, UTF8Str +}; + +struct StringWrapperInternal { + union { + const Handle oop_str; + const jchar* unicode_str; + const Symbol* symbol_str; + const char* utf8_str; + }; + const StringType type; + const size_t length; + + StringWrapperInternal(const Handle oop_str, const size_t length) : oop_str(oop_str), type(StringType::OopStr), length(length) {} + StringWrapperInternal(const jchar* unicode_str, const size_t length) : unicode_str(unicode_str), type(StringType::UnicodeStr), length(length) {} + StringWrapperInternal(const Symbol* symbol_str, const size_t length) : symbol_str(symbol_str), type(StringType::SymbolStr), length(length) {} + StringWrapperInternal(const char* utf8_str, const size_t length) : utf8_str(utf8_str), type(StringType::UTF8Str), length(length) {} +}; + static unsigned int hash_string(const jchar* s, int len, bool useAlt) { return useAlt ? AltHashing::halfsiphash_32(_alt_hash_seed, s, len) : java_lang_String::hash_code(s, len); } +const char* StringTable::get_symbol_utf8(const StringWrapper& symbol) { + return reinterpret_cast(symbol.symbol_str->bytes()); +} + +unsigned int StringTable::hash_wrapped_string(const StringWrapper& wrapped_str) { + switch (wrapped_str.type) { + case StringType::OopStr: + return java_lang_String::hash_code(wrapped_str.oop_str()); + case StringType::UnicodeStr: + return java_lang_String::hash_code(wrapped_str.unicode_str, static_cast(wrapped_str.length)); + case StringType::SymbolStr: + return java_lang_String::hash_code(get_symbol_utf8(wrapped_str), wrapped_str.length); + case StringType::UTF8Str: + return java_lang_String::hash_code(wrapped_str.utf8_str, wrapped_str.length); + default: + ShouldNotReachHere(); + } + return 0; +} + +// Unnamed int needed to fit CompactHashtable's equals type signature +bool StringTable::wrapped_string_equals(oop java_string, const StringWrapper& wrapped_str, int) { + switch (wrapped_str.type) { + case StringType::OopStr: + return java_lang_String::equals(java_string, wrapped_str.oop_str()); + case StringType::UnicodeStr: + return java_lang_String::equals(java_string, wrapped_str.unicode_str, static_cast(wrapped_str.length)); + case StringType::SymbolStr: + return java_lang_String::equals(java_string, get_symbol_utf8(wrapped_str), wrapped_str.length); + case StringType::UTF8Str: + return java_lang_String::equals(java_string, wrapped_str.utf8_str, wrapped_str.length); + default: + ShouldNotReachHere(); + } + return false; +} + class StringTableConfig : public StackObj { private: public: @@ -163,22 +220,33 @@ class StringTableConfig : public StackObj { } }; -class StringTableLookupJchar : StackObj { - private: - Thread* _thread; +class StringTableLookup : StackObj { uintx _hash; - int _len; - const jchar* _str; + +protected: + Thread* _thread; Handle _found; - public: - StringTableLookupJchar(Thread* thread, uintx hash, const jchar* key, int len) - : _thread(thread), _hash(hash), _len(len), _str(key) { - } - uintx get_hash() const { - return _hash; +public: + StringTableLookup(Thread* thread, uintx hash) + : _hash(hash), _thread(thread) {} + uintx get_hash() const { return _hash; } + bool is_dead(WeakHandle* value) { + oop val_oop = value->peek(); + return val_oop == nullptr; } - bool equals(WeakHandle* value) { +}; + +class StringTableLookupUnicode : public StringTableLookup { +private: + const jchar* _str; + int _len; + +public: + StringTableLookupUnicode(Thread* thread, uintx hash, const jchar* key, int len) + : StringTableLookup(thread, hash), _str(key), _len(len) {} + + bool equals(const WeakHandle* value) { oop val_oop = value->peek(); if (val_oop == nullptr) { return false; @@ -188,29 +256,42 @@ class StringTableLookupJchar : StackObj { return false; } // Need to resolve weak handle and Handleize through possible safepoint. - _found = Handle(_thread, value->resolve()); + _found = Handle(_thread, value->resolve()); return true; } - bool is_dead(WeakHandle* value) { +}; + +class StringTableLookupUTF8 : public StringTableLookup { +private: + const char* _str; + size_t _utf8_len; + +public: + StringTableLookupUTF8(Thread* thread, uintx hash, const char* key, size_t utf8_len) + : StringTableLookup(thread, hash), _str(key), _utf8_len(utf8_len) {} + + bool equals(const WeakHandle* value) { oop val_oop = value->peek(); - return val_oop == nullptr; + if (val_oop == nullptr) { + return false; + } + bool equals = java_lang_String::equals(val_oop, _str, _utf8_len); + if (!equals) { + return false; + } + // Need to resolve weak handle and Handleize through possible safepoint. + _found = Handle(_thread, value->resolve()); + return true; } }; -class StringTableLookupOop : public StackObj { - private: - Thread* _thread; - uintx _hash; +class StringTableLookupOop : public StringTableLookup { +private: Handle _find; - Handle _found; // Might be a different oop with the same value that's already - // in the table, which is the point. - public: - StringTableLookupOop(Thread* thread, uintx hash, Handle handle) - : _thread(thread), _hash(hash), _find(handle) { } - uintx get_hash() const { - return _hash; - } +public: + StringTableLookupOop(Thread* thread, uintx hash, Handle handle) + : StringTableLookup(thread, hash), _find(handle) {} bool equals(WeakHandle* value) { oop val_oop = value->peek(); @@ -225,11 +306,6 @@ class StringTableLookupOop : public StackObj { _found = Handle(_thread, value->resolve()); return true; } - - bool is_dead(WeakHandle* value) { - oop val_oop = value->peek(); - return val_oop == nullptr; - } }; void StringTable::create_table() { @@ -291,14 +367,15 @@ oop StringTable::lookup(Symbol* symbol) { oop StringTable::lookup(const jchar* name, int len) { unsigned int hash = java_lang_String::hash_code(name, len); - oop string = lookup_shared(name, len, hash); + StringWrapper wrapped_name(name, len); + oop string = lookup_shared(wrapped_name, hash); if (string != nullptr) { return string; } if (_alt_hash) { hash = hash_string(name, len, true); } - return do_lookup(name, len, hash); + return do_lookup(wrapped_name, hash); } class StringTableGet : public StackObj { @@ -323,80 +400,140 @@ void StringTable::update_needs_rehash(bool rehash) { } } -oop StringTable::do_lookup(const jchar* name, int len, uintx hash) { +oop StringTable::do_lookup(const StringWrapper& name, uintx hash) { Thread* thread = Thread::current(); - StringTableLookupJchar lookup(thread, hash, name, len); StringTableGet stg(thread); bool rehash_warning; - _local_table->get(thread, lookup, stg, &rehash_warning); + + switch (name.type) { + case StringType::OopStr: { + StringTableLookupOop lookup(thread, hash, name.oop_str); + _local_table->get(thread, lookup, stg, &rehash_warning); + break; + } + case StringType::UnicodeStr: { + StringTableLookupUnicode lookup(thread, hash, name.unicode_str, static_cast(name.length)); + _local_table->get(thread, lookup, stg, &rehash_warning); + break; + } + case StringType::SymbolStr: { + StringTableLookupUTF8 lookup(thread, hash, get_symbol_utf8(name), name.length); + _local_table->get(thread, lookup, stg, &rehash_warning); + break; + } + case StringType::UTF8Str: { + StringTableLookupUTF8 lookup(thread, hash, name.utf8_str, name.length); + _local_table->get(thread, lookup, stg, &rehash_warning); + break; + } + default: + ShouldNotReachHere(); + } + update_needs_rehash(rehash_warning); return stg.get_res_oop(); } +// Converts and allocates to a unicode string and stores the unicode length in len +const jchar* StringTable::to_unicode(const StringWrapper& wrapped_str, int &len, TRAPS) { + switch (wrapped_str.type) { + case StringType::UnicodeStr: + len = static_cast(wrapped_str.length); + return wrapped_str.unicode_str; + case StringType::OopStr: + return java_lang_String::as_unicode_string(wrapped_str.oop_str(), len, CHECK_NULL); + case StringType::SymbolStr: { + const char* utf8_str = get_symbol_utf8(wrapped_str); + int unicode_length = UTF8::unicode_length(utf8_str, wrapped_str.symbol_str->utf8_length()); + jchar* chars = NEW_RESOURCE_ARRAY(jchar, unicode_length); + UTF8::convert_to_unicode(utf8_str, chars, unicode_length); + len = unicode_length; + return chars; + } + case StringType::UTF8Str: { + int unicode_length = UTF8::unicode_length(wrapped_str.utf8_str); + jchar* chars = NEW_RESOURCE_ARRAY(jchar, unicode_length); + UTF8::convert_to_unicode(wrapped_str.utf8_str, chars, unicode_length); + len = unicode_length; + return chars; + } + default: + ShouldNotReachHere(); + } + return nullptr; +} + +Handle StringTable::handle_from_wrapped_string(const StringWrapper& wrapped_str, TRAPS) { + switch (wrapped_str.type) { + case StringType::OopStr: + return wrapped_str.oop_str; + case StringType::UnicodeStr: + return java_lang_String::create_from_unicode(wrapped_str.unicode_str, static_cast(wrapped_str.length), THREAD); + case StringType::SymbolStr: + return java_lang_String::create_from_symbol(wrapped_str.symbol_str, THREAD); + case StringType::UTF8Str: + return java_lang_String::create_from_str(wrapped_str.utf8_str, THREAD); + default: + ShouldNotReachHere(); + } + return Handle(); +} + // Interning oop StringTable::intern(Symbol* symbol, TRAPS) { if (symbol == nullptr) return nullptr; - ResourceMark rm(THREAD); - int length; - jchar* chars = symbol->as_unicode(length); - Handle string; - oop result = intern(string, chars, length, CHECK_NULL); + int length = symbol->utf8_length(); + StringWrapper name(symbol, length); + oop result = intern(name, CHECK_NULL); return result; } oop StringTable::intern(oop string, TRAPS) { if (string == nullptr) return nullptr; - ResourceMark rm(THREAD); - int length; + int length = java_lang_String::length(string); Handle h_string (THREAD, string); - jchar* chars = java_lang_String::as_unicode_string(string, length, - CHECK_NULL); - oop result = intern(h_string, chars, length, CHECK_NULL); + StringWrapper name(h_string, length); + oop result = intern(name, CHECK_NULL); return result; } oop StringTable::intern(const char* utf8_string, TRAPS) { if (utf8_string == nullptr) return nullptr; - ResourceMark rm(THREAD); - int length = UTF8::unicode_length(utf8_string); - jchar* chars = NEW_RESOURCE_ARRAY(jchar, length); - UTF8::convert_to_unicode(utf8_string, chars, length); - Handle string; - oop result = intern(string, chars, length, CHECK_NULL); + size_t length = strlen(utf8_string); + StringWrapper name(utf8_string, length); + oop result = intern(name, CHECK_NULL); return result; } -oop StringTable::intern(Handle string_or_null_h, const jchar* name, int len, TRAPS) { +oop StringTable::intern(const StringWrapper& name, TRAPS) { // shared table always uses java_lang_String::hash_code - unsigned int hash = java_lang_String::hash_code(name, len); - oop found_string = lookup_shared(name, len, hash); + unsigned int hash = hash_wrapped_string(name); + oop found_string = lookup_shared(name, hash); if (found_string != nullptr) { return found_string; } + if (_alt_hash) { - hash = hash_string(name, len, true); + ResourceMark rm(THREAD); + // Convert to unicode for alt hashing + int unicode_length; + const jchar* chars = to_unicode(name, unicode_length, CHECK_NULL); + hash = hash_string(chars, unicode_length, true); } - found_string = do_lookup(name, len, hash); + + found_string = do_lookup(name, hash); if (found_string != nullptr) { return found_string; } - return do_intern(string_or_null_h, name, len, hash, THREAD); + return do_intern(name, hash, THREAD); } -oop StringTable::do_intern(Handle string_or_null_h, const jchar* name, - int len, uintx hash, TRAPS) { +oop StringTable::do_intern(const StringWrapper& name, uintx hash, TRAPS) { HandleMark hm(THREAD); // cleanup strings created - Handle string_h; - - if (!string_or_null_h.is_null()) { - string_h = string_or_null_h; - } else { - string_h = java_lang_String::create_from_unicode(name, len, CHECK_NULL); - } + Handle string_h = handle_from_wrapped_string(name, CHECK_NULL); - assert(java_lang_String::equals(string_h(), name, len), + assert(StringTable::wrapped_string_equals(string_h(), name), "string must be properly initialized"); - assert(len == java_lang_String::length(string_h()), "Must be same length"); // Notify deduplication support that the string is being interned. A string // must never be deduplicated after it has been interned. Doing so interferes @@ -410,7 +547,7 @@ oop StringTable::do_intern(Handle string_or_null_h, const jchar* name, bool rehash_warning; do { - // Callers have already looked up the String using the jchar* name, so just go to add. + // Callers have already looked up the String, so just go to add. WeakHandle wh(_oop_storage, string_h); // The hash table takes ownership of the WeakHandle, even if it's not inserted. if (_local_table->insert(THREAD, lookup, wh, &rehash_warning)) { @@ -775,14 +912,17 @@ size_t StringTable::shared_entry_count() { return _shared_table.entry_count(); } -oop StringTable::lookup_shared(const jchar* name, int len, unsigned int hash) { - assert(hash == java_lang_String::hash_code(name, len), +oop StringTable::lookup_shared(const StringWrapper& name, unsigned int hash) { + assert(hash == hash_wrapped_string(name), "hash must be computed using java_lang_String::hash_code"); - return _shared_table.lookup(name, hash, len); + // len is required but is already part of StringWrapper, so 0 is used + return _shared_table.lookup(name, hash, 0); } oop StringTable::lookup_shared(const jchar* name, int len) { - return _shared_table.lookup(name, java_lang_String::hash_code(name, len), len); + StringWrapper wrapped_name(name, len); + // len is required but is already part of StringWrapper, so 0 is used + return _shared_table.lookup(wrapped_name, java_lang_String::hash_code(name, len), 0); } // This is called BEFORE we enter the CDS safepoint. We can allocate heap objects. diff --git a/src/hotspot/share/classfile/stringTable.hpp b/src/hotspot/share/classfile/stringTable.hpp index 9f49e797182..38abb9c875c 100644 --- a/src/hotspot/share/classfile/stringTable.hpp +++ b/src/hotspot/share/classfile/stringTable.hpp @@ -56,6 +56,18 @@ class StringTable : AllStatic { static double get_load_factor(); static double get_dead_factor(size_t num_dead); +public: + typedef struct StringWrapperInternal StringWrapper; + + // Unnamed int needed to fit CompactHashtable's equals type signature + static bool wrapped_string_equals(oop java_string, const StringWrapper& wrapped_str, int = 0); + +private: + static const char* get_symbol_utf8(const StringWrapper& symbol_str); + static unsigned int hash_wrapped_string(const StringWrapper& wrapped_str); + static const jchar* to_unicode(const StringWrapper& wrapped_str, int &len, TRAPS); + static Handle handle_from_wrapped_string(const StringWrapper& wrapped_str, TRAPS); + // GC support // Callback for GC to notify of changes that might require cleaning or resize. @@ -65,9 +77,9 @@ class StringTable : AllStatic { static void item_added(); static void item_removed(); - static oop intern(Handle string_or_null_h, const jchar* name, int len, TRAPS); - static oop do_intern(Handle string_or_null, const jchar* name, int len, uintx hash, TRAPS); - static oop do_lookup(const jchar* name, int len, uintx hash); + static oop intern(const StringWrapper& name, TRAPS); + static oop do_intern(const StringWrapper& name, uintx hash, TRAPS); + static oop do_lookup(const StringWrapper& name, uintx hash); static void print_table_statistics(outputStream* st); @@ -87,7 +99,7 @@ class StringTable : AllStatic { // Interning static oop intern(Symbol* symbol, TRAPS); static oop intern(oop string, TRAPS); - static oop intern(const char *utf8_string, TRAPS); + static oop intern(const char* utf8_string, TRAPS); // Rehash the string table if it gets out of balance private: @@ -131,7 +143,7 @@ class StringTable : AllStatic { #endif // INCLUDE_CDS_JAVA_HEAP private: - static oop lookup_shared(const jchar* name, int len, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(nullptr); + static oop lookup_shared(const StringWrapper& name, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(nullptr); public: static oop lookup_shared(const jchar* name, int len) NOT_CDS_JAVA_HEAP_RETURN_(nullptr); static size_t shared_entry_count() NOT_CDS_JAVA_HEAP_RETURN_(0); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 2338a179324..0cd9886bd01 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -38,7 +38,6 @@ #include "classfile/loaderConstraints.hpp" #include "classfile/packageEntry.hpp" #include "classfile/placeholders.hpp" -#include "classfile/protectionDomainCache.hpp" #include "classfile/resolutionErrors.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" @@ -82,6 +81,7 @@ #include "services/diagnosticCommand.hpp" #include "services/finalizerService.hpp" #include "services/threadService.hpp" +#include "utilities/growableArray.hpp" #include "utilities/macros.hpp" #include "utilities/utf8.hpp" #if INCLUDE_CDS @@ -134,29 +134,29 @@ oop SystemDictionary::java_platform_loader() { } void SystemDictionary::compute_java_loaders(TRAPS) { - if (_java_system_loader.is_empty()) { - oop system_loader = get_system_class_loader_impl(CHECK); - _java_system_loader = OopHandle(Universe::vm_global(), system_loader); + if (_java_platform_loader.is_empty()) { + oop platform_loader = get_platform_class_loader_impl(CHECK); + _java_platform_loader = OopHandle(Universe::vm_global(), platform_loader); } else { // It must have been restored from the archived module graph assert(CDSConfig::is_using_archive(), "must be"); assert(CDSConfig::is_using_full_module_graph(), "must be"); DEBUG_ONLY( - oop system_loader = get_system_class_loader_impl(CHECK); - assert(_java_system_loader.resolve() == system_loader, "must be"); + oop platform_loader = get_platform_class_loader_impl(CHECK); + assert(_java_platform_loader.resolve() == platform_loader, "must be"); ) } - if (_java_platform_loader.is_empty()) { - oop platform_loader = get_platform_class_loader_impl(CHECK); - _java_platform_loader = OopHandle(Universe::vm_global(), platform_loader); + if (_java_system_loader.is_empty()) { + oop system_loader = get_system_class_loader_impl(CHECK); + _java_system_loader = OopHandle(Universe::vm_global(), system_loader); } else { // It must have been restored from the archived module graph assert(CDSConfig::is_using_archive(), "must be"); assert(CDSConfig::is_using_full_module_graph(), "must be"); DEBUG_ONLY( - oop platform_loader = get_platform_class_loader_impl(CHECK); - assert(_java_platform_loader.resolve() == platform_loader, "must be"); + oop system_loader = get_system_class_loader_impl(CHECK); + assert(_java_system_loader.resolve() == system_loader, "must be"); ) } } @@ -330,9 +330,9 @@ static void handle_resolution_exception(Symbol* class_name, bool throw_error, TR // Forwards to resolve_or_null -Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, +Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader, bool throw_error, TRAPS) { - Klass* klass = resolve_or_null(class_name, class_loader, protection_domain, THREAD); + Klass* klass = resolve_or_null(class_name, class_loader, THREAD); // Check for pending exception or null klass, and throw exception if (HAS_PENDING_EXCEPTION || klass == nullptr) { handle_resolution_exception(class_name, throw_error, CHECK_NULL); @@ -342,9 +342,9 @@ Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader // Forwards to resolve_array_class_or_null or resolve_instance_class_or_null -Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) { +Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, TRAPS) { if (Signature::is_array(class_name)) { - return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD); + return resolve_array_class_or_null(class_name, class_loader, THREAD); } else { assert(class_name != nullptr && !Signature::is_array(class_name), "must be"); if (Signature::has_envelope(class_name)) { @@ -352,9 +352,9 @@ Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader // Ignore wrapping L and ;. TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1, class_name->utf8_length() - 2); - return resolve_instance_class_or_null(name, class_loader, protection_domain, THREAD); + return resolve_instance_class_or_null(name, class_loader, THREAD); } else { - return resolve_instance_class_or_null(class_name, class_loader, protection_domain, THREAD); + return resolve_instance_class_or_null(class_name, class_loader, THREAD); } } } @@ -363,7 +363,6 @@ Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name, Handle class_loader, - Handle protection_domain, TRAPS) { assert(Signature::is_array(class_name), "must be array"); ResourceMark rm(THREAD); @@ -375,7 +374,6 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name, Symbol* obj_class = ss.as_symbol(); k = SystemDictionary::resolve_instance_class_or_null(obj_class, class_loader, - protection_domain, CHECK_NULL); if (k != nullptr) { k = k->array_klass(ndims, CHECK_NULL); @@ -421,7 +419,6 @@ static inline void log_circularity_error(Symbol* name, PlaceholderEntry* probe) InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* class_name, Symbol* next_name, Handle class_loader, - Handle protection_domain, bool is_superclass, TRAPS) { @@ -486,7 +483,6 @@ InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* clas InstanceKlass* superk = SystemDictionary::resolve_instance_class_or_null(next_name, class_loader, - protection_domain, THREAD); // Clean up placeholder entry. @@ -513,7 +509,7 @@ InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* clas static void handle_parallel_super_load(Symbol* name, Symbol* superclassname, Handle class_loader, - Handle protection_domain, TRAPS) { + TRAPS) { // The result superk is not used; resolve_with_circularity_detection is called for circularity check only. // This passes true to is_superclass even though it might not be the super class in order to perform the @@ -521,7 +517,6 @@ static void handle_parallel_super_load(Symbol* name, Klass* superk = SystemDictionary::resolve_with_circularity_detection(name, superclassname, class_loader, - protection_domain, true, CHECK); } @@ -587,7 +582,6 @@ void SystemDictionary::post_class_load_event(EventClassLoad* event, const Instan // This can return null, an exception or an InstanceKlass. InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle class_loader, - Handle protection_domain, TRAPS) { // name must be in the form of "java/lang/Object" -- cannot be "Ljava/lang/Object;" DEBUG_ONLY(ResourceMark rm(THREAD)); @@ -601,12 +595,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, ClassLoaderData* loader_data = register_loader(class_loader); Dictionary* dictionary = loader_data->dictionary(); - // Do lookup to see if class already exists and the protection domain - // has the right access. - // This call uses find which checks protection domain already matches - // All subsequent calls use find_class, and set loaded_class so that - // before we return a result, we call out to java to check for valid protection domain. - InstanceKlass* probe = dictionary->find(THREAD, name, protection_domain); + // Do lookup to see if class already exists. + InstanceKlass* probe = dictionary->find_class(THREAD, name); if (probe != nullptr) return probe; // Non-bootstrap class loaders will call out to class loader and @@ -652,7 +642,6 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, if (circularity_detection_in_progress) { handle_parallel_super_load(name, superclassname, class_loader, - protection_domain, CHECK_NULL); } @@ -737,12 +726,6 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // Make sure we have the right class in the dictionary DEBUG_ONLY(verify_dictionary_entry(name, loaded_class)); - if (protection_domain() != nullptr) { - // A SecurityManager (if installed) may prevent this protection_domain from accessing loaded_class - // by throwing a SecurityException. - dictionary->check_package_access(loaded_class, class_loader, protection_domain, CHECK_NULL); - } - return loaded_class; } @@ -760,8 +743,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, InstanceKlass* SystemDictionary::find_instance_klass(Thread* current, Symbol* class_name, - Handle class_loader, - Handle protection_domain) { + Handle class_loader) { ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader()); if (loader_data == nullptr) { @@ -771,15 +753,14 @@ InstanceKlass* SystemDictionary::find_instance_klass(Thread* current, } Dictionary* dictionary = loader_data->dictionary(); - return dictionary->find(current, class_name, protection_domain); + return dictionary->find_class(current, class_name); } // Look for a loaded instance or array klass by name. Do not do any loading. // return null in case of error. Klass* SystemDictionary::find_instance_or_array_klass(Thread* current, Symbol* class_name, - Handle class_loader, - Handle protection_domain) { + Handle class_loader) { Klass* k = nullptr; assert(class_name != nullptr, "class name must be non nullptr"); @@ -793,13 +774,13 @@ Klass* SystemDictionary::find_instance_or_array_klass(Thread* current, if (t != T_OBJECT) { k = Universe::typeArrayKlass(t); } else { - k = SystemDictionary::find_instance_klass(current, ss.as_symbol(), class_loader, protection_domain); + k = SystemDictionary::find_instance_klass(current, ss.as_symbol(), class_loader); } if (k != nullptr) { k = k->array_klass_or_null(ndims); } } else { - k = find_instance_klass(current, class_name, class_loader, protection_domain); + k = find_instance_klass(current, class_name, class_loader); } return k; } @@ -825,7 +806,6 @@ InstanceKlass* SystemDictionary::resolve_hidden_class_from_stream( loader_data = register_loader(class_loader, create_mirror_cld); assert(st != nullptr, "invariant"); - assert(st->need_verify(), "invariant"); // Parse stream and create a klass. InstanceKlass* k = KlassFactory::create_from_stream(st, @@ -1044,8 +1024,7 @@ bool SystemDictionary::is_shared_class_visible_impl(Symbol* class_name, } bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, InstanceKlass* super_type, - Handle class_loader, Handle protection_domain, - bool is_superclass, TRAPS) { + Handle class_loader, bool is_superclass, TRAPS) { assert(super_type->is_shared(), "must be"); // Quick check if the super type has been already loaded. @@ -1055,14 +1034,14 @@ bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, Insta if (!super_type->is_shared_unregistered_class() && super_type->class_loader_data() != nullptr) { // Check if the superclass is loaded by the current class_loader Symbol* name = super_type->name(); - InstanceKlass* check = find_instance_klass(THREAD, name, class_loader, protection_domain); + InstanceKlass* check = find_instance_klass(THREAD, name, class_loader); if (check == super_type) { return true; } } Klass *found = resolve_with_circularity_detection(klass->name(), super_type->name(), - class_loader, protection_domain, is_superclass, CHECK_false); + class_loader, is_superclass, CHECK_false); if (found == super_type) { return true; } else { @@ -1072,8 +1051,7 @@ bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, Insta } } -bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle class_loader, - Handle protection_domain, TRAPS) { +bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle class_loader, TRAPS) { // Check the superclass and interfaces. They must be the same // as in dump time, because the layout of depends on // the specific layout of ik->super() and ik->local_interfaces(). @@ -1083,7 +1061,7 @@ bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle if (ik->super() != nullptr) { bool check_super = check_shared_class_super_type(ik, InstanceKlass::cast(ik->super()), - class_loader, protection_domain, true, + class_loader, true, CHECK_false); if (!check_super) { return false; @@ -1093,7 +1071,7 @@ bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle Array* interfaces = ik->local_interfaces(); int num_interfaces = interfaces->length(); for (int index = 0; index < num_interfaces; index++) { - bool check_interface = check_shared_class_super_type(ik, interfaces->at(index), class_loader, protection_domain, false, + bool check_interface = check_shared_class_super_type(ik, interfaces->at(index), class_loader, false, CHECK_false); if (!check_interface) { return false; @@ -1111,7 +1089,7 @@ InstanceKlass* SystemDictionary::load_shared_lambda_proxy_class(InstanceKlass* i InstanceKlass* shared_nest_host = SystemDictionaryShared::get_shared_nest_host(ik); assert(shared_nest_host->is_shared(), "nest host must be in CDS archive"); Symbol* cn = shared_nest_host->name(); - Klass *s = resolve_or_fail(cn, class_loader, protection_domain, true, CHECK_NULL); + Klass *s = resolve_or_fail(cn, class_loader, true, CHECK_NULL); if (s != shared_nest_host) { // The dynamically resolved nest_host is not the same as the one we used during dump time, // so we cannot use ik. @@ -1151,7 +1129,7 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik, return nullptr; } - bool check = check_shared_class_super_types(ik, class_loader, protection_domain, CHECK_NULL); + bool check = check_shared_class_super_types(ik, class_loader, CHECK_NULL); if (!check) { ik->set_shared_loading_failed(); return nullptr; @@ -1579,17 +1557,6 @@ bool SystemDictionary::do_unloading(GCTimer* gc_timer) { if (unloading_occurred) { SymbolTable::trigger_cleanup(); - if (java_lang_System::allow_security_manager()) { - // Oops referenced by the protection domain cache table may get unreachable independently - // of the class loader (eg. cached protection domain oops). So we need to - // explicitly unlink them here. - // All protection domain oops are linked to the caller class, so if nothing - // unloads, this is not needed. - ProtectionDomainCacheTable::trigger_cleanup(); - } else { - assert(ProtectionDomainCacheTable::number_of_entries() == 0, "should be empty"); - } - ConditionalMutexLocker ml(ClassInitError_lock, is_concurrent); InstanceKlass::clean_initialization_error_table(); } @@ -1627,7 +1594,6 @@ void SystemDictionary::initialize(TRAPS) { ResolutionErrorTable::initialize(); LoaderConstraintTable::initialize(); PlaceholderTable::initialize(); - ProtectionDomainCacheTable::initialize(); #if INCLUDE_CDS SystemDictionaryShared::initialize(); #endif @@ -1719,6 +1685,23 @@ void SystemDictionary::update_dictionary(JavaThread* current, mu1.notify_all(); } +#if INCLUDE_CDS +// Indicate that loader_data has initiated the loading of class k, which +// has already been defined by a parent loader. +// This API should be used only by AOTLinkedClassBulkLoader +void SystemDictionary::add_to_initiating_loader(JavaThread* current, + InstanceKlass* k, + ClassLoaderData* loader_data) { + assert(CDSConfig::is_using_aot_linked_classes(), "must be"); + assert_locked_or_safepoint(SystemDictionary_lock); + Symbol* name = k->name(); + Dictionary* dictionary = loader_data->dictionary(); + assert(k->is_loaded(), "must be"); + assert(k->class_loader_data() != loader_data, "only for classes defined by a parent loader"); + assert(dictionary->find_class(current, name) == nullptr, "sanity"); + dictionary->add_klass(current, name, k); +} +#endif // Try to find a class name using the loader constraints. The // loader constraints might know about a class that isn't fully loaded @@ -1727,10 +1710,7 @@ Klass* SystemDictionary::find_constrained_instance_or_array_klass( Thread* current, Symbol* class_name, Handle class_loader) { // First see if it has been loaded directly. - // Force the protection domain to be null. (This removes protection checks.) - Handle no_protection_domain; - Klass* klass = find_instance_or_array_klass(current, class_name, class_loader, - no_protection_domain); + Klass* klass = find_instance_or_array_klass(current, class_name, class_loader); if (klass != nullptr) return klass; @@ -2034,6 +2014,52 @@ Method* SystemDictionary::find_method_handle_intrinsic(vmIntrinsicID iid, return nullptr; } +#if INCLUDE_CDS +void SystemDictionary::get_all_method_handle_intrinsics(GrowableArray* methods) { + assert(SafepointSynchronize::is_at_safepoint(), "must be"); + auto do_method = [&] (InvokeMethodKey& key, Method*& m) { + methods->append(m); + }; + _invoke_method_intrinsic_table->iterate_all(do_method); +} + +void SystemDictionary::restore_archived_method_handle_intrinsics() { + if (UseSharedSpaces) { + EXCEPTION_MARK; + restore_archived_method_handle_intrinsics_impl(THREAD); + if (HAS_PENDING_EXCEPTION) { + // This is probably caused by OOM -- other parts of the CDS archive have direct pointers to + // the archived method handle intrinsics, so we can't really recover from this failure. + vm_exit_during_initialization(err_msg("Failed to restore archived method handle intrinsics. Try to increase heap size.")); + } + } +} + +void SystemDictionary::restore_archived_method_handle_intrinsics_impl(TRAPS) { + Array* list = MetaspaceShared::archived_method_handle_intrinsics(); + for (int i = 0; i < list->length(); i++) { + methodHandle m(THREAD, list->at(i)); + Method::restore_archived_method_handle_intrinsic(m, CHECK); + m->constants()->restore_unshareable_info(CHECK); + if (!Arguments::is_interpreter_only() || m->intrinsic_id() == vmIntrinsics::_linkToNative) { + AdapterHandlerLibrary::create_native_wrapper(m); + if (!m->has_compiled_code()) { + ResourceMark rm(THREAD); + vm_exit_during_initialization(err_msg("Failed to initialize method %s", m->external_name())); + } + } + + // There's no need to grab the InvokeMethodIntrinsicTable_lock, as we are still very early in + // VM start-up -- in init_globals2() -- so we are still running a single Java thread. It's not + // possible to have a contention. + const int iid_as_int = vmIntrinsics::as_int(m->intrinsic_id()); + InvokeMethodKey key(m->signature(), iid_as_int); + bool created = _invoke_method_intrinsic_table->put(key, m()); + assert(created, "unexpected contention"); + } +} +#endif // INCLUDE_CDS + // Helper for unpacking the return value from linkMethod and linkCallSite. static Method* unpack_method_and_appendix(Handle mname, Klass* accessing_klass, @@ -2132,21 +2158,18 @@ static bool is_always_visible_class(oop mirror) { // N.B. Code in reflection should use this entry point. Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature, Klass* accessing_klass, - Handle class_loader, - Handle protection_domain, SignatureStream::FailureMode failure_mode, TRAPS) { - assert(accessing_klass == nullptr || (class_loader.is_null() && protection_domain.is_null()), - "one or the other, or perhaps neither"); + + Handle class_loader; // What we have here must be a valid field descriptor, // and all valid field descriptors are supported. // Produce the same java.lang.Class that reflection reports. if (accessing_klass != nullptr) { class_loader = Handle(THREAD, accessing_klass->class_loader()); - protection_domain = Handle(THREAD, accessing_klass->protection_domain()); } - ResolvingSignatureStream ss(signature, class_loader, protection_domain, false); + ResolvingSignatureStream ss(signature, class_loader, false); oop mirror_oop = ss.as_java_mirror(failure_mode, CHECK_NH); if (mirror_oop == nullptr) { return Handle(); // report failure this way @@ -2187,10 +2210,9 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, return Handle(); // do not attempt from within compiler, unless it was cached } - Handle class_loader, protection_domain; + Handle class_loader; if (accessing_klass != nullptr) { class_loader = Handle(THREAD, accessing_klass->class_loader()); - protection_domain = Handle(THREAD, accessing_klass->protection_domain()); } bool can_be_cached = true; int npts = ArgumentCount(signature).size(); @@ -2202,8 +2224,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, oop mirror = nullptr; if (can_be_cached) { // Use neutral class loader to lookup candidate classes to be placed in the cache. - mirror = ss.as_java_mirror(Handle(), Handle(), - SignatureStream::ReturnNull, CHECK_(empty)); + mirror = ss.as_java_mirror(Handle(), SignatureStream::ReturnNull, CHECK_(empty)); if (mirror == nullptr || (ss.is_reference() && !is_always_visible_class(mirror))) { // Fall back to accessing_klass context. can_be_cached = false; @@ -2211,8 +2232,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, } if (!can_be_cached) { // Resolve, throwing a real error if it doesn't work. - mirror = ss.as_java_mirror(class_loader, protection_domain, - SignatureStream::NCDFError, CHECK_(empty)); + mirror = ss.as_java_mirror(class_loader, SignatureStream::NCDFError, CHECK_(empty)); } assert(mirror != nullptr, "%s", ss.as_symbol()->as_C_string()); if (ss.at_return_type()) @@ -2265,12 +2285,11 @@ Handle SystemDictionary::find_field_handle_type(Symbol* signature, ResourceMark rm(THREAD); SignatureStream ss(signature, /*is_method=*/ false); if (!ss.is_done()) { - Handle class_loader, protection_domain; + Handle class_loader; if (accessing_klass != nullptr) { class_loader = Handle(THREAD, accessing_klass->class_loader()); - protection_domain = Handle(THREAD, accessing_klass->protection_domain()); } - oop mirror = ss.as_java_mirror(class_loader, protection_domain, SignatureStream::NCDFError, CHECK_(empty)); + oop mirror = ss.as_java_mirror(class_loader, SignatureStream::NCDFError, CHECK_(empty)); ss.next(); if (ss.is_done()) { return Handle(THREAD, mirror); @@ -2408,9 +2427,6 @@ void SystemDictionary::print_on(outputStream *st) { // loader constraints - print under SD_lock LoaderConstraintTable::print_on(st); st->cr(); - - ProtectionDomainCacheTable::print_on(st); - st->cr(); } void SystemDictionary::print() { print_on(tty); } @@ -2424,9 +2440,6 @@ void SystemDictionary::verify() { // Verify constraint table LoaderConstraintTable::verify(); - - // Verify protection domain table - ProtectionDomainCacheTable::verify(); } void SystemDictionary::dump(outputStream *st, bool verbose) { @@ -2437,7 +2450,6 @@ void SystemDictionary::dump(outputStream *st, bool verbose) { CDS_ONLY(SystemDictionaryShared::print_table_statistics(st)); ClassLoaderDataGraph::print_table_statistics(st); LoaderConstraintTable::print_table_statistics(st); - ProtectionDomainCacheTable::print_table_statistics(st); } } diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 04980291716..5883b76b64b 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -33,12 +33,12 @@ // The dictionary in each ClassLoaderData stores all loaded classes, either // initiatied by its class loader or defined by its class loader: // -// class loader -> ClassLoaderData -> [class, protection domain set] +// class loader -> ClassLoaderData -> Loaded and initiated loaded classes // // Classes are loaded lazily. The default VM class loader is // represented as null. -// The underlying data structure is an open hash table (Dictionary) per +// The underlying data structure is a concurrent hash table (Dictionary) per // ClassLoaderData with a fixed number of buckets. During loading the // class loader object is locked, (for the VM loader a private lock object is used). // The global SystemDictionary_lock is held for all additions into the ClassLoaderData @@ -49,9 +49,7 @@ // a side data structure, and is used to detect ClassCircularityErrors. // // When class loading is finished, a new entry is added to the dictionary -// of the class loader and the placeholder is removed. Note that the protection -// domain field of the dictionary entry has not yet been filled in when -// the "real" dictionary entry is created. +// of the class loader and the placeholder is removed. // // Clients of this class who are interested in finding if a class has // been completely loaded -- not classes in the process of being loaded -- @@ -75,7 +73,10 @@ class GCTimer; class EventClassLoad; class Symbol; +template class GrowableArray; + class SystemDictionary : AllStatic { + friend class AOTLinkedClassBulkLoader; friend class BootstrapInfo; friend class vmClasses; friend class VMStructs; @@ -88,24 +89,23 @@ class SystemDictionary : AllStatic { // throw_error flag. For most uses the throw_error argument should be set // to true. - static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS); + static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, bool throw_error, TRAPS); // Convenient call for null loader and protection domain. static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS) { - return resolve_or_fail(class_name, Handle(), Handle(), throw_error, THREAD); + return resolve_or_fail(class_name, Handle(), throw_error, THREAD); } // Returns a class with a given class name and class loader. // Loads the class if needed. If not found null is returned. - static Klass* resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS); + static Klass* resolve_or_null(Symbol* class_name, Handle class_loader, TRAPS); // Version with null loader and protection domain static Klass* resolve_or_null(Symbol* class_name, TRAPS) { - return resolve_or_null(class_name, Handle(), Handle(), THREAD); + return resolve_or_null(class_name, Handle(), THREAD); } static InstanceKlass* resolve_with_circularity_detection(Symbol* class_name, Symbol* next_name, Handle class_loader, - Handle protection_domain, bool is_superclass, TRAPS); @@ -114,9 +114,8 @@ class SystemDictionary : AllStatic { // "class_name" is the class whose super class or interface is being resolved. static InstanceKlass* resolve_super_or_fail(Symbol* class_name, Symbol* super_name, Handle class_loader, - Handle protection_domain, bool is_superclass, TRAPS) { - return resolve_with_circularity_detection(class_name, super_name, class_loader, protection_domain, - is_superclass, THREAD); + bool is_superclass, TRAPS) { + return resolve_with_circularity_detection(class_name, super_name, class_loader, is_superclass, THREAD); } private: @@ -149,14 +148,13 @@ class SystemDictionary : AllStatic { // Lookup an already loaded class. If not found null is returned. static InstanceKlass* find_instance_klass(Thread* current, Symbol* class_name, - Handle class_loader, Handle protection_domain); + Handle class_loader); // Lookup an already loaded instance or array class. // Do not make any queries to class loaders; consult only the cache. // If not found null is returned. static Klass* find_instance_or_array_klass(Thread* current, Symbol* class_name, - Handle class_loader, - Handle protection_domain); + Handle class_loader); // Lookup an instance or array class that has already been loaded // either into the given class loader, or else into another class @@ -239,22 +237,14 @@ class SystemDictionary : AllStatic { Symbol* signature, TRAPS); + static void get_all_method_handle_intrinsics(GrowableArray* methods) NOT_CDS_RETURN; + static void restore_archived_method_handle_intrinsics() NOT_CDS_RETURN; + // compute java_mirror (java.lang.Class instance) for a type ("I", "[[B", "LFoo;", etc.) - // Either the accessing_klass or the CL/PD can be non-null, but not both. static Handle find_java_mirror_for_type(Symbol* signature, Klass* accessing_klass, - Handle class_loader, - Handle protection_domain, SignatureStream::FailureMode failure_mode, TRAPS); - static Handle find_java_mirror_for_type(Symbol* signature, - Klass* accessing_klass, - SignatureStream::FailureMode failure_mode, - TRAPS) { - // callee will fill in CL/PD from AK, if they are needed - return find_java_mirror_for_type(signature, accessing_klass, Handle(), Handle(), - failure_mode, THREAD); - } // find a java.lang.invoke.MethodType object for a given signature // (asks Java to compute it if necessary, except in a compiler thread) @@ -293,6 +283,9 @@ class SystemDictionary : AllStatic { const char* message); static const char* find_nest_host_error(const constantPoolHandle& pool, int which); + static void add_to_initiating_loader(JavaThread* current, InstanceKlass* k, + ClassLoaderData* loader_data) NOT_CDS_RETURN; + static OopHandle _java_system_loader; static OopHandle _java_platform_loader; @@ -300,10 +293,10 @@ class SystemDictionary : AllStatic { // Basic loading operations static InstanceKlass* resolve_instance_class_or_null(Symbol* class_name, Handle class_loader, - Handle protection_domain, TRAPS); + TRAPS); static Klass* resolve_array_class_or_null(Symbol* class_name, Handle class_loader, - Handle protection_domain, TRAPS); + TRAPS); static void define_instance_class(InstanceKlass* k, Handle class_loader, TRAPS); static InstanceKlass* find_or_define_helper(Symbol* class_name, Handle class_loader, @@ -325,12 +318,12 @@ class SystemDictionary : AllStatic { PackageEntry* pkg_entry, Handle class_loader); static bool check_shared_class_super_type(InstanceKlass* klass, InstanceKlass* super, - Handle class_loader, Handle protection_domain, + Handle class_loader, bool is_superclass, TRAPS); - static bool check_shared_class_super_types(InstanceKlass* ik, Handle class_loader, - Handle protection_domain, TRAPS); + static bool check_shared_class_super_types(InstanceKlass* ik, Handle class_loader, TRAPS); // Second part of load_shared_class static void load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data) NOT_CDS_RETURN; + static void restore_archived_method_handle_intrinsics_impl(TRAPS) NOT_CDS_RETURN; protected: // Used by SystemDictionaryShared diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 08f224d969f..84b7ea0d6b9 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -27,12 +27,13 @@ #include "cds/archiveHeapLoader.hpp" #include "cds/archiveUtils.hpp" #include "cds/cdsConfig.hpp" +#include "cds/cdsProtectionDomain.hpp" #include "cds/classListParser.hpp" #include "cds/classListWriter.hpp" +#include "cds/dumpTimeClassInfo.inline.hpp" #include "cds/dynamicArchive.hpp" #include "cds/filemap.hpp" -#include "cds/cdsProtectionDomain.hpp" -#include "cds/dumpTimeClassInfo.inline.hpp" +#include "cds/heapShared.hpp" #include "cds/metaspaceShared.hpp" #include "cds/runTimeClassInfo.hpp" #include "classfile/classFileStream.hpp" @@ -204,6 +205,15 @@ DumpTimeClassInfo* SystemDictionaryShared::get_info_locked(InstanceKlass* k) { return info; } +void SystemDictionaryShared::mark_required_hidden_class(InstanceKlass* k) { + assert(k->is_hidden(), "sanity"); + DumpTimeClassInfo* info = _dumptime_table->get(k); + ResourceMark rm; + if (info != nullptr) { + info->set_is_required_hidden_class(); + } +} + bool SystemDictionaryShared::check_for_exclusion(InstanceKlass* k, DumpTimeClassInfo* info) { if (MetaspaceShared::is_in_shared_metaspace(k)) { // We have reached a super type that's already in the base archive. Treat it @@ -287,9 +297,13 @@ bool SystemDictionaryShared::check_for_exclusion_impl(InstanceKlass* k) { if (!k->is_hidden() && k->shared_classpath_index() < 0 && is_builtin(k)) { if (k->name()->starts_with("java/lang/invoke/BoundMethodHandle$Species_")) { // This class is dynamically generated by the JDK - ResourceMark rm; - log_info(cds)("Skipping %s because it is dynamically generated", k->name()->as_C_string()); - return true; // exclude without warning + if (CDSConfig::is_dumping_aot_linked_classes()) { + k->set_shared_classpath_index(0); + } else { + ResourceMark rm; + log_info(cds)("Skipping %s because it is dynamically generated", k->name()->as_C_string()); + return true; // exclude without warning + } } else { // These are classes loaded from unsupported locations (such as those loaded by JVMTI native // agent during dump time). @@ -326,9 +340,8 @@ bool SystemDictionaryShared::check_for_exclusion_impl(InstanceKlass* k) { } } - if (k->is_hidden() && !is_registered_lambda_proxy_class(k)) { - ResourceMark rm; - log_debug(cds)("Skipping %s: Hidden class", k->name()->as_C_string()); + if (k->is_hidden() && !should_hidden_class_be_archived(k)) { + log_info(cds)("Skipping %s: Hidden class", k->name()->as_C_string()); return true; } @@ -588,7 +601,11 @@ void SystemDictionaryShared::validate_before_archiving(InstanceKlass* k) { guarantee(!info->is_excluded(), "Should not attempt to archive excluded class %s", name); if (is_builtin(k)) { if (k->is_hidden()) { - assert(is_registered_lambda_proxy_class(k), "unexpected hidden class %s", name); + if (CDSConfig::is_dumping_invokedynamic()) { + assert(should_hidden_class_be_archived(k), "unexpected hidden class %s", name); + } else { + assert(is_registered_lambda_proxy_class(k), "unexpected hidden class %s", name); + } } guarantee(!k->is_shared_unregistered_class(), "Class loader type must be set for BUILTIN class %s", name); @@ -640,7 +657,93 @@ class UnregisteredClassesDuplicationChecker : StackObj { } }; -void SystemDictionaryShared::check_excluded_classes() { +void SystemDictionaryShared::scan_constant_pool(InstanceKlass* k) { + if (CDSConfig::is_dumping_invokedynamic()) { + k->constants()->find_required_hidden_classes(); + } +} + +bool SystemDictionaryShared::should_hidden_class_be_archived(InstanceKlass* k) { + assert(k->is_hidden(), "sanity"); + if (is_registered_lambda_proxy_class(k)) { + return true; + } + + if (CDSConfig::is_dumping_invokedynamic()) { + DumpTimeClassInfo* info = _dumptime_table->get(k); + if (info != nullptr && info->is_required_hidden_class()) { + guarantee(HeapShared::is_archivable_hidden_klass(k), "required hidden class must be archivable"); + return true; + } + } + + return false; +} + +// Returns true if the class should be excluded. This can be called by +// AOTConstantPoolResolver before or after we enter the CDS safepoint. +// When called before the safepoint, we need to link the class so that +// it can be checked by check_for_exclusion(). +bool SystemDictionaryShared::should_be_excluded(Klass* k) { + assert(CDSConfig::is_dumping_archive(), "sanity"); + assert(CDSConfig::current_thread_is_vm_or_dumper(), "sanity"); + + if (k->is_objArray_klass()) { + return should_be_excluded(ObjArrayKlass::cast(k)->bottom_klass()); + } + + if (!k->is_instance_klass()) { + return false; + } else { + InstanceKlass* ik = InstanceKlass::cast(k); + + if (!SafepointSynchronize::is_at_safepoint()) { + if (!ik->is_linked()) { + // check_for_exclusion() below doesn't link unlinked classes. We come + // here only when we are trying to aot-link constant pool entries, so + // we'd better link the class. + JavaThread* THREAD = JavaThread::current(); + ik->link_class(THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + return true; // linking failed -- let's exclude it + } + } + + MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); + DumpTimeClassInfo* p = get_info_locked(ik); + if (p->is_excluded()) { + return true; + } + return check_for_exclusion(ik, p); + } else { + // No need to check for is_linked() as all eligible classes should have + // already been linked in MetaspaceShared::link_class_for_cds(). + // Can't take the lock as we are in safepoint. + DumpTimeClassInfo* p = _dumptime_table->get(ik); + if (p->is_excluded()) { + return true; + } + return check_for_exclusion(ik, p); + } + } +} + +void SystemDictionaryShared::find_all_archivable_classes() { + HeapShared::start_finding_required_hidden_classes(); + find_all_archivable_classes_impl(); + HeapShared::end_finding_required_hidden_classes(); +} + +// Iterate over all the classes in _dumptime_table, marking the ones that must be +// excluded from the archive. Those that are not excluded will be archivable. +// +// (a) Non-hidden classes are easy. They are only check by the rules in +// SystemDictionaryShared::check_for_exclusion(). +// (b) For hidden classes, we only archive those that are required (i.e., they are +// referenced by Java objects (such as CallSites) that are reachable from +// ConstantPools). This needs help from HeapShared. +void SystemDictionaryShared::find_all_archivable_classes_impl() { assert(!class_loading_may_happen(), "class loading must be disabled"); assert_lock_strong(DumpTimeTable_lock); @@ -653,10 +756,56 @@ void SystemDictionaryShared::check_excluded_classes() { dup_checker.mark_duplicated_classes(); } - auto check_for_exclusion = [&] (InstanceKlass* k, DumpTimeClassInfo& info) { - SystemDictionaryShared::check_for_exclusion(k, &info); + ResourceMark rm; + + // First, scan all non-hidden classes + auto check_non_hidden = [&] (InstanceKlass* k, DumpTimeClassInfo& info) { + if (!k->is_hidden()) { + SystemDictionaryShared::check_for_exclusion(k, &info); + if (!info.is_excluded() && !info.has_scanned_constant_pool()) { + scan_constant_pool(k); + info.set_has_scanned_constant_pool(); + } + } }; - _dumptime_table->iterate_all_live_classes(check_for_exclusion); + _dumptime_table->iterate_all_live_classes(check_non_hidden); + + // Then, scan all the hidden classes that have been marked as required to + // discover more hidden classes. Stop when we cannot make progress anymore. + bool made_progress; + do { + made_progress = false; + auto check_hidden = [&] (InstanceKlass* k, DumpTimeClassInfo& info) { + if (k->is_hidden() && should_hidden_class_be_archived(k)) { + SystemDictionaryShared::check_for_exclusion(k, &info); + if (info.is_excluded()) { + guarantee(!info.is_required_hidden_class(), "A required hidden class cannot be marked as excluded"); + } else if (!info.has_scanned_constant_pool()) { + scan_constant_pool(k); + info.set_has_scanned_constant_pool(); + // The CP entries in k *MAY* refer to other hidden classes, so scan + // every hidden class again. + made_progress = true; + } + } + }; + _dumptime_table->iterate_all_live_classes(check_hidden); + } while (made_progress); + + // Now, all hidden classes that have not yet been scanned must be marked as excluded + auto exclude_remaining_hidden = [&] (InstanceKlass* k, DumpTimeClassInfo& info) { + if (k->is_hidden()) { + SystemDictionaryShared::check_for_exclusion(k, &info); + if (CDSConfig::is_dumping_invokedynamic()) { + if (should_hidden_class_be_archived(k)) { + guarantee(!info.is_excluded(), "Must be"); + } else { + guarantee(info.is_excluded(), "Must be"); + } + } + } + }; + _dumptime_table->iterate_all_live_classes(exclude_remaining_hidden); _dumptime_table->update_counts(); cleanup_lambda_proxy_class_dictionary(); @@ -766,6 +915,11 @@ void SystemDictionaryShared::add_lambda_proxy_class(InstanceKlass* caller_ik, Method* member_method, Symbol* instantiated_method_type, TRAPS) { + if (CDSConfig::is_dumping_invokedynamic()) { + // The lambda proxy classes will be stored as part of aot-resolved constant pool entries. + // There's no need to remember them in a separate table. + return; + } assert(caller_ik->class_loader() == lambda_ik->class_loader(), "mismatched class loader"); assert(caller_ik->class_loader_data() == lambda_ik->class_loader_data(), "mismatched class loader data"); @@ -1188,7 +1342,7 @@ class CopyLambdaProxyClassInfoToArchive : StackObj { // In static dump, info._proxy_klasses->at(0) is already relocated to point to the archived class // (not the original class). // - // The following check has been moved to SystemDictionaryShared::check_excluded_classes(), which + // The following check has been moved to SystemDictionaryShared::find_all_archivable_classes(), which // happens before the classes are copied. // // if (SystemDictionaryShared::is_excluded_class(info._proxy_klasses->at(0))) { diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index c79821036e0..5e0c54a6ffc 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -188,6 +188,7 @@ class SystemDictionaryShared: public SystemDictionary { static DumpTimeClassInfo* get_info(InstanceKlass* k); static DumpTimeClassInfo* get_info_locked(InstanceKlass* k); + static void find_all_archivable_classes_impl(); static void write_dictionary(RunTimeSharedDictionary* dictionary, bool is_builtin); static void write_lambda_proxy_class_dictionary(LambdaProxyClassDictionary* dictionary); @@ -199,10 +200,12 @@ class SystemDictionaryShared: public SystemDictionary { static void remove_dumptime_info(InstanceKlass* k) NOT_CDS_RETURN; static bool has_been_redefined(InstanceKlass* k); static InstanceKlass* retrieve_lambda_proxy_class(const RunTimeLambdaProxyClassInfo* info) NOT_CDS_RETURN_(nullptr); - + static void scan_constant_pool(InstanceKlass* k); DEBUG_ONLY(static bool _class_loading_may_happen;) public: + static bool should_hidden_class_be_archived(InstanceKlass* k); + static void mark_required_hidden_class(InstanceKlass* k); static bool is_hidden_lambda_proxy(InstanceKlass* ik); static bool is_early_klass(InstanceKlass* k); // Was k loaded while JvmtiExport::is_early_phase()==true static bool has_archived_enum_objs(InstanceKlass* ik); @@ -288,7 +291,8 @@ class SystemDictionaryShared: public SystemDictionary { } static bool add_unregistered_class(Thread* current, InstanceKlass* k); - static void check_excluded_classes(); + static void find_all_archivable_classes(); + static bool should_be_excluded(Klass* k); static bool check_for_exclusion(InstanceKlass* k, DumpTimeClassInfo* info); static void validate_before_archiving(InstanceKlass* k); static bool is_excluded_class(InstanceKlass* k); diff --git a/src/hotspot/share/classfile/verificationType.cpp b/src/hotspot/share/classfile/verificationType.cpp index bd66cf43b5c..ddeee499814 100644 --- a/src/hotspot/share/classfile/verificationType.cpp +++ b/src/hotspot/share/classfile/verificationType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -57,8 +57,7 @@ bool VerificationType::resolve_and_check_assignability(InstanceKlass* klass, Sym this_class = klass; } else { this_class = SystemDictionary::resolve_or_fail( - name, Handle(THREAD, klass->class_loader()), - Handle(THREAD, klass->protection_domain()), true, CHECK_false); + name, Handle(THREAD, klass->class_loader()), true, CHECK_false); if (log_is_enabled(Debug, class, resolve)) { Verifier::trace_class_resolution(this_class, klass); } @@ -79,8 +78,7 @@ bool VerificationType::resolve_and_check_assignability(InstanceKlass* klass, Sym from_class = klass; } else { from_class = SystemDictionary::resolve_or_fail( - from_name, Handle(THREAD, klass->class_loader()), - Handle(THREAD, klass->protection_domain()), true, CHECK_false); + from_name, Handle(THREAD, klass->class_loader()), true, CHECK_false); if (log_is_enabled(Debug, class, resolve)) { Verifier::trace_class_resolution(from_class, klass); } diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index b34cde4c63a..ef3caff6476 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -105,8 +105,8 @@ static verify_byte_codes_fn_t verify_byte_codes_fn() { // Methods in Verifier -bool Verifier::should_verify_for(oop class_loader, bool should_verify_class) { - return (class_loader == nullptr || !should_verify_class) ? +bool Verifier::should_verify_for(oop class_loader) { + return class_loader == nullptr ? BytecodeVerificationLocal : BytecodeVerificationRemote; } @@ -276,7 +276,7 @@ bool Verifier::verify(InstanceKlass* klass, bool should_verify_class, TRAPS) { bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_verify_class) { Symbol* name = klass->name(); - return (should_verify_for(klass->class_loader(), should_verify_class) && + return (should_verify_class && // return if the class is a bootstrapping class // or defineClass specified not to verify by default (flags override passed arg) // We need to skip the following four for bootstraping @@ -2092,15 +2092,13 @@ void ClassVerifier::class_format_error(const char* msg, ...) { Klass* ClassVerifier::load_class(Symbol* name, TRAPS) { HandleMark hm(THREAD); - // Get current loader and protection domain first. + // Get current loader first. oop loader = current_class()->class_loader(); - oop protection_domain = current_class()->protection_domain(); assert(name_in_supers(name, current_class()), "name should be a super class"); Klass* kls = SystemDictionary::resolve_or_fail( - name, Handle(THREAD, loader), Handle(THREAD, protection_domain), - true, THREAD); + name, Handle(THREAD, loader), true, THREAD); if (kls != nullptr) { if (log_is_enabled(Debug, class, resolve)) { diff --git a/src/hotspot/share/classfile/verifier.hpp b/src/hotspot/share/classfile/verifier.hpp index 8065620c8fd..731d5eb8d3b 100644 --- a/src/hotspot/share/classfile/verifier.hpp +++ b/src/hotspot/share/classfile/verifier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -52,7 +52,7 @@ class Verifier : AllStatic { // Return false if the class is loaded by the bootstrap loader, // or if defineClass was called requesting skipping verification // -Xverify:all overrides this value - static bool should_verify_for(oop class_loader, bool should_verify_class); + static bool should_verify_for(oop class_loader); // Relax certain access checks to enable some broken 1.1 apps to run on 1.2. static bool relax_access_for(oop class_loader); diff --git a/src/hotspot/share/classfile/vmClassMacros.hpp b/src/hotspot/share/classfile/vmClassMacros.hpp index 395e718c55d..395034d4a21 100644 --- a/src/hotspot/share/classfile/vmClassMacros.hpp +++ b/src/hotspot/share/classfile/vmClassMacros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -60,10 +60,7 @@ do_klass(Error_klass, java_lang_Error ) \ do_klass(Exception_klass, java_lang_Exception ) \ do_klass(RuntimeException_klass, java_lang_RuntimeException ) \ - do_klass(SecurityManager_klass, java_lang_SecurityManager ) \ do_klass(ProtectionDomain_klass, java_security_ProtectionDomain ) \ - do_klass(AccessControlContext_klass, java_security_AccessControlContext ) \ - do_klass(AccessController_klass, java_security_AccessController ) \ do_klass(SecureClassLoader_klass, java_security_SecureClassLoader ) \ do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException ) \ do_klass(Record_klass, java_lang_Record ) \ @@ -175,6 +172,7 @@ do_klass(Short_klass, java_lang_Short ) \ do_klass(Integer_klass, java_lang_Integer ) \ do_klass(Long_klass, java_lang_Long ) \ + do_klass(Void_klass, java_lang_Void ) \ \ /* force inline of iterators */ \ do_klass(Iterator_klass, java_util_Iterator ) \ diff --git a/src/hotspot/share/classfile/vmClasses.cpp b/src/hotspot/share/classfile/vmClasses.cpp index b62d699dfe2..553864ef0b9 100644 --- a/src/hotspot/share/classfile/vmClasses.cpp +++ b/src/hotspot/share/classfile/vmClasses.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "cds/aotLinkedClassBulkLoader.hpp" #include "cds/archiveHeapLoader.hpp" #include "cds/cdsConfig.hpp" #include "classfile/classLoader.hpp" @@ -210,6 +211,9 @@ void vmClasses::resolve_all(TRAPS) { #endif InstanceStackChunkKlass::init_offset_of_stack(); + if (CDSConfig::is_using_aot_linked_classes()) { + AOTLinkedClassBulkLoader::load_javabase_classes(THREAD); + } } #if INCLUDE_CDS diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 34861b52d54..ca451572de7 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -89,6 +89,7 @@ class SerializeClosure; template(java_lang_Integer_IntegerCache, "java/lang/Integer$IntegerCache") \ template(java_lang_Long, "java/lang/Long") \ template(java_lang_Long_LongCache, "java/lang/Long$LongCache") \ + template(java_lang_Void, "java/lang/Void") \ \ template(jdk_internal_vm_vector_VectorSupport, "jdk/internal/vm/vector/VectorSupport") \ template(jdk_internal_vm_vector_VectorPayload, "jdk/internal/vm/vector/VectorSupport$VectorPayload") \ @@ -117,12 +118,8 @@ class SerializeClosure; template(java_lang_reflect_RecordComponent, "java/lang/reflect/RecordComponent") \ template(java_lang_StringBuffer, "java/lang/StringBuffer") \ template(java_lang_StringBuilder, "java/lang/StringBuilder") \ - template(java_lang_SecurityManager, "java/lang/SecurityManager") \ template(java_lang_ScopedValue, "java/lang/ScopedValue") \ template(java_lang_ScopedValue_Carrier, "java/lang/ScopedValue$Carrier") \ - template(java_security_AccessControlContext, "java/security/AccessControlContext") \ - template(java_security_AccessController, "java/security/AccessController") \ - template(executePrivileged_name, "executePrivileged") \ template(java_security_CodeSource, "java/security/CodeSource") \ template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \ template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \ @@ -309,6 +306,8 @@ class SerializeClosure; template(jdk_internal_vm_annotation_JvmtiHideEvents_signature, "Ljdk/internal/vm/annotation/JvmtiHideEvents;") \ template(jdk_internal_vm_annotation_JvmtiMountTransition_signature, "Ljdk/internal/vm/annotation/JvmtiMountTransition;") \ \ + template(java_lang_ref_SoftReference_signature, "Ljava/lang/ref/SoftReference;") \ + \ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ template(java_lang_invoke_ConstantCallSite, "java/lang/invoke/ConstantCallSite") \ @@ -437,9 +436,6 @@ class SerializeClosure; template(getCause_name, "getCause") \ template(initCause_name, "initCause") \ template(getProperty_name, "getProperty") \ - template(context_name, "context") \ - template(contextClassLoader_name, "contextClassLoader") \ - template(getClassContext_name, "getClassContext") \ template(wait_name, "wait0") \ template(forName_name, "forName") \ template(forName0_name, "forName0") \ @@ -487,7 +483,6 @@ class SerializeClosure; template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \ template(input_stream_signature, "Ljava/io/InputStream;") \ template(print_stream_signature, "Ljava/io/PrintStream;") \ - template(security_manager_signature, "Ljava/lang/SecurityManager;") \ template(defineOrCheckPackage_name, "defineOrCheckPackage") \ template(defineOrCheckPackage_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)Ljava/lang/Package;") \ template(getProtectionDomain_name, "getProtectionDomain") \ @@ -601,9 +596,6 @@ class SerializeClosure; template(void_string_signature, "()Ljava/lang/String;") \ template(object_array_object_signature, "([Ljava/lang/Object;)Ljava/lang/Object;") \ template(object_object_array_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\ - template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \ - template(accesscontrolcontext_signature, "Ljava/security/AccessControlContext;") \ - template(class_protectiondomain_signature, "(Ljava/lang/Class;Ljava/security/ProtectionDomain;)V") \ template(thread_signature, "Ljava/lang/Thread;") \ template(thread_fieldholder_signature, "Ljava/lang/Thread$FieldHolder;") \ template(threadgroup_signature, "Ljava/lang/ThreadGroup;") \ @@ -726,6 +718,7 @@ class SerializeClosure; JFR_TEMPLATES(template) \ \ /* CDS */ \ + template(createArchivedObjects, "createArchivedObjects") \ template(dumpSharedArchive, "dumpSharedArchive") \ template(dumpSharedArchive_signature, "(ZLjava/lang/String;)Ljava/lang/String;") \ template(generateLambdaFormHolderClasses, "generateLambdaFormHolderClasses") \ @@ -739,6 +732,7 @@ class SerializeClosure; template(jdk_internal_misc_CDS, "jdk/internal/misc/CDS") \ template(java_util_concurrent_ConcurrentHashMap, "java/util/concurrent/ConcurrentHashMap") \ template(java_util_ArrayList, "java/util/ArrayList") \ + template(runtimeSetup, "runtimeSetup") \ template(toFileURL_name, "toFileURL") \ template(toFileURL_signature, "(Ljava/lang/String;)Ljava/net/URL;") \ template(url_array_classloader_void_signature, "([Ljava/net/URL;Ljava/lang/ClassLoader;)V") \ diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 52d26418af6..d0879e9967c 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -2483,6 +2483,214 @@ bool G1ConcurrentMark::try_stealing(uint worker_id, G1TaskQueueEntry& task_entry return _task_queues->steal(worker_id, task_entry); } +void G1CMTask::process_current_region(G1CMBitMapClosure& bitmap_closure) { + if (has_aborted() || _curr_region == nullptr) { + return; + } + + // This means that we're already holding on to a region. + assert(_finger != nullptr, "if region is not null, then the finger " + "should not be null either"); + + // We might have restarted this task after an evacuation pause + // which might have evacuated the region we're holding on to + // underneath our feet. Let's read its limit again to make sure + // that we do not iterate over a region of the heap that + // contains garbage (update_region_limit() will also move + // _finger to the start of the region if it is found empty). + update_region_limit(); + // We will start from _finger not from the start of the region, + // as we might be restarting this task after aborting half-way + // through scanning this region. In this case, _finger points to + // the address where we last found a marked object. If this is a + // fresh region, _finger points to start(). + MemRegion mr = MemRegion(_finger, _region_limit); + + assert(!_curr_region->is_humongous() || mr.start() == _curr_region->bottom(), + "humongous regions should go around loop once only"); + + // Some special cases: + // If the memory region is empty, we can just give up the region. + // If the current region is humongous then we only need to check + // the bitmap for the bit associated with the start of the object, + // scan the object if it's live, and give up the region. + // Otherwise, let's iterate over the bitmap of the part of the region + // that is left. + // If the iteration is successful, give up the region. + if (mr.is_empty()) { + giveup_current_region(); + abort_marking_if_regular_check_fail(); + } else if (_curr_region->is_humongous() && mr.start() == _curr_region->bottom()) { + if (_mark_bitmap->is_marked(mr.start())) { + // The object is marked - apply the closure + bitmap_closure.do_addr(mr.start()); + } + // Even if this task aborted while scanning the humongous object + // we can (and should) give up the current region. + giveup_current_region(); + abort_marking_if_regular_check_fail(); + } else if (_mark_bitmap->iterate(&bitmap_closure, mr)) { + giveup_current_region(); + abort_marking_if_regular_check_fail(); + } else { + assert(has_aborted(), "currently the only way to do so"); + // The only way to abort the bitmap iteration is to return + // false from the do_bit() method. However, inside the + // do_bit() method we move the _finger to point to the + // object currently being looked at. So, if we bail out, we + // have definitely set _finger to something non-null. + assert(_finger != nullptr, "invariant"); + + // Region iteration was actually aborted. So now _finger + // points to the address of the object we last scanned. If we + // leave it there, when we restart this task, we will rescan + // the object. It is easy to avoid this. We move the finger by + // enough to point to the next possible object header. + assert(_finger < _region_limit, "invariant"); + HeapWord* const new_finger = _finger + cast_to_oop(_finger)->size(); + if (new_finger >= _region_limit) { + giveup_current_region(); + } else { + move_finger_to(new_finger); + } + } +} + +void G1CMTask::claim_new_region() { + // Read the note on the claim_region() method on why it might + // return null with potentially more regions available for + // claiming and why we have to check out_of_regions() to determine + // whether we're done or not. + while (!has_aborted() && _curr_region == nullptr && !_cm->out_of_regions()) { + // We are going to try to claim a new region. We should have + // given up on the previous one. + // Separated the asserts so that we know which one fires. + assert(_curr_region == nullptr, "invariant"); + assert(_finger == nullptr, "invariant"); + assert(_region_limit == nullptr, "invariant"); + G1HeapRegion* claimed_region = _cm->claim_region(_worker_id); + if (claimed_region != nullptr) { + // Yes, we managed to claim one + setup_for_region(claimed_region); + assert(_curr_region == claimed_region, "invariant"); + } + // It is important to call the regular clock here. It might take + // a while to claim a region if, for example, we hit a large + // block of empty regions. So we need to call the regular clock + // method once round the loop to make sure it's called + // frequently enough. + abort_marking_if_regular_check_fail(); + } +} + +void G1CMTask::attempt_stealing() { + // We cannot check whether the global stack is empty, since other + // tasks might be pushing objects to it concurrently. + assert(_cm->out_of_regions() && _task_queue->size() == 0, + "only way to reach here"); + while (!has_aborted()) { + G1TaskQueueEntry entry; + if (_cm->try_stealing(_worker_id, entry)) { + scan_task_entry(entry); + + // And since we're towards the end, let's totally drain the + // local queue and global stack. + drain_local_queue(false); + drain_global_stack(false); + } else { + break; + } + } +} + +void G1CMTask::attempt_termination(bool is_serial) { + // We cannot check whether the global stack is empty, since other + // tasks might be concurrently pushing objects on it. + // Separated the asserts so that we know which one fires. + assert(_cm->out_of_regions(), "only way to reach here"); + assert(_task_queue->size() == 0, "only way to reach here"); + double termination_start_time_ms = os::elapsedTime() * 1000.0; + + // The G1CMTask class also extends the TerminatorTerminator class, + // hence its should_exit_termination() method will also decide + // whether to exit the termination protocol or not. + bool finished = (is_serial || + _cm->terminator()->offer_termination(this)); + _termination_time_ms += (os::elapsedTime() * 1000.0 - termination_start_time_ms); + + if (finished) { + // We're all done. + + // We can now guarantee that the global stack is empty, since + // all other tasks have finished. We separated the guarantees so + // that, if a condition is false, we can immediately find out + // which one. + guarantee(_cm->out_of_regions(), "only way to reach here"); + guarantee(_cm->mark_stack_empty(), "only way to reach here"); + guarantee(_task_queue->size() == 0, "only way to reach here"); + guarantee(!_cm->has_overflown(), "only way to reach here"); + guarantee(!has_aborted(), "should never happen if termination has completed"); + } else { + // Apparently there's more work to do. Let's abort this task. We + // will restart it and hopefully we can find more things to do. + set_has_aborted(); + } +} + +void G1CMTask::handle_abort(bool is_serial, double elapsed_time_ms) { + if (_has_timed_out) { + double diff_ms = elapsed_time_ms - _time_target_ms; + // Keep statistics of how well we did with respect to hitting + // our target only if we actually timed out (if we aborted for + // other reasons, then the results might get skewed). + _marking_step_diff_ms.add(diff_ms); + } + + if (!_cm->has_overflown()) { + return; + } + + // This is the interesting one. We aborted because a global + // overflow was raised. This means we have to restart the + // marking phase and start iterating over regions. However, in + // order to do this we have to make sure that all tasks stop + // what they are doing and re-initialize in a safe manner. We + // will achieve this with the use of two barrier sync points. + if (!is_serial) { + // We only need to enter the sync barrier if being called + // from a parallel context + _cm->enter_first_sync_barrier(_worker_id); + + // When we exit this sync barrier we know that all tasks have + // stopped doing marking work. So, it's now safe to + // re-initialize our data structures. + } + + clear_region_fields(); + flush_mark_stats_cache(); + + if (!is_serial) { + // If we're executing the concurrent phase of marking, reset the marking + // state; otherwise the marking state is reset after reference processing, + // during the remark pause. + // If we reset here as a result of an overflow during the remark we will + // see assertion failures from any subsequent set_concurrency_and_phase() + // calls. + if (_cm->concurrent() && _worker_id == 0) { + // Worker 0 is responsible for clearing the global data structures because + // of an overflow. During STW we should not clear the overflow flag (in + // G1ConcurrentMark::reset_marking_state()) since we rely on it being true when we exit + // method to abort the pause and restart concurrent marking. + _cm->reset_marking_for_restart(); + + log_info(gc, marking)("Concurrent Mark reset for overflow"); + } + + // ...and enter the second barrier. + _cm->enter_second_sync_barrier(_worker_id); + } +} + /***************************************************************************** The do_marking_step(time_target_ms, ...) method is the building @@ -2653,123 +2861,27 @@ void G1CMTask::do_marking_step(double time_target_ms, drain_global_stack(true); do { - if (!has_aborted() && _curr_region != nullptr) { - // This means that we're already holding on to a region. - assert(_finger != nullptr, "if region is not null, then the finger " - "should not be null either"); - - // We might have restarted this task after an evacuation pause - // which might have evacuated the region we're holding on to - // underneath our feet. Let's read its limit again to make sure - // that we do not iterate over a region of the heap that - // contains garbage (update_region_limit() will also move - // _finger to the start of the region if it is found empty). - update_region_limit(); - // We will start from _finger not from the start of the region, - // as we might be restarting this task after aborting half-way - // through scanning this region. In this case, _finger points to - // the address where we last found a marked object. If this is a - // fresh region, _finger points to start(). - MemRegion mr = MemRegion(_finger, _region_limit); - - assert(!_curr_region->is_humongous() || mr.start() == _curr_region->bottom(), - "humongous regions should go around loop once only"); - - // Some special cases: - // If the memory region is empty, we can just give up the region. - // If the current region is humongous then we only need to check - // the bitmap for the bit associated with the start of the object, - // scan the object if it's live, and give up the region. - // Otherwise, let's iterate over the bitmap of the part of the region - // that is left. - // If the iteration is successful, give up the region. - if (mr.is_empty()) { - giveup_current_region(); - abort_marking_if_regular_check_fail(); - } else if (_curr_region->is_humongous() && mr.start() == _curr_region->bottom()) { - if (_mark_bitmap->is_marked(mr.start())) { - // The object is marked - apply the closure - bitmap_closure.do_addr(mr.start()); - } - // Even if this task aborted while scanning the humongous object - // we can (and should) give up the current region. - giveup_current_region(); - abort_marking_if_regular_check_fail(); - } else if (_mark_bitmap->iterate(&bitmap_closure, mr)) { - giveup_current_region(); - abort_marking_if_regular_check_fail(); - } else { - assert(has_aborted(), "currently the only way to do so"); - // The only way to abort the bitmap iteration is to return - // false from the do_bit() method. However, inside the - // do_bit() method we move the _finger to point to the - // object currently being looked at. So, if we bail out, we - // have definitely set _finger to something non-null. - assert(_finger != nullptr, "invariant"); - - // Region iteration was actually aborted. So now _finger - // points to the address of the object we last scanned. If we - // leave it there, when we restart this task, we will rescan - // the object. It is easy to avoid this. We move the finger by - // enough to point to the next possible object header. - assert(_finger < _region_limit, "invariant"); - HeapWord* const new_finger = _finger + cast_to_oop(_finger)->size(); - // Check if bitmap iteration was aborted while scanning the last object - if (new_finger >= _region_limit) { - giveup_current_region(); - } else { - move_finger_to(new_finger); - } - } - } + process_current_region(bitmap_closure); // At this point we have either completed iterating over the // region we were holding on to, or we have aborted. // We then partially drain the local queue and the global stack. - // (Do we really need this?) drain_local_queue(true); drain_global_stack(true); - // Read the note on the claim_region() method on why it might - // return null with potentially more regions available for - // claiming and why we have to check out_of_regions() to determine - // whether we're done or not. - while (!has_aborted() && _curr_region == nullptr && !_cm->out_of_regions()) { - // We are going to try to claim a new region. We should have - // given up on the previous one. - // Separated the asserts so that we know which one fires. - assert(_curr_region == nullptr, "invariant"); - assert(_finger == nullptr, "invariant"); - assert(_region_limit == nullptr, "invariant"); - G1HeapRegion* claimed_region = _cm->claim_region(_worker_id); - if (claimed_region != nullptr) { - // Yes, we managed to claim one - setup_for_region(claimed_region); - assert(_curr_region == claimed_region, "invariant"); - } - // It is important to call the regular clock here. It might take - // a while to claim a region if, for example, we hit a large - // block of empty regions. So we need to call the regular clock - // method once round the loop to make sure it's called - // frequently enough. - abort_marking_if_regular_check_fail(); - } + claim_new_region(); - if (!has_aborted() && _curr_region == nullptr) { - assert(_cm->out_of_regions(), - "at this point we should be out of regions"); - } + assert(has_aborted() || _curr_region != nullptr || _cm->out_of_regions(), + "at this point we should be out of regions"); } while ( _curr_region != nullptr && !has_aborted()); - if (!has_aborted()) { - // We cannot check whether the global stack is empty, since other - // tasks might be pushing objects to it concurrently. - assert(_cm->out_of_regions(), - "at this point we should be out of regions"); - // Try to reduce the number of available SATB buffers so that - // remark has less work to do. - drain_satb_buffers(); - } + // We cannot check whether the global stack is empty, since other + // tasks might be pushing objects to it concurrently. + assert(has_aborted() || _cm->out_of_regions(), + "at this point we should be out of regions"); + // Try to reduce the number of available SATB buffers so that + // remark has less work to do. + drain_satb_buffers(); // Since we've done everything else, we can now totally drain the // local queue and global stack. @@ -2780,60 +2892,13 @@ void G1CMTask::do_marking_step(double time_target_ms, if (do_stealing && !has_aborted()) { // We have not aborted. This means that we have finished all that // we could. Let's try to do some stealing... - - // We cannot check whether the global stack is empty, since other - // tasks might be pushing objects to it concurrently. - assert(_cm->out_of_regions() && _task_queue->size() == 0, - "only way to reach here"); - while (!has_aborted()) { - G1TaskQueueEntry entry; - if (_cm->try_stealing(_worker_id, entry)) { - scan_task_entry(entry); - - // And since we're towards the end, let's totally drain the - // local queue and global stack. - drain_local_queue(false); - drain_global_stack(false); - } else { - break; - } - } + attempt_stealing(); } // We still haven't aborted. Now, let's try to get into the // termination protocol. if (do_termination && !has_aborted()) { - // We cannot check whether the global stack is empty, since other - // tasks might be concurrently pushing objects on it. - // Separated the asserts so that we know which one fires. - assert(_cm->out_of_regions(), "only way to reach here"); - assert(_task_queue->size() == 0, "only way to reach here"); - double termination_start_time_ms = os::elapsedTime() * 1000.0; - - // The G1CMTask class also extends the TerminatorTerminator class, - // hence its should_exit_termination() method will also decide - // whether to exit the termination protocol or not. - bool finished = (is_serial || - _cm->terminator()->offer_termination(this)); - _termination_time_ms += (os::elapsedTime() * 1000.0 - termination_start_time_ms); - - if (finished) { - // We're all done. - - // We can now guarantee that the global stack is empty, since - // all other tasks have finished. We separated the guarantees so - // that, if a condition is false, we can immediately find out - // which one. - guarantee(_cm->out_of_regions(), "only way to reach here"); - guarantee(_cm->mark_stack_empty(), "only way to reach here"); - guarantee(_task_queue->size() == 0, "only way to reach here"); - guarantee(!_cm->has_overflown(), "only way to reach here"); - guarantee(!has_aborted(), "should never happen if termination has completed"); - } else { - // Apparently there's more work to do. Let's abort this task. It - // will restart it and we can hopefully find more things to do. - set_has_aborted(); - } + attempt_termination(is_serial); } // Mainly for debugging purposes to make sure that a pointer to the @@ -2847,59 +2912,7 @@ void G1CMTask::do_marking_step(double time_target_ms, if (has_aborted()) { // The task was aborted for some reason. - if (_has_timed_out) { - double diff_ms = elapsed_time_ms - _time_target_ms; - // Keep statistics of how well we did with respect to hitting - // our target only if we actually timed out (if we aborted for - // other reasons, then the results might get skewed). - _marking_step_diff_ms.add(diff_ms); - } - - if (_cm->has_overflown()) { - // This is the interesting one. We aborted because a global - // overflow was raised. This means we have to restart the - // marking phase and start iterating over regions. However, in - // order to do this we have to make sure that all tasks stop - // what they are doing and re-initialize in a safe manner. We - // will achieve this with the use of two barrier sync points. - - if (!is_serial) { - // We only need to enter the sync barrier if being called - // from a parallel context - _cm->enter_first_sync_barrier(_worker_id); - - // When we exit this sync barrier we know that all tasks have - // stopped doing marking work. So, it's now safe to - // re-initialize our data structures. - } - - clear_region_fields(); - flush_mark_stats_cache(); - - if (!is_serial) { - // If we're executing the concurrent phase of marking, reset the marking - // state; otherwise the marking state is reset after reference processing, - // during the remark pause. - // If we reset here as a result of an overflow during the remark we will - // see assertion failures from any subsequent set_concurrency_and_phase() - // calls. - if (_cm->concurrent() && _worker_id == 0) { - // Worker 0 is responsible for clearing the global data structures because - // of an overflow. During STW we should not clear the overflow flag (in - // G1ConcurrentMark::reset_marking_state()) since we rely on it being true when we exit - // method to abort the pause and restart concurrent marking. - _cm->reset_marking_for_restart(); - - log_info(gc, marking)("Concurrent Mark reset for overflow"); - } - - // ...and enter the second barrier. - _cm->enter_second_sync_barrier(_worker_id); - } - // At this point, if we're during the concurrent phase of - // marking, everything has been re-initialized and we're - // ready to restart. - } + handle_abort(is_serial, elapsed_time_ms); } } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index b197afc65ee..fed624df851 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -810,6 +810,21 @@ class G1CMTask : public TerminatorTerminator { // Makes the limit of the region up-to-date void update_region_limit(); + // Handles the processing of the current region. + void process_current_region(G1CMBitMapClosure& bitmap_closure); + + // Claims a new region if available. + void claim_new_region(); + + // Attempts to steal work from other tasks. + void attempt_stealing(); + + // Handles the termination protocol. + void attempt_termination(bool is_serial); + + // Handles the has_aborted scenario. + void handle_abort(bool is_serial, double elapsed_time_ms); + // Called when either the words scanned or the refs visited limit // has been reached void reached_limit(); diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index bb5ac5036fe..7ae81de1d07 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -755,27 +755,71 @@ class G1ScanAndCountNMethodClosure : public NMethodClosure { // Heap region closure to be applied to all regions in the current collection set // increment to fix up non-card related roots. -class G1ScanCollectionSetRegionClosure : public G1HeapRegionClosure { +class G1ScanCodeRootsClosure : public G1HeapRegionClosure { G1ParScanThreadState* _pss; G1RemSetScanState* _scan_state; - G1GCPhaseTimes::GCParPhases _scan_phase; - G1GCPhaseTimes::GCParPhases _code_roots_phase; - uint _worker_id; size_t _code_roots_scanned; +public: + G1ScanCodeRootsClosure(G1RemSetScanState* scan_state, + G1ParScanThreadState* pss, + uint worker_id) : + _pss(pss), + _scan_state(scan_state), + _worker_id(worker_id), + _code_roots_scanned(0) { } + + bool do_heap_region(G1HeapRegion* r) { + // Scan the code root list attached to the current region + G1ScanAndCountNMethodClosure cl(_pss->closures()->weak_nmethods()); + r->code_roots_do(&cl); + _code_roots_scanned += cl.count(); + return false; + } + + size_t code_roots_scanned() const { return _code_roots_scanned; } +}; + +void G1RemSet::scan_collection_set_code_roots(G1ParScanThreadState* pss, + uint worker_id, + G1GCPhaseTimes::GCParPhases coderoots_phase, + G1GCPhaseTimes::GCParPhases objcopy_phase) { + EventGCPhaseParallel event; + + Tickspan code_root_scan_time; + Tickspan code_root_trim_partially_time; + G1EvacPhaseWithTrimTimeTracker timer(pss, code_root_scan_time, code_root_trim_partially_time); + + G1GCPhaseTimes* p = _g1h->phase_times(); + + G1ScanCodeRootsClosure cl(_scan_state, pss, worker_id); + // Code roots work distribution occurs inside the iteration method. So scan all collection + // set regions for all threads. + _g1h->collection_set_iterate_increment_from(&cl, worker_id); + + p->record_or_add_time_secs(coderoots_phase, worker_id, code_root_scan_time.seconds()); + p->add_time_secs(objcopy_phase, worker_id, code_root_trim_partially_time.seconds()); + + p->record_or_add_thread_work_item(coderoots_phase, worker_id, cl.code_roots_scanned(), G1GCPhaseTimes::CodeRootsScannedNMethods); + + event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(coderoots_phase)); +} + +class G1ScanOptionalRemSetRootsClosure : public G1HeapRegionClosure { + G1ParScanThreadState* _pss; + + uint _worker_id; + + G1GCPhaseTimes::GCParPhases _scan_phase; + size_t _opt_roots_scanned; + size_t _opt_refs_scanned; size_t _opt_refs_memory_used; - Tickspan _code_root_scan_time; - Tickspan _code_trim_partially_time; - - Tickspan _rem_set_opt_root_scan_time; - Tickspan _rem_set_opt_trim_partially_time; - void scan_opt_rem_set_roots(G1HeapRegion* r) { G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r); @@ -786,92 +830,58 @@ class G1ScanCollectionSetRegionClosure : public G1HeapRegionClosure { } public: - G1ScanCollectionSetRegionClosure(G1RemSetScanState* scan_state, - G1ParScanThreadState* pss, + G1ScanOptionalRemSetRootsClosure(G1ParScanThreadState* pss, uint worker_id, - G1GCPhaseTimes::GCParPhases scan_phase, - G1GCPhaseTimes::GCParPhases code_roots_phase) : + G1GCPhaseTimes::GCParPhases scan_phase) : _pss(pss), - _scan_state(scan_state), - _scan_phase(scan_phase), - _code_roots_phase(code_roots_phase), _worker_id(worker_id), - _code_roots_scanned(0), + _scan_phase(scan_phase), _opt_roots_scanned(0), _opt_refs_scanned(0), - _opt_refs_memory_used(0), - _code_root_scan_time(), - _code_trim_partially_time(), - _rem_set_opt_root_scan_time(), - _rem_set_opt_trim_partially_time() { } + _opt_refs_memory_used(0) { } - bool do_heap_region(G1HeapRegion* r) { - // The individual references for the optional remembered set are per-worker, so we - // always need to scan them. + bool do_heap_region(G1HeapRegion* r) override { if (r->has_index_in_opt_cset()) { - EventGCPhaseParallel event; - G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_opt_root_scan_time, _rem_set_opt_trim_partially_time); scan_opt_rem_set_roots(r); - - event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_scan_phase)); - } - - // Scan code root remembered sets. - { - EventGCPhaseParallel event; - G1EvacPhaseWithTrimTimeTracker timer(_pss, _code_root_scan_time, _code_trim_partially_time); - G1ScanAndCountNMethodClosure cl(_pss->closures()->weak_nmethods()); - - // Scan the code root list attached to the current region - r->code_roots_do(&cl); - - _code_roots_scanned += cl.count(); - - event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_code_roots_phase)); } - return false; } - Tickspan code_root_scan_time() const { return _code_root_scan_time; } - Tickspan code_root_trim_partially_time() const { return _code_trim_partially_time; } - - size_t code_roots_scanned() const { return _code_roots_scanned; } - - Tickspan rem_set_opt_root_scan_time() const { return _rem_set_opt_root_scan_time; } - Tickspan rem_set_opt_trim_partially_time() const { return _rem_set_opt_trim_partially_time; } - size_t opt_roots_scanned() const { return _opt_roots_scanned; } size_t opt_refs_scanned() const { return _opt_refs_scanned; } size_t opt_refs_memory_used() const { return _opt_refs_memory_used; } }; -void G1RemSet::scan_collection_set_regions(G1ParScanThreadState* pss, - uint worker_id, - G1GCPhaseTimes::GCParPhases scan_phase, - G1GCPhaseTimes::GCParPhases coderoots_phase, - G1GCPhaseTimes::GCParPhases objcopy_phase) { - G1ScanCollectionSetRegionClosure cl(_scan_state, pss, worker_id, scan_phase, coderoots_phase); - _g1h->collection_set_iterate_increment_from(&cl, worker_id); +void G1RemSet::scan_collection_set_optional_roots(G1ParScanThreadState* pss, + uint worker_id, + G1GCPhaseTimes::GCParPhases scan_phase, + G1GCPhaseTimes::GCParPhases objcopy_phase) { + assert(scan_phase == G1GCPhaseTimes::OptScanHR, "must be"); + + EventGCPhaseParallel event; + + Tickspan rem_set_opt_root_scan_time; + Tickspan rem_set_opt_trim_partially_time; + G1EvacPhaseWithTrimTimeTracker timer(pss, rem_set_opt_root_scan_time, rem_set_opt_trim_partially_time); G1GCPhaseTimes* p = _g1h->phase_times(); - p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_root_scan_time().seconds()); - p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_trim_partially_time().seconds()); + G1ScanOptionalRemSetRootsClosure cl(pss, worker_id, scan_phase); + // The individual references for the optional remembered set are per-worker, so every worker + // always need to scan all regions (no claimer). + _g1h->collection_set_iterate_increment_from(&cl, worker_id); - p->record_or_add_time_secs(coderoots_phase, worker_id, cl.code_root_scan_time().seconds()); - p->record_or_add_thread_work_item(coderoots_phase, worker_id, cl.code_roots_scanned(), G1GCPhaseTimes::CodeRootsScannedNMethods); + p->record_or_add_time_secs(scan_phase, worker_id, rem_set_opt_root_scan_time.seconds()); + p->record_or_add_time_secs(objcopy_phase, worker_id, rem_set_opt_trim_partially_time.seconds()); - p->add_time_secs(objcopy_phase, worker_id, cl.code_root_trim_partially_time().seconds()); + p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_roots_scanned(), G1GCPhaseTimes::ScanHRFoundRoots); + p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanHRScannedOptRefs); + p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanHRUsedMemory); - // At this time we record some metrics only for the evacuations after the initial one. - if (scan_phase == G1GCPhaseTimes::OptScanHR) { - p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_roots_scanned(), G1GCPhaseTimes::ScanHRFoundRoots); - p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanHRScannedOptRefs); - p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanHRUsedMemory); - } + event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(scan_phase)); } + #ifdef ASSERT void G1RemSet::assert_scan_top_is_null(uint hrm_index) { assert(_scan_state->scan_top(hrm_index) == nullptr, diff --git a/src/hotspot/share/gc/g1/g1RemSet.hpp b/src/hotspot/share/gc/g1/g1RemSet.hpp index 0445ad185d3..ae4d4a35c45 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.hpp +++ b/src/hotspot/share/gc/g1/g1RemSet.hpp @@ -112,11 +112,15 @@ class G1RemSet: public CHeapObj { // Do work for regions in the current increment of the collection set, scanning // non-card based (heap) roots. - void scan_collection_set_regions(G1ParScanThreadState* pss, - uint worker_id, - G1GCPhaseTimes::GCParPhases scan_phase, - G1GCPhaseTimes::GCParPhases coderoots_phase, - G1GCPhaseTimes::GCParPhases objcopy_phase); + void scan_collection_set_code_roots(G1ParScanThreadState* pss, + uint worker_id, + G1GCPhaseTimes::GCParPhases coderoots_phase, + G1GCPhaseTimes::GCParPhases objcopy_phase); + + void scan_collection_set_optional_roots(G1ParScanThreadState* pss, + uint worker_id, + G1GCPhaseTimes::GCParPhases scan_phase, + G1GCPhaseTimes::GCParPhases objcopy_phase); // Two methods for concurrent refinement support, executed concurrently to // the mutator: diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index f3590aa2ff6..13c4e9949ed 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -591,8 +591,10 @@ class G1EvacuateRegionsBaseTask : public WorkerTask { protected: G1CollectedHeap* _g1h; G1ParScanThreadStateSet* _per_thread_states; + G1ScannerTasksQueueSet* _task_queues; TaskTerminator _terminator; + uint _num_workers; void evacuate_live_objects(G1ParScanThreadState* pss, @@ -667,7 +669,22 @@ class G1EvacuateRegionsTask : public G1EvacuateRegionsBaseTask { void scan_roots(G1ParScanThreadState* pss, uint worker_id) { _root_processor->evacuate_roots(pss, worker_id); _g1h->rem_set()->scan_heap_roots(pss, worker_id, G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::ObjCopy, _has_optional_evacuation_work); - _g1h->rem_set()->scan_collection_set_regions(pss, worker_id, G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::CodeRoots, G1GCPhaseTimes::ObjCopy); + _g1h->rem_set()->scan_collection_set_code_roots(pss, worker_id, G1GCPhaseTimes::CodeRoots, G1GCPhaseTimes::ObjCopy); + // There are no optional roots to scan right now. +#ifdef ASSERT + class VerifyOptionalCollectionSetRootsEmptyClosure : public G1HeapRegionClosure { + G1ParScanThreadState* _pss; + + public: + VerifyOptionalCollectionSetRootsEmptyClosure(G1ParScanThreadState* pss) : _pss(pss) { } + + bool do_heap_region(G1HeapRegion* r) override { + assert(!r->has_index_in_opt_cset(), "must be"); + return false; + } + } cl(pss); + _g1h->collection_set_iterate_increment_from(&cl, worker_id); +#endif } void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) { @@ -736,7 +753,8 @@ class G1EvacuateOptionalRegionsTask : public G1EvacuateRegionsBaseTask { void scan_roots(G1ParScanThreadState* pss, uint worker_id) { _g1h->rem_set()->scan_heap_roots(pss, worker_id, G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::OptObjCopy, true /* remember_already_scanned_cards */); - _g1h->rem_set()->scan_collection_set_regions(pss, worker_id, G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::OptCodeRoots, G1GCPhaseTimes::OptObjCopy); + _g1h->rem_set()->scan_collection_set_code_roots(pss, worker_id, G1GCPhaseTimes::OptCodeRoots, G1GCPhaseTimes::OptObjCopy); + _g1h->rem_set()->scan_collection_set_optional_roots(pss, worker_id, G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::ObjCopy); } void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) { diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp index fbaef426b51..8eaa23ab476 100644 --- a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp @@ -140,7 +140,8 @@ LIR_Opr BarrierSetC1::atomic_add_at(LIRAccess& access, LIRItem& value) { void BarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) { DecoratorSet decorators = access.decorators(); - bool is_volatile = (((decorators & MO_SEQ_CST) != 0) || AlwaysAtomicAccesses); + bool is_volatile = (decorators & MO_SEQ_CST) != 0; + bool is_atomic = is_volatile || AlwaysAtomicAccesses; bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0; bool mask_boolean = (decorators & C1_MASK_BOOLEAN) != 0; LIRGenerator* gen = access.gen(); @@ -154,7 +155,7 @@ void BarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) { } LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; - if (is_volatile && !needs_patching) { + if (is_atomic && !needs_patching) { gen->volatile_field_store(value, access.resolved_addr()->as_address_ptr(), access.access_emit_info()); } else { __ store(value, access.resolved_addr()->as_address_ptr(), access.access_emit_info(), patch_code); @@ -168,7 +169,8 @@ void BarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) { void BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { LIRGenerator *gen = access.gen(); DecoratorSet decorators = access.decorators(); - bool is_volatile = (((decorators & MO_SEQ_CST) != 0) || AlwaysAtomicAccesses); + bool is_volatile = (decorators & MO_SEQ_CST) != 0; + bool is_atomic = is_volatile || AlwaysAtomicAccesses; bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0; bool mask_boolean = (decorators & C1_MASK_BOOLEAN) != 0; bool in_native = (decorators & IN_NATIVE) != 0; @@ -180,7 +182,7 @@ void BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; if (in_native) { __ move_wide(access.resolved_addr()->as_address_ptr(), result); - } else if (is_volatile && !needs_patching) { + } else if (is_atomic && !needs_patching) { gen->volatile_field_load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info()); } else { __ load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info(), patch_code); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp index 8d10b7cbfcf..e7d5a2e00c5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp @@ -253,9 +253,9 @@ void ShenandoahPacer::pace_for_alloc(size_t words) { return; } - jlong const max_delay = ShenandoahPacingMaxDelay * NANOSECS_PER_MILLISEC; - jlong const start_time = os::elapsed_counter(); - while (!claimed && (os::elapsed_counter() - start_time) < max_delay) { + jlong const start_time = os::javaTimeNanos(); + jlong const deadline = start_time + (ShenandoahPacingMaxDelay * NANOSECS_PER_MILLISEC); + while (!claimed && os::javaTimeNanos() < deadline) { // We could instead assist GC, but this would suffice for now. wait(1); claimed = claim_for_alloc(words); @@ -267,7 +267,7 @@ void ShenandoahPacer::pace_for_alloc(size_t words) { claimed = claim_for_alloc(words); assert(claimed, "Should always succeed"); } - ShenandoahThreadLocalData::add_paced_time(current, (double)(os::elapsed_counter() - start_time) / NANOSECS_PER_SEC); + ShenandoahThreadLocalData::add_paced_time(current, (double)(os::javaTimeNanos() - start_time) / NANOSECS_PER_SEC); } void ShenandoahPacer::wait(size_t time_ms) { @@ -276,7 +276,7 @@ void ShenandoahPacer::wait(size_t time_ms) { assert(time_ms > 0, "Should not call this with zero argument, as it would stall until notify"); assert(time_ms <= LONG_MAX, "Sanity"); MonitorLocker locker(_wait_monitor); - _wait_monitor->wait((long)time_ms); + _wait_monitor->wait(time_ms); } void ShenandoahPacer::notify_waiters() { diff --git a/src/hotspot/share/gc/z/zHeap.cpp b/src/hotspot/share/gc/z/zHeap.cpp index 1e917bb5ee3..d29a5d15795 100644 --- a/src/hotspot/share/gc/z/zHeap.cpp +++ b/src/hotspot/share/gc/z/zHeap.cpp @@ -248,10 +248,6 @@ void ZHeap::free_page(ZPage* page, bool allow_defragment) { // Remove page table entry _page_table.remove(page); - if (page->is_old()) { - page->remset_delete(); - } - // Free page _page_allocator.free_page(page, allow_defragment); } @@ -262,9 +258,6 @@ size_t ZHeap::free_empty_pages(const ZArray* pages) { ZArrayIterator iter(pages); for (ZPage* page; iter.next(&page);) { _page_table.remove(page); - if (page->is_old()) { - page->remset_delete(); - } freed += page->size(); } diff --git a/src/hotspot/share/gc/z/zPageAllocator.cpp b/src/hotspot/share/gc/z/zPageAllocator.cpp index 12c17468bfb..ecd9f3e34b9 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.cpp +++ b/src/hotspot/share/gc/z/zPageAllocator.cpp @@ -809,6 +809,11 @@ ZPage* ZPageAllocator::prepare_to_recycle(ZPage* page, bool allow_defragment) { return defragment_page(to_recycle); } + // Remove the remset before recycling + if (to_recycle->is_old() && to_recycle == page) { + to_recycle->remset_delete(); + } + return to_recycle; } @@ -880,18 +885,9 @@ void ZPageAllocator::free_pages(const ZArray* pages) { } void ZPageAllocator::free_pages_alloc_failed(ZPageAllocation* allocation) { - ZArray to_recycle_pages; - - // Prepare pages for recycling before taking the lock - ZListRemoveIterator allocation_pages_iter(allocation->pages()); - for (ZPage* page; allocation_pages_iter.next(&page);) { - // Prepare to recycle - ZPage* const to_recycle = prepare_to_recycle(page, false /* allow_defragment */); - - // Register for recycling - to_recycle_pages.push(to_recycle); - } - + // The page(s) in the allocation are either taken from the cache or a newly + // created, mapped and commited ZPage. These page(s) have not been inserted in + // the page table, nor allocated a remset, so prepare_to_recycle is not required. ZLocker locker(&_lock); // Only decrease the overall used and not the generation used, @@ -901,7 +897,7 @@ void ZPageAllocator::free_pages_alloc_failed(ZPageAllocation* allocation) { size_t freed = 0; // Free any allocated/flushed pages - ZArrayIterator iter(&to_recycle_pages); + ZListRemoveIterator iter(allocation->pages()); for (ZPage* page; iter.next(&page);) { freed += page->size(); recycle_page(page); diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index e50d758335c..bc46a2cf852 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -326,12 +326,6 @@ JVM_GetNextThreadIdOffset(JNIEnv *env, jclass threadClass); JNIEXPORT void JNICALL JVM_RegisterContinuationMethods(JNIEnv *env, jclass cls); -/* - * java.lang.SecurityManager - */ -JNIEXPORT jobjectArray JNICALL -JVM_GetClassContext(JNIEnv *env); - /* * java.lang.Package */ diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 1d8268dbda6..cb85513eed0 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -949,6 +949,15 @@ void InterpreterRuntime::resolve_invokehandle(JavaThread* current) { pool->cache()->set_method_handle(method_index, info); } +void InterpreterRuntime::cds_resolve_invokehandle(int raw_index, + constantPoolHandle& pool, TRAPS) { + const Bytecodes::Code bytecode = Bytecodes::_invokehandle; + CallInfo info; + LinkResolver::resolve_invoke(info, Handle(), pool, raw_index, bytecode, CHECK); + + pool->cache()->set_method_handle(raw_index, info); +} + // First time execution: Resolve symbols, create a permanent CallSite object. void InterpreterRuntime::resolve_invokedynamic(JavaThread* current) { LastFrameAccessor last_frame(current); @@ -968,6 +977,14 @@ void InterpreterRuntime::resolve_invokedynamic(JavaThread* current) { pool->cache()->set_dynamic_call(info, index); } +void InterpreterRuntime::cds_resolve_invokedynamic(int raw_index, + constantPoolHandle& pool, TRAPS) { + const Bytecodes::Code bytecode = Bytecodes::_invokedynamic; + CallInfo info; + LinkResolver::resolve_invoke(info, Handle(), pool, raw_index, bytecode, CHECK); + pool->cache()->set_dynamic_call(info, raw_index); +} + // This function is the interface to the assembly code. It returns the resolved // cpCache entry. This doesn't safepoint, but the helper routines safepoint. // This function will check for redefinition! diff --git a/src/hotspot/share/interpreter/interpreterRuntime.hpp b/src/hotspot/share/interpreter/interpreterRuntime.hpp index 61041694fc6..3635433f434 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.hpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.hpp @@ -92,12 +92,15 @@ class InterpreterRuntime: AllStatic { static void resolve_from_cache(JavaThread* current, Bytecodes::Code bytecode); - // Used by ClassPrelinker + // Used by AOTConstantPoolResolver static void resolve_get_put(Bytecodes::Code bytecode, int field_index, methodHandle& m, constantPoolHandle& pool, bool initialize_holder, TRAPS); static void cds_resolve_invoke(Bytecodes::Code bytecode, int method_index, constantPoolHandle& pool, TRAPS); - + static void cds_resolve_invokehandle(int raw_index, + constantPoolHandle& pool, TRAPS); + static void cds_resolve_invokedynamic(int raw_index, + constantPoolHandle& pool, TRAPS); private: // Statics & fields static void resolve_get_put(JavaThread* current, Bytecodes::Code bytecode); diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index 92d95b43e40..6300b660092 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -496,7 +496,6 @@ Method* LinkResolver::lookup_polymorphic_method(const LinkInfo& link_info, Klass* natives = vmClasses::MethodHandleNatives_klass(); if (natives == nullptr || InstanceKlass::cast(natives)->is_not_initialized()) { SystemDictionary::resolve_or_fail(vmSymbols::java_lang_invoke_MethodHandleNatives(), - Handle(), Handle(), true, CHECK_NULL); diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp index bb91016e522..c2a40164787 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp +++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -1202,7 +1202,7 @@ static ClassFileStream* schema_extend_event_klass_bytes(const InstanceKlass* ik, orig_stream->skip_u1_fast(attrib_len); } } - return new ClassFileStream(new_buffer, orig_stream_length, nullptr, ClassFileStream::verify); + return new ClassFileStream(new_buffer, orig_stream_length, nullptr); } // Attempt to locate an existing UTF8_INFO mapping the utf8_constant. @@ -1510,7 +1510,7 @@ static ClassFileStream* schema_extend_event_subklass_bytes(const InstanceKlass* size_of_new_bytes = size_of_instrumented_bytes; is_instrumented = true; } - return new ClassFileStream(new_bytes, size_of_new_bytes, nullptr, ClassFileStream::verify); + return new ClassFileStream(new_bytes, size_of_new_bytes, nullptr); } static bool _force_instrumentation = false; @@ -1547,7 +1547,7 @@ static ClassFileStream* retransform_bytes(const Klass* existing_klass, const Cla assert(new_bytes != nullptr, "invariant"); assert(size_of_new_bytes > 0, "invariant"); is_instrumented = true; - return new ClassFileStream(new_bytes, size_of_new_bytes, nullptr, ClassFileStream::verify); + return new ClassFileStream(new_bytes, size_of_new_bytes, nullptr); } // On initial class load. diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index d60baa3c1cc..143248ef714 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -169,7 +169,7 @@ NO_TRANSITION(jboolean, jfr_set_throttle(JNIEnv* env, jclass jvm, jlong event_ty return JNI_TRUE; NO_TRANSITION_END -NO_TRANSITION(void, jfr_set_miscellaneous(JNIEnv* env, jobject jvm, jlong event_type_id, jlong value)) +NO_TRANSITION(void, jfr_set_miscellaneous(JNIEnv* env, jclass jvm, jlong event_type_id, jlong value)) JfrEventSetting::set_miscellaneous(event_type_id, value); const JfrEventId typed_event_id = (JfrEventId)event_type_id; if (EventDeprecatedInvocation::eventId == typed_event_id) { diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp index ece4425782d..5020920945e 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp @@ -101,7 +101,7 @@ jboolean JNICALL jfr_is_available(JNIEnv* env, jclass jvm); jdouble JNICALL jfr_time_conv_factor(JNIEnv* env, jclass jvm); -jlong JNICALL jfr_type_id(JNIEnv* env, jobject jvm, jclass jc); +jlong JNICALL jfr_type_id(JNIEnv* env, jclass jvm, jclass jc); void JNICALL jfr_set_repository_location(JNIEnv* env, jclass jvm, jstring location); @@ -129,7 +129,7 @@ jlong JNICALL jfr_get_unloaded_event_classes_count(JNIEnv* env, jclass jvm); jboolean JNICALL jfr_set_throttle(JNIEnv* env, jclass jvm, jlong event_type_id, jlong event_sample_size, jlong period_ms); -void JNICALL jfr_set_miscellaneous(JNIEnv* env, jobject jvm, jlong id, jlong value); +void JNICALL jfr_set_miscellaneous(JNIEnv* env, jclass jvm, jlong id, jlong value); void JNICALL jfr_emit_old_object_samples(JNIEnv* env, jclass jvm, jlong cutoff_ticks, jboolean, jboolean); diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 3599df18544..aa8ce28b7c5 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -613,10 +613,8 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU JVMCIKlassHandle resolved_klass(THREAD); Klass* accessing_klass = UNPACK_PAIR(Klass, accessing_klass); Handle class_loader; - Handle protection_domain; if (accessing_klass != nullptr) { class_loader = Handle(THREAD, accessing_klass->class_loader()); - protection_domain = Handle(THREAD, accessing_klass->protection_domain()); } else { switch (accessing_klass_loader) { case 0: break; // class_loader is already null, the boot loader @@ -629,23 +627,21 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU } if (resolve) { - resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, protection_domain, true, CHECK_NULL); + resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, true, CHECK_NULL); } else { if (Signature::has_envelope(class_name)) { // This is a name from a signature. Strip off the trimmings. // Call recursive to keep scope of strippedsym. TempNewSymbol strippedsym = Signature::strip_envelope(class_name); resolved_klass = SystemDictionary::find_instance_klass(THREAD, strippedsym, - class_loader, - protection_domain); + class_loader); } else if (Signature::is_array(class_name)) { SignatureStream ss(class_name, false); int ndim = ss.skip_array_prefix(); if (ss.type() == T_OBJECT) { Symbol* strippedsym = ss.as_symbol(); resolved_klass = SystemDictionary::find_instance_klass(THREAD, strippedsym, - class_loader, - protection_domain); + class_loader); if (!resolved_klass.is_null()) { resolved_klass = resolved_klass->array_klass(ndim, CHECK_NULL); } @@ -654,8 +650,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU } } else { resolved_klass = SystemDictionary::find_instance_klass(THREAD, class_name, - class_loader, - protection_domain); + class_loader); } } JVMCIObject result = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL); diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 129a88ac4d7..c930910dd44 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -941,9 +941,8 @@ void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...) va_end(ap); JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - Handle h_loader = Handle(); - Handle h_protection_domain = Handle(); - Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader, h_protection_domain); + Handle h_loader; + Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader ); } else { JNIAccessMark jni(this, THREAD); jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 8241fc2498c..ac972e97b1b 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -1678,14 +1678,12 @@ Klass* JVMCIRuntime::get_klass_by_name_impl(Klass*& accessing_klass, } Handle loader; - Handle domain; if (accessing_klass != nullptr) { loader = Handle(THREAD, accessing_klass->class_loader()); - domain = Handle(THREAD, accessing_klass->protection_domain()); } Klass* found_klass = require_local ? - SystemDictionary::find_instance_or_array_klass(THREAD, sym, loader, domain) : + SystemDictionary::find_instance_or_array_klass(THREAD, sym, loader) : SystemDictionary::find_constrained_instance_or_array_klass(THREAD, sym, loader); // If we fail to find an array klass, look again for its element type. diff --git a/src/hotspot/share/logging/logDiagnosticCommand.hpp b/src/hotspot/share/logging/logDiagnosticCommand.hpp index 089bcdc48af..e63509bea9e 100644 --- a/src/hotspot/share/logging/logDiagnosticCommand.hpp +++ b/src/hotspot/share/logging/logDiagnosticCommand.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -59,7 +59,6 @@ class LogDiagnosticCommand : public DCmdWithParser { return "Lists current log configuration, enables/disables/configures a log output, or rotates all logs."; } - // Used by SecurityManager. This DCMD requires ManagementPermission = control. static const JavaPermission permission() { JavaPermission p = {"java.lang.management.ManagementPermission", "control", nullptr}; return p; diff --git a/src/hotspot/share/logging/logFileStreamOutput.cpp b/src/hotspot/share/logging/logFileStreamOutput.cpp index 76e67a45de2..dc34a9b8b14 100644 --- a/src/hotspot/share/logging/logFileStreamOutput.cpp +++ b/src/hotspot/share/logging/logFileStreamOutput.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ #include "logging/logMessageBuffer.hpp" #include "memory/allocation.inline.hpp" #include "utilities/defaultStream.hpp" +#include const char* const LogFileStreamOutput::FoldMultilinesOptionKey = "foldmultilines"; @@ -119,14 +120,35 @@ int LogFileStreamOutput::write_internal(const LogDecorations& decorations, const int written = 0; const bool use_decorations = !_decorators.is_empty(); - if (use_decorations) { - WRITE_LOG_WITH_RESULT_CHECK(write_decorations(decorations), written); - WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, " "), written); - } - if (!_fold_multilines) { - WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s\n", msg), written); + const char* base = msg; + int decorator_padding = 0; + if (use_decorations) { + WRITE_LOG_WITH_RESULT_CHECK(write_decorations(decorations), decorator_padding); + WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, " "), written); + } + written += decorator_padding; + + // Search for newlines in the string and repeatedly print the substrings that end + // with each newline. + const char* next = strstr(msg, "\n"); + while (next != nullptr) { // We have some newlines to print + int to_print = next - base; + WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%.*s\n", to_print, base), written); + if (use_decorations) { + WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "[%*c] ", decorator_padding - 2, ' '), written); // Substracting 2 because decorator_padding includes the brackets + } + base = next + 1; + next = strstr(base, "\n"); + } + + // Print the end of the message + WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s\n", base), written); } else { + if (use_decorations) { + WRITE_LOG_WITH_RESULT_CHECK(write_decorations(decorations), written); + WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, " "), written); + } char *dupstr = os::strdup_check_oom(msg, mtLogging); char *cur = dupstr; char *next; diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index b53a015b0f2..15ac30d09ab 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -38,6 +38,7 @@ class outputStream; LOG_TAG(age) \ LOG_TAG(alloc) \ LOG_TAG(annotation) \ + LOG_TAG(aot) \ LOG_TAG(arguments) \ LOG_TAG(array) \ LOG_TAG(attach) \ @@ -160,7 +161,6 @@ class outputStream; LOG_TAG(preorder) /* Trace all classes loaded in order referenced (not loaded) */ \ LOG_TAG(preview) /* Trace loading of preview feature types */ \ LOG_TAG(promotion) \ - LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \ LOG_TAG(ptrqueue) \ LOG_TAG(purge) \ LOG_TAG(record) \ diff --git a/src/hotspot/share/memory/allocation.hpp b/src/hotspot/share/memory/allocation.hpp index 9841ce3183c..ae834ec9a72 100644 --- a/src/hotspot/share/memory/allocation.hpp +++ b/src/hotspot/share/memory/allocation.hpp @@ -353,7 +353,7 @@ class MetaspaceObj { void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, Type type) throw(); - void operator delete(void* p) { ShouldNotCallThis(); } + void operator delete(void* p) = delete; // Declare a *static* method with the same signature in any subclass of MetaspaceObj // that should be read-only by default. See symbol.hpp for an example. This function diff --git a/src/hotspot/share/memory/iterator.inline.hpp b/src/hotspot/share/memory/iterator.inline.hpp index 532782b18f1..7ed2b9b3faa 100644 --- a/src/hotspot/share/memory/iterator.inline.hpp +++ b/src/hotspot/share/memory/iterator.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -27,6 +27,7 @@ #include "memory/iterator.hpp" +#include "cds/aotLinkedClassBulkLoader.hpp" #include "classfile/classLoaderData.hpp" #include "code/nmethod.hpp" #include "oops/access.inline.hpp" @@ -51,7 +52,11 @@ inline void ClaimMetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) inline void ClaimMetadataVisitingOopIterateClosure::do_klass(Klass* k) { ClassLoaderData* cld = k->class_loader_data(); - ClaimMetadataVisitingOopIterateClosure::do_cld(cld); + if (cld != nullptr) { + ClaimMetadataVisitingOopIterateClosure::do_cld(cld); + } else { + assert(AOTLinkedClassBulkLoader::is_pending_aot_linked_class(k), "sanity"); + } } inline void ClaimMetadataVisitingOopIterateClosure::do_nmethod(nmethod* nm) { diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 7147e2588c9..73cc16bc122 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -23,11 +23,11 @@ */ #include "precompiled.hpp" -#include "cds/archiveHeapWriter.hpp" -#include "cds/archiveHeapLoader.hpp" +#include "cds/aotConstantPoolResolver.hpp" #include "cds/archiveBuilder.hpp" +#include "cds/archiveHeapLoader.hpp" +#include "cds/archiveHeapWriter.hpp" #include "cds/cdsConfig.hpp" -#include "cds/classPrelinker.hpp" #include "cds/heapShared.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.hpp" @@ -35,6 +35,7 @@ #include "classfile/metadataOnStackMark.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" @@ -283,6 +284,44 @@ void ConstantPool::klass_at_put(int class_index, Klass* k) { } #if INCLUDE_CDS_JAVA_HEAP +template +void ConstantPool::iterate_archivable_resolved_references(Function function) { + objArrayOop rr = resolved_references(); + if (rr != nullptr && cache() != nullptr && CDSConfig::is_dumping_invokedynamic()) { + Array* indy_entries = cache()->resolved_indy_entries(); + if (indy_entries != nullptr) { + for (int i = 0; i < indy_entries->length(); i++) { + ResolvedIndyEntry *rie = indy_entries->adr_at(i); + if (rie->is_resolved() && AOTConstantPoolResolver::is_resolution_deterministic(this, rie->constant_pool_index())) { + int rr_index = rie->resolved_references_index(); + assert(resolved_reference_at(rr_index) != nullptr, "must exist"); + function(rr_index); + + // Save the BSM as well (sometimes the JIT looks up the BSM it for replay) + int indy_cp_index = rie->constant_pool_index(); + int bsm_mh_cp_index = bootstrap_method_ref_index_at(indy_cp_index); + int bsm_rr_index = cp_to_object_index(bsm_mh_cp_index); + assert(resolved_reference_at(bsm_rr_index) != nullptr, "must exist"); + function(bsm_rr_index); + } + } + } + + Array* method_entries = cache()->resolved_method_entries(); + if (method_entries != nullptr) { + for (int i = 0; i < method_entries->length(); i++) { + ResolvedMethodEntry* rme = method_entries->adr_at(i); + if (rme->is_resolved(Bytecodes::_invokehandle) && rme->has_appendix() && + cache()->can_archive_resolved_method(this, rme)) { + int rr_index = rme->resolved_references_index(); + assert(resolved_reference_at(rr_index) != nullptr, "must exist"); + function(rr_index); + } + } + } + } +} + // Returns the _resolved_reference array after removing unarchivable items from it. // Returns null if this class is not supported, or _resolved_reference doesn't exist. objArrayOop ConstantPool::prepare_resolved_references_for_archiving() { @@ -300,8 +339,15 @@ objArrayOop ConstantPool::prepare_resolved_references_for_archiving() { objArrayOop rr = resolved_references(); if (rr != nullptr) { + ResourceMark rm; int rr_len = rr->length(); + GrowableArray keep_resolved_refs(rr_len, rr_len, false); + ConstantPool* src_cp = ArchiveBuilder::current()->get_source_addr(this); + src_cp->iterate_archivable_resolved_references([&](int rr_index) { + keep_resolved_refs.at_put(rr_index, true); + }); + objArrayOop scratch_rr = HeapShared::scratch_resolved_references(src_cp); Array* ref_map = reference_map(); int ref_map_len = ref_map == nullptr ? 0 : ref_map->length(); @@ -316,8 +362,13 @@ objArrayOop ConstantPool::prepare_resolved_references_for_archiving() { if (!ArchiveHeapWriter::is_string_too_large_to_archive(obj)) { scratch_rr->obj_at_put(i, obj); } + continue; } } + + if (keep_resolved_refs.at(i)) { + scratch_rr->obj_at_put(i, obj); + } } } return scratch_rr; @@ -325,6 +376,32 @@ objArrayOop ConstantPool::prepare_resolved_references_for_archiving() { return rr; } +void ConstantPool::find_required_hidden_classes() { + if (_cache == nullptr) { + return; + } + + ClassLoaderData* loader_data = pool_holder()->class_loader_data(); + if (loader_data == nullptr) { + // These are custom loader classes from the preimage + return; + } + + if (!SystemDictionaryShared::is_builtin_loader(loader_data)) { + // Archiving resolved references for classes from non-builtin loaders + // is not yet supported. + return; + } + + objArrayOop rr = resolved_references(); + if (rr != nullptr) { + iterate_archivable_resolved_references([&](int rr_index) { + oop obj = rr->obj_at(rr_index); + HeapShared::find_required_hidden_classes_in_object(obj); + }); + } +} + void ConstantPool::add_dumped_interned_strings() { objArrayOop rr = resolved_references(); if (rr != nullptr) { @@ -349,6 +426,11 @@ void ConstantPool::restore_unshareable_info(TRAPS) { assert(is_constantPool(), "ensure C++ vtable is restored"); assert(on_stack(), "should always be set for shared constant pools"); assert(is_shared(), "should always be set for shared constant pools"); + if (is_for_method_handle_intrinsic()) { + // See the same check in remove_unshareable_info() below. + assert(cache() == NULL, "must not have cpCache"); + return; + } assert(_cache != nullptr, "constant pool _cache should not be null"); // Only create the new resolved references array if it hasn't been attempted before @@ -388,6 +470,14 @@ void ConstantPool::remove_unshareable_info() { // we always set _on_stack to true to avoid having to change _flags during runtime. _flags |= (_on_stack | _is_shared); + if (is_for_method_handle_intrinsic()) { + // This CP was created by Method::make_method_handle_intrinsic() and has nothing + // that need to be removed/restored. It has no cpCache since the intrinsic methods + // don't have any bytecodes. + assert(cache() == NULL, "must not have cpCache"); + return; + } + // resolved_references(): remember its length. If it cannot be restored // from the archived heap objects at run time, we need to dynamically allocate it. if (cache() != nullptr) { @@ -482,7 +572,7 @@ void ConstantPool::remove_resolved_klass_if_non_deterministic(int cp_index) { can_archive = false; } else { ConstantPool* src_cp = ArchiveBuilder::current()->get_source_addr(this); - can_archive = ClassPrelinker::is_resolution_deterministic(src_cp, cp_index); + can_archive = AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index); } if (!can_archive) { @@ -502,7 +592,7 @@ void ConstantPool::remove_resolved_klass_if_non_deterministic(int cp_index) { (!k->is_instance_klass() || pool_holder()->is_subtype_of(k)) ? "" : " (not supertype)"); } else { Symbol* name = klass_name_at(cp_index); - log.print(" %s", name->as_C_string()); + log.print(" => %s", name->as_C_string()); } } @@ -590,13 +680,12 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int cp_ind Handle mirror_handle; Symbol* name = this_cp->symbol_at(name_index); Handle loader (THREAD, this_cp->pool_holder()->class_loader()); - Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain()); Klass* k; { // Turn off the single stepping while doing class resolution JvmtiHideSingleStepping jhss(javaThread); - k = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD); + k = SystemDictionary::resolve_or_fail(name, loader, true, THREAD); } // JvmtiHideSingleStepping jhss(javaThread); if (!HAS_PENDING_EXCEPTION) { @@ -666,10 +755,8 @@ Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int w HandleMark hm(current); Symbol* name = this_cp->symbol_at(name_index); oop loader = this_cp->pool_holder()->class_loader(); - oop protection_domain = this_cp->pool_holder()->protection_domain(); - Handle h_prot (current, protection_domain); Handle h_loader (current, loader); - Klass* k = SystemDictionary::find_instance_klass(current, name, h_loader, h_prot); + Klass* k = SystemDictionary::find_instance_klass(current, name, h_loader); // Avoid constant pool verification at a safepoint, as it takes the Module_lock. if (k != nullptr && current->is_Java_thread()) { @@ -748,9 +835,7 @@ int ConstantPool::to_cp_index(int index, Bytecodes::Code code) { case Bytecodes::_fast_invokevfinal: // Bytecode interpreter uses this return resolved_method_entry_at(index)->constant_pool_index(); default: - tty->print_cr("Unexpected bytecode: %d", code); - ShouldNotReachHere(); // All cases should have been handled - return -1; + fatal("Unexpected bytecode: %s", Bytecodes::name(code)); } } diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index bcc9a08dd6c..9ada3e29d49 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -82,7 +82,7 @@ class ConstantPool : public Metadata { friend class JVMCIVMStructs; friend class BytecodeInterpreter; // Directly extracts a klass in the pool for fast instanceof/checkcast friend class Universe; // For null constructor - friend class ClassPrelinker; // CDS + friend class AOTConstantPoolResolver; private: // If you add a new field that points to any metaspace object, you // must add this field to ConstantPool::metaspace_pointers_do(). @@ -109,7 +109,8 @@ class ConstantPool : public Metadata { _has_preresolution = 1, // Flags _on_stack = 2, _is_shared = 4, - _has_dynamic_constant = 8 + _has_dynamic_constant = 8, + _is_for_method_handle_intrinsic = 16 }; u2 _flags; // old fashioned bit twiddling @@ -216,6 +217,9 @@ class ConstantPool : public Metadata { bool has_dynamic_constant() const { return (_flags & _has_dynamic_constant) != 0; } void set_has_dynamic_constant() { _flags |= _has_dynamic_constant; } + bool is_for_method_handle_intrinsic() const { return (_flags & _is_for_method_handle_intrinsic) != 0; } + void set_is_for_method_handle_intrinsic() { _flags |= _is_for_method_handle_intrinsic; } + // Klass holding pool InstanceKlass* pool_holder() const { return _pool_holder; } void set_pool_holder(InstanceKlass* k) { _pool_holder = k; } @@ -679,12 +683,14 @@ class ConstantPool : public Metadata { #if INCLUDE_CDS // CDS support objArrayOop prepare_resolved_references_for_archiving() NOT_CDS_JAVA_HEAP_RETURN_(nullptr); + void find_required_hidden_classes() NOT_CDS_JAVA_HEAP_RETURN; void add_dumped_interned_strings() NOT_CDS_JAVA_HEAP_RETURN; void remove_unshareable_info(); void restore_unshareable_info(TRAPS); private: void remove_unshareable_entries(); void remove_resolved_klass_if_non_deterministic(int cp_index); + template void iterate_archivable_resolved_references(Function function); #endif private: diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp index 321d8add755..bcf3669c9df 100644 --- a/src/hotspot/share/oops/cpCache.cpp +++ b/src/hotspot/share/oops/cpCache.cpp @@ -23,9 +23,9 @@ */ #include "precompiled.hpp" +#include "cds/aotConstantPoolResolver.hpp" #include "cds/archiveBuilder.hpp" #include "cds/cdsConfig.hpp" -#include "cds/classPrelinker.hpp" #include "cds/heapShared.hpp" #include "classfile/resolutionErrors.hpp" #include "classfile/systemDictionary.hpp" @@ -401,9 +401,7 @@ void ConstantPoolCache::remove_unshareable_info() { assert(CDSConfig::is_dumping_archive(), "sanity"); if (_resolved_indy_entries != nullptr) { - for (int i = 0; i < _resolved_indy_entries->length(); i++) { - resolved_indy_entry_at(i)->remove_unshareable_info(); - } + remove_resolved_indy_entries_if_non_deterministic(); } if (_resolved_field_entries != nullptr) { remove_resolved_field_entries_if_non_deterministic(); @@ -422,7 +420,7 @@ void ConstantPoolCache::remove_resolved_field_entries_if_non_deterministic() { bool archived = false; bool resolved = rfi->is_resolved(Bytecodes::_getfield) || rfi->is_resolved(Bytecodes::_putfield); - if (resolved && ClassPrelinker::is_resolution_deterministic(src_cp, cp_index)) { + if (resolved && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { rfi->mark_and_relocate(); archived = true; } else { @@ -436,11 +434,10 @@ void ConstantPoolCache::remove_resolved_field_entries_if_non_deterministic() { Symbol* klass_name = cp->klass_name_at(klass_cp_index); Symbol* name = cp->uncached_name_ref_at(cp_index); Symbol* signature = cp->uncached_signature_ref_at(cp_index); - log.print("%s field CP entry [%3d]: %s %s %s.%s:%s", + log.print("%s field CP entry [%3d]: %s => %s.%s:%s", (archived ? "archived" : "reverted"), cp_index, cp->pool_holder()->name()->as_C_string(), - (archived ? "=>" : " "), klass_name->as_C_string(), name->as_C_string(), signature->as_C_string()); } } @@ -457,13 +454,13 @@ void ConstantPoolCache::remove_resolved_method_entries_if_non_deterministic() { bool archived = false; bool resolved = rme->is_resolved(Bytecodes::_invokevirtual) || rme->is_resolved(Bytecodes::_invokespecial) || - rme->is_resolved(Bytecodes::_invokeinterface); + rme->is_resolved(Bytecodes::_invokeinterface) || + rme->is_resolved(Bytecodes::_invokehandle); // Just for safety -- this should not happen, but do not archive if we ever see this. - resolved &= !(rme->is_resolved(Bytecodes::_invokehandle) || - rme->is_resolved(Bytecodes::_invokestatic)); + resolved &= !(rme->is_resolved(Bytecodes::_invokestatic)); - if (resolved && can_archive_resolved_method(rme)) { + if (resolved && can_archive_resolved_method(src_cp, rme)) { rme->mark_and_relocate(src_cp); archived = true; } else { @@ -495,7 +492,41 @@ void ConstantPoolCache::remove_resolved_method_entries_if_non_deterministic() { } } -bool ConstantPoolCache::can_archive_resolved_method(ResolvedMethodEntry* method_entry) { +void ConstantPoolCache::remove_resolved_indy_entries_if_non_deterministic() { + ConstantPool* cp = constant_pool(); + ConstantPool* src_cp = ArchiveBuilder::current()->get_source_addr(cp); + for (int i = 0; i < _resolved_indy_entries->length(); i++) { + ResolvedIndyEntry* rei = _resolved_indy_entries->adr_at(i); + int cp_index = rei->constant_pool_index(); + bool archived = false; + bool resolved = rei->is_resolved(); + if (resolved && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { + rei->mark_and_relocate(); + archived = true; + } else { + rei->remove_unshareable_info(); + } + if (resolved) { + LogStreamHandle(Trace, cds, resolve) log; + if (log.is_enabled()) { + ResourceMark rm; + int bsm = cp->bootstrap_method_ref_index_at(cp_index); + int bsm_ref = cp->method_handle_index_at(bsm); + Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref); + Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref); + Symbol* bsm_klass = cp->klass_name_at(cp->uncached_klass_ref_index_at(bsm_ref)); + log.print("%s indy CP entry [%3d]: %s (%d)", + (archived ? "archived" : "reverted"), + cp_index, cp->pool_holder()->name()->as_C_string(), i); + log.print(" %s %s.%s:%s", (archived ? "=>" : " "), bsm_klass->as_C_string(), + bsm_name->as_C_string(), bsm_signature->as_C_string()); + } + ArchiveBuilder::alloc_stats()->record_indy_cp_entry(archived, resolved && !archived); + } + } +} + +bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry) { InstanceKlass* pool_holder = constant_pool()->pool_holder(); if (!(pool_holder->is_shared_boot_class() || pool_holder->is_shared_platform_class() || pool_holder->is_shared_app_class())) { @@ -520,10 +551,9 @@ bool ConstantPoolCache::can_archive_resolved_method(ResolvedMethodEntry* method_ } int cp_index = method_entry->constant_pool_index(); - ConstantPool* src_cp = ArchiveBuilder::current()->get_source_addr(constant_pool()); assert(src_cp->tag_at(cp_index).is_method() || src_cp->tag_at(cp_index).is_interface_method(), "sanity"); - if (!ClassPrelinker::is_resolution_deterministic(src_cp, cp_index)) { + if (!AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { return false; } @@ -531,11 +561,16 @@ bool ConstantPoolCache::can_archive_resolved_method(ResolvedMethodEntry* method_ method_entry->is_resolved(Bytecodes::_invokevirtual) || method_entry->is_resolved(Bytecodes::_invokespecial)) { return true; + } else if (method_entry->is_resolved(Bytecodes::_invokehandle)) { + if (CDSConfig::is_dumping_invokedynamic()) { + // invokehandle depends on archived MethodType and LambdaForms. + return true; + } else { + return false; + } } else { - // invokestatic and invokehandle are not supported yet. return false; } - } #endif // INCLUDE_CDS diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp index f95f141d845..8652409a1a4 100644 --- a/src/hotspot/share/oops/cpCache.hpp +++ b/src/hotspot/share/oops/cpCache.hpp @@ -224,8 +224,9 @@ class ConstantPoolCache: public MetaspaceObj { #if INCLUDE_CDS void remove_resolved_field_entries_if_non_deterministic(); + void remove_resolved_indy_entries_if_non_deterministic(); void remove_resolved_method_entries_if_non_deterministic(); - bool can_archive_resolved_method(ResolvedMethodEntry* method_entry); + bool can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry); #endif // RedefineClasses support diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index a9024bf4a9f..d2761667f64 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "cds/aotClassInitializer.hpp" #include "cds/archiveUtils.hpp" #include "cds/cdsConfig.hpp" #include "cds/cdsEnumKlass.hpp" @@ -734,6 +735,18 @@ bool InstanceKlass::is_sealed() const { _permitted_subclasses != Universe::the_empty_short_array(); } +// JLS 8.9: An enum class is either implicitly final and derives +// from java.lang.Enum, or else is implicitly sealed to its +// anonymous subclasses. This query detects both kinds. +// It does not validate the finality or +// sealing conditions: it merely checks for a super of Enum. +// This is sufficient for recognizing well-formed enums. +bool InstanceKlass::is_enum_subclass() const { + InstanceKlass* s = java_super(); + return (s == vmClasses::Enum_klass() || + (s != nullptr && s->java_super() == vmClasses::Enum_klass())); +} + bool InstanceKlass::should_be_initialized() const { return !is_initialized(); } @@ -791,6 +804,68 @@ void InstanceKlass::initialize(TRAPS) { } } +#ifdef ASSERT +void InstanceKlass::assert_no_clinit_will_run_for_aot_initialized_class() const { + assert(has_aot_initialized_mirror(), "must be"); + + InstanceKlass* s = java_super(); + if (s != nullptr) { + DEBUG_ONLY(ResourceMark rm); + assert(s->is_initialized(), "super class %s of aot-inited class %s must have been initialized", + s->external_name(), external_name()); + s->assert_no_clinit_will_run_for_aot_initialized_class(); + } + + Array* interfaces = local_interfaces(); + int len = interfaces->length(); + for (int i = 0; i < len; i++) { + InstanceKlass* intf = interfaces->at(i); + if (!intf->is_initialized()) { + ResourceMark rm; + // Note: an interface needs to be marked as is_initialized() only if + // - it has a + // - it has declared a default method. + assert(!intf->interface_needs_clinit_execution_as_super(/*also_check_supers*/false), + "uninitialized super interface %s of aot-inited class %s must not have ", + intf->external_name(), external_name()); + } + } +} +#endif + +#if INCLUDE_CDS +void InstanceKlass::initialize_with_aot_initialized_mirror(TRAPS) { + assert(has_aot_initialized_mirror(), "must be"); + assert(CDSConfig::is_loading_heap(), "must be"); + assert(CDSConfig::is_using_aot_linked_classes(), "must be"); + assert_no_clinit_will_run_for_aot_initialized_class(); + + if (is_initialized()) { + return; + } + + if (log_is_enabled(Info, cds, init)) { + ResourceMark rm; + log_info(cds, init)("%s (aot-inited)", external_name()); + } + + link_class(CHECK); + +#ifdef ASSERT + { + Handle h_init_lock(THREAD, init_lock()); + ObjectLocker ol(h_init_lock, THREAD); + assert(!is_initialized(), "sanity"); + assert(!is_being_initialized(), "sanity"); + assert(!is_in_error_state(), "sanity"); + } +#endif + + set_init_thread(THREAD); + AOTClassInitializer::call_runtime_setup(THREAD, this); + set_initialization_state_and_notify(fully_initialized, CHECK); +} +#endif bool InstanceKlass::verify_code(TRAPS) { // 1) Verify the bytecodes @@ -1578,7 +1653,10 @@ void InstanceKlass::call_class_initializer(TRAPS) { #if INCLUDE_CDS // This is needed to ensure the consistency of the archived heap objects. - if (has_archived_enum_objs()) { + if (has_aot_initialized_mirror() && CDSConfig::is_loading_heap()) { + AOTClassInitializer::call_runtime_setup(THREAD, this); + return; + } else if (has_archived_enum_objs()) { assert(is_shared(), "must be"); bool initialized = CDSEnumKlass::initialize_enum_klass(this, CHECK); if (initialized) { @@ -1607,6 +1685,47 @@ void InstanceKlass::call_class_initializer(TRAPS) { } } +// If a class that implements this interface is initialized, is the JVM required +// to first execute a method declared in this interface, +// or (if also_check_supers==true) any of the super types of this interface? +// +// JVMS 5.5. Initialization, step 7: Next, if C is a class rather than +// an interface, then let SC be its superclass and let SI1, ..., SIn +// be all superinterfaces of C (whether direct or indirect) that +// declare at least one non-abstract, non-static method. +// +// So when an interface is initialized, it does not look at its +// supers. But a proper class will ensure that all of its supers have +// run their methods, except that it disregards interfaces +// that lack a non-static concrete method (i.e., a default method). +// Therefore, you should probably call this method only when the +// current class is a super of some proper class, not an interface. +bool InstanceKlass::interface_needs_clinit_execution_as_super(bool also_check_supers) const { + assert(is_interface(), "must be"); + + if (!has_nonstatic_concrete_methods()) { + // quick check: no nonstatic concrete methods are declared by this or any super interfaces + return false; + } + + // JVMS 5.5. Initialization + // ...If C is an interface that declares a non-abstract, + // non-static method, the initialization of a class that + // implements C directly or indirectly. + if (declares_nonstatic_concrete_methods() && class_initializer() != nullptr) { + return true; + } + if (also_check_supers) { + Array* all_ifs = transitive_interfaces(); + for (int i = 0; i < all_ifs->length(); ++i) { + InstanceKlass* super_intf = all_ifs->at(i); + if (super_intf->declares_nonstatic_concrete_methods() && super_intf->class_initializer() != nullptr) { + return true; + } + } + } + return false; +} void InstanceKlass::mask_for(const methodHandle& method, int bci, InterpreterOopMap* entry_for) { @@ -2497,6 +2616,7 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) { } } + it->push(&_nest_host); it->push(&_nest_members); it->push(&_permitted_subclasses); it->push(&_record_components); @@ -2560,8 +2680,12 @@ void InstanceKlass::remove_unshareable_info() { _methods_jmethod_ids = nullptr; _jni_ids = nullptr; _oop_map_cache = nullptr; - // clear _nest_host to ensure re-load at runtime - _nest_host = nullptr; + if (CDSConfig::is_dumping_invokedynamic() && HeapShared::is_lambda_proxy_klass(this)) { + // keep _nest_host + } else { + // clear _nest_host to ensure re-load at runtime + _nest_host = nullptr; + } init_shared_package_entry(); _dep_context_last_cleaned = 0; @@ -2700,6 +2824,18 @@ bool InstanceKlass::can_be_verified_at_dumptime() const { } return true; } + +int InstanceKlass::shared_class_loader_type() const { + if (is_shared_boot_class()) { + return ClassLoader::BOOT_LOADER; + } else if (is_shared_platform_class()) { + return ClassLoader::PLATFORM_LOADER; + } else if (is_shared_app_class()) { + return ClassLoader::APP_LOADER; + } else { + return ClassLoader::OTHER; + } +} #endif // INCLUDE_CDS #if INCLUDE_JVMTI @@ -2907,6 +3043,10 @@ ModuleEntry* InstanceKlass::module() const { return class_loader_data()->unnamed_module(); } +bool InstanceKlass::in_javabase_module() const { + return module()->name() == vmSymbols::java_base(); +} + void InstanceKlass::set_package(ClassLoaderData* loader_data, PackageEntry* pkg_entry, TRAPS) { // ensure java/ packages only loaded by boot or platform builtin loaders diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index daaa16f2059..13b50859ee3 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -45,7 +45,6 @@ class ConstantPool; class DeoptimizationScope; class klassItable; -class Monitor; class RecordComponent; // An InstanceKlass is the VM level representation of a Java class. @@ -68,7 +67,6 @@ class ClassFileStream; class KlassDepChange; class DependencyContext; class fieldDescriptor; -class jniIdMapBase; class JNIid; class JvmtiCachedClassFieldMap; class nmethodBucket; @@ -323,6 +321,7 @@ class InstanceKlass: public Klass { void set_shared_loading_failed() { _misc_flags.set_shared_loading_failed(true); } #if INCLUDE_CDS + int shared_class_loader_type() const; void set_shared_class_loader_type(s2 loader_type) { _misc_flags.set_shared_class_loader_type(loader_type); } void assign_class_loader_type() { _misc_flags.assign_class_loader_type(_class_loader_data); } #endif @@ -429,6 +428,9 @@ class InstanceKlass: public Klass { } bool is_record() const; + // test for enum class (or possibly an anonymous subclass within a sealed enum) + bool is_enum_subclass() const; + // permitted subclasses Array* permitted_subclasses() const { return _permitted_subclasses; } void set_permitted_subclasses(Array* s) { _permitted_subclasses = s; } @@ -475,6 +477,7 @@ class InstanceKlass: public Klass { // package PackageEntry* package() const { return _package_entry; } ModuleEntry* module() const; + bool in_javabase_module() const; bool in_unnamed_package() const { return (_package_entry == nullptr); } void set_package(ClassLoaderData* loader_data, PackageEntry* pkg_entry, TRAPS); // If the package for the InstanceKlass is in the boot loader's package entry @@ -531,12 +534,15 @@ class InstanceKlass: public Klass { // initialization (virtuals from Klass) bool should_be_initialized() const; // means that initialize should be called + void initialize_with_aot_initialized_mirror(TRAPS); + void assert_no_clinit_will_run_for_aot_initialized_class() const NOT_DEBUG_RETURN; void initialize(TRAPS); void link_class(TRAPS); bool link_class_or_fail(TRAPS); // returns false on failure void rewrite_class(TRAPS); void link_methods(TRAPS); Method* class_initializer() const; + bool interface_needs_clinit_execution_as_super(bool also_check_supers=true) const; // reference type ReferenceType reference_type() const { return (ReferenceType)_reference_type; } diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 2629be64bea..2c75d6da3b8 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -25,8 +25,6 @@ #ifndef SHARE_OOPS_KLASS_HPP #define SHARE_OOPS_KLASS_HPP -#include "memory/iterator.hpp" -#include "memory/memRegion.hpp" #include "oops/klassFlags.hpp" #include "oops/markWord.hpp" #include "oops/metadata.hpp" @@ -60,8 +58,6 @@ class fieldDescriptor; class klassVtable; class ModuleEntry; class PackageEntry; -class ParCompactionManager; -class PSPromotionManager; class vtableEntry; class Klass : public Metadata { @@ -195,7 +191,12 @@ class Klass : public Metadata { _has_archived_enum_objs = 1 << 4, // This class was not loaded from a classfile in the module image // or classpath. - _is_generated_shared_class = 1 << 5 + _is_generated_shared_class = 1 << 5, + // archived mirror already initialized by AOT-cache assembly: no further need to call + _has_aot_initialized_mirror = 1 << 6, + // If this class has been aot-inititalized, do we need to call its runtimeSetup() + // method during the production run? + _is_runtime_setup_required = 1 << 7, }; #endif @@ -377,6 +378,23 @@ class Klass : public Metadata { NOT_CDS(return false;) } + void set_has_aot_initialized_mirror() { + CDS_ONLY(_shared_class_flags |= _has_aot_initialized_mirror;) + } + bool has_aot_initialized_mirror() const { + CDS_ONLY(return (_shared_class_flags & _has_aot_initialized_mirror) != 0;) + NOT_CDS(return false;) + } + + void set_is_runtime_setup_required() { + assert(has_aot_initialized_mirror(), "sanity"); + CDS_ONLY(_shared_class_flags |= _is_runtime_setup_required;) + } + bool is_runtime_setup_required() const { + CDS_ONLY(return (_shared_class_flags & _is_runtime_setup_required) != 0;) + NOT_CDS(return false;) + } + bool is_shared() const { // shadows MetaspaceObj::is_shared)() CDS_ONLY(return (_shared_class_flags & _is_shared_class) != 0;) NOT_CDS(return false;) diff --git a/src/hotspot/share/oops/markWord.hpp b/src/hotspot/share/oops/markWord.hpp index 7d2bff1efc0..1e1b8d77a90 100644 --- a/src/hotspot/share/oops/markWord.hpp +++ b/src/hotspot/share/oops/markWord.hpp @@ -133,7 +133,9 @@ class markWord { // We store the (narrow) Klass* in the bits 43 to 64. // These are for bit-precise extraction of the narrow Klass* from the 64-bit Markword + static constexpr int klass_offset_in_bytes = 4; static constexpr int klass_shift = hash_shift + hash_bits; + static constexpr int klass_shift_at_offset = klass_shift - klass_offset_in_bytes * BitsPerByte; static constexpr int klass_bits = 22; static constexpr uintptr_t klass_mask = right_n_bits(klass_bits); static constexpr uintptr_t klass_mask_in_place = klass_mask << klass_shift; diff --git a/src/hotspot/share/oops/metadata.hpp b/src/hotspot/share/oops/metadata.hpp index f5aee34c80d..ff18cef60a7 100644 --- a/src/hotspot/share/oops/metadata.hpp +++ b/src/hotspot/share/oops/metadata.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -44,11 +44,10 @@ class Metadata : public MetaspaceObj { virtual bool is_method() const { return false; } virtual bool is_methodData() const { return false; } virtual bool is_constantPool() const { return false; } - virtual bool is_methodCounters() const { return false; } virtual int size() const = 0; virtual MetaspaceObj::Type type() const = 0; virtual const char* internal_name() const = 0; - virtual void metaspace_pointers_do(MetaspaceClosure* iter) {} + virtual void metaspace_pointers_do(MetaspaceClosure* iter) = 0; void print() const; void print_value() const; diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 26a047449ed..af10efc0f00 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -927,8 +927,7 @@ bool Method::is_klass_loaded_by_klass_index(int klass_index) const { Thread *thread = Thread::current(); Symbol* klass_name = constants()->klass_name_at(klass_index); Handle loader(thread, method_holder()->class_loader()); - Handle prot (thread, method_holder()->protection_domain()); - return SystemDictionary::find_instance_klass(thread, klass_name, loader, prot) != nullptr; + return SystemDictionary::find_instance_klass(thread, klass_name, loader) != nullptr; } else { return true; } @@ -1432,6 +1431,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, cp->symbol_at_put(_imcp_invoke_name, name); cp->symbol_at_put(_imcp_invoke_signature, signature); cp->set_has_preresolution(); + cp->set_is_for_method_handle_intrinsic(); // decide on access bits: public or not? int flags_bits = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_FINAL); @@ -1480,6 +1480,16 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, return m; } +#if INCLUDE_CDS +void Method::restore_archived_method_handle_intrinsic(methodHandle m, TRAPS) { + m->link_method(m, CHECK); + + if (m->intrinsic_id() == vmIntrinsics::_linkToNative) { + m->set_interpreter_entry(m->adapter()->get_i2c_entry()); + } +} +#endif + Klass* Method::check_non_bcp_klass(Klass* klass) { if (klass != nullptr && klass->class_loader() != nullptr) { if (klass->is_objArray_klass()) diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index 232e5fb577e..271d8b39863 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -32,7 +32,6 @@ #include "oops/methodFlags.hpp" #include "oops/instanceKlass.hpp" #include "oops/oop.hpp" -#include "oops/typeArrayOop.hpp" #include "utilities/accessFlags.hpp" #include "utilities/align.hpp" #include "utilities/growableArray.hpp" @@ -122,6 +121,7 @@ class Method : public Metadata { #if INCLUDE_CDS void remove_unshareable_info(); void restore_unshareable_info(TRAPS); + static void restore_archived_method_handle_intrinsic(methodHandle m, TRAPS); #endif // accessors for instance variables diff --git a/src/hotspot/share/oops/methodCounters.cpp b/src/hotspot/share/oops/methodCounters.cpp index 00096c5012c..93fd7e65c6b 100644 --- a/src/hotspot/share/oops/methodCounters.cpp +++ b/src/hotspot/share/oops/methodCounters.cpp @@ -50,12 +50,12 @@ MethodCounters::MethodCounters(const methodHandle& mh) : MethodCounters* MethodCounters::allocate_no_exception(const methodHandle& mh) { ClassLoaderData* loader_data = mh->method_holder()->class_loader_data(); - return new(loader_data, method_counters_size(), MetaspaceObj::MethodCountersType) MethodCounters(mh); + return new(loader_data, size(), MetaspaceObj::MethodCountersType) MethodCounters(mh); } MethodCounters* MethodCounters::allocate_with_exception(const methodHandle& mh, TRAPS) { ClassLoaderData* loader_data = mh->method_holder()->class_loader_data(); - return new(loader_data, method_counters_size(), MetaspaceObj::MethodCountersType, THREAD) MethodCounters(mh); + return new(loader_data, size(), MetaspaceObj::MethodCountersType, THREAD) MethodCounters(mh); } void MethodCounters::clear_counters() { @@ -70,7 +70,6 @@ void MethodCounters::clear_counters() { } void MethodCounters::print_value_on(outputStream* st) const { - assert(is_methodCounters(), "must be methodCounters"); st->print("method counters"); print_address_on(st); } diff --git a/src/hotspot/share/oops/methodCounters.hpp b/src/hotspot/share/oops/methodCounters.hpp index 80cfb159b50..bdf033a46a8 100644 --- a/src/hotspot/share/oops/methodCounters.hpp +++ b/src/hotspot/share/oops/methodCounters.hpp @@ -30,7 +30,7 @@ #include "interpreter/invocationCounter.hpp" #include "utilities/align.hpp" -class MethodCounters : public Metadata { +class MethodCounters : public MetaspaceObj { friend class VMStructs; friend class JVMCIVMStructs; private: @@ -52,19 +52,18 @@ class MethodCounters : public Metadata { MethodCounters(const methodHandle& mh); public: - virtual bool is_methodCounters() const { return true; } - static MethodCounters* allocate_no_exception(const methodHandle& mh); static MethodCounters* allocate_with_exception(const methodHandle& mh, TRAPS); + DEBUG_ONLY(bool on_stack() { return false; }) void deallocate_contents(ClassLoaderData* loader_data) {} - static int method_counters_size() { + void metaspace_pointers_do(MetaspaceClosure* it) { return; } + + static int size() { return align_up((int)sizeof(MethodCounters), wordSize) / wordSize; } - virtual int size() const { - return method_counters_size(); - } + MetaspaceObj::Type type() const { return MethodCountersType; } void clear_counters(); @@ -128,8 +127,7 @@ class MethodCounters : public Metadata { return byte_offset_of(MethodCounters, _backedge_mask); } - virtual const char* internal_name() const { return "{method counters}"; } - virtual void print_value_on(outputStream* st) const; - + const char* internal_name() const { return "{method counters}"; } + void print_value_on(outputStream* st) const; }; #endif // SHARE_OOPS_METHODCOUNTERS_HPP diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index bc2649ba0ed..3c0c0b54689 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -1558,6 +1558,8 @@ void MethodData::print_value_on(outputStream* st) const { } void MethodData::print_data_on(outputStream* st) const { + ConditionalMutexLocker ml(extra_data_lock(), !extra_data_lock()->owned_by_self(), + Mutex::_no_safepoint_check_flag); ResourceMark rm; ProfileData* data = first_data(); if (_parameters_type_data_di != no_parameters) { @@ -1568,6 +1570,7 @@ void MethodData::print_data_on(outputStream* st) const { st->fill_to(6); data->print_data_on(st, this); } + st->print_cr("--- Extra data:"); DataLayout* dp = extra_data_base(); DataLayout* end = args_data_limit(); diff --git a/src/hotspot/share/oops/methodData.hpp b/src/hotspot/share/oops/methodData.hpp index 36fcf8ce5fd..8375552a911 100644 --- a/src/hotspot/share/oops/methodData.hpp +++ b/src/hotspot/share/oops/methodData.hpp @@ -2511,7 +2511,7 @@ class MethodData : public Metadata { void clean_method_data(bool always_clean); void clean_weak_method_links(); - Mutex* extra_data_lock() { return &_extra_data_lock; } + Mutex* extra_data_lock() const { return const_cast(&_extra_data_lock); } void check_extra_data_locked() const NOT_DEBUG_RETURN; }; diff --git a/src/hotspot/share/oops/objLayout.cpp b/src/hotspot/share/oops/objLayout.cpp new file mode 100644 index 00000000000..3d18d319ed2 --- /dev/null +++ b/src/hotspot/share/oops/objLayout.cpp @@ -0,0 +1,50 @@ +/* + * Copyright Amazon.com Inc. 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 "oops/markWord.hpp" +#include "oops/objLayout.hpp" +#include "runtime/globals.hpp" +#include "utilities/debug.hpp" + +ObjLayout::Mode ObjLayout::_klass_mode = ObjLayout::Undefined; +int ObjLayout::_oop_base_offset_in_bytes = 0; +bool ObjLayout::_oop_has_klass_gap = false; + +void ObjLayout::initialize() { + assert(_klass_mode == Undefined, "ObjLayout initialized twice"); + if (UseCompactObjectHeaders) { + _klass_mode = Compact; + _oop_base_offset_in_bytes = sizeof(markWord); + _oop_has_klass_gap = false; + } else if (UseCompressedClassPointers) { + _klass_mode = Compressed; + _oop_base_offset_in_bytes = sizeof(markWord) + sizeof(narrowKlass); + _oop_has_klass_gap = true; + } else { + _klass_mode = Uncompressed; + _oop_base_offset_in_bytes = sizeof(markWord) + sizeof(Klass*); + _oop_has_klass_gap = false; + } +} diff --git a/src/hotspot/share/oops/objLayout.hpp b/src/hotspot/share/oops/objLayout.hpp new file mode 100644 index 00000000000..e434524d4b0 --- /dev/null +++ b/src/hotspot/share/oops/objLayout.hpp @@ -0,0 +1,66 @@ +/* + * Copyright Amazon.com Inc. 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_OOPS_OBJLAYOUT_HPP +#define SHARE_OOPS_OBJLAYOUT_HPP + +/* + * This class helps to avoid loading more than one flag in some + * operations that require checking UseCompressedClassPointers, + * UseCompactObjectHeaders and possibly more. + * + * This is important on some performance critical paths, e.g. where + * the Klass* is accessed frequently, especially by GC oop iterators + * and stack-trace builders. + */ +class ObjLayout { +public: + enum Mode { + // +UseCompactObjectHeaders (implies +UseCompressedClassPointers) + Compact, + // +UseCompressedClassPointers (-UseCompactObjectHeaders) + Compressed, + // -UseCompressedClassPointers (-UseCompactObjectHeaders) + Uncompressed, + // Not yet initialized + Undefined + }; + +private: + static Mode _klass_mode; + static int _oop_base_offset_in_bytes; + static bool _oop_has_klass_gap; + +public: + static void initialize(); + static inline Mode klass_mode(); + static inline int oop_base_offset_in_bytes() { + return _oop_base_offset_in_bytes; + } + static inline bool oop_has_klass_gap() { + return _oop_has_klass_gap; + } +}; + +#endif // SHARE_OOPS_OBJLAYOUT_HPP diff --git a/src/hotspot/share/oops/objLayout.inline.hpp b/src/hotspot/share/oops/objLayout.inline.hpp new file mode 100644 index 00000000000..677c1a933bd --- /dev/null +++ b/src/hotspot/share/oops/objLayout.inline.hpp @@ -0,0 +1,48 @@ +/* + * Copyright Amazon.com Inc. 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_OOPS_OBJLAYOUT_INLINE_HPP +#define SHARE_OOPS_OBJLAYOUT_INLINE_HPP + +#include "oops/objLayout.hpp" + +inline ObjLayout::Mode ObjLayout::klass_mode() { +#ifdef ASSERT + assert(_klass_mode != Undefined, "KlassMode not yet initialized"); + if (UseCompactObjectHeaders) { + assert(_klass_mode == Compact, "Klass mode does not match flags"); + } else if (UseCompressedClassPointers) { + assert(_klass_mode == Compressed, "Klass mode does not match flags"); + } else { + assert(_klass_mode == Uncompressed, "Klass mode does not match flags"); + } +#endif +#ifdef _LP64 + return _klass_mode; +#else + return Uncompressed; +#endif +} + +#endif // SHARE_OOPS_OBJLAYOUT_INLINE_HPP diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index 9385379a617..11cab4c043b 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -152,10 +152,6 @@ bool oopDesc::is_array_noinline() const { return is_array(); } bool oopDesc::is_objArray_noinline() const { return is_objArray(); } bool oopDesc::is_typeArray_noinline() const { return is_typeArray(); } -bool oopDesc::has_klass_gap() { - return UseCompressedClassPointers && !UseCompactObjectHeaders; -} - #if INCLUDE_CDS_JAVA_HEAP void oopDesc::set_narrow_klass(narrowKlass nk) { assert(CDSConfig::is_dumping_heap(), "Used by CDS only. Do not abuse!"); diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index dcf42c7343b..f52baab0de6 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -31,6 +31,7 @@ #include "oops/accessDecorators.hpp" #include "oops/markWord.hpp" #include "oops/metadata.hpp" +#include "oops/objLayout.hpp" #include "runtime/atomic.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -324,7 +325,9 @@ class oopDesc { inline bool mark_must_be_preserved() const; inline bool mark_must_be_preserved(markWord m) const; - static bool has_klass_gap(); + inline static bool has_klass_gap() { + return ObjLayout::oop_has_klass_gap(); + } // for code generation static int mark_offset_in_bytes() { return (int)offset_of(oopDesc, _mark); } @@ -332,12 +335,8 @@ class oopDesc { #ifdef _LP64 if (UseCompactObjectHeaders) { // NOTE: The only places where this is used with compact headers are the C2 - // compiler and JVMCI, and even there we don't use it to access the (narrow)Klass* - // directly. It is used only as a placeholder to identify the special memory slice - // containing Klass* info. This value could be any value that is not a valid - // field offset. Use an offset halfway into the markWord, as the markWord is never - // partially loaded from C2 and JVMCI. - return mark_offset_in_bytes() + 4; + // compiler and JVMCI. + return mark_offset_in_bytes() + markWord::klass_offset_in_bytes; } else #endif { @@ -350,15 +349,7 @@ class oopDesc { } static int base_offset_in_bytes() { - if (UseCompactObjectHeaders) { - // With compact headers, the Klass* field is not used for the Klass* - // and is used for the object fields instead. - return sizeof(markWord); - } else if (UseCompressedClassPointers) { - return sizeof(markWord) + sizeof(narrowKlass); - } else { - return sizeof(markWord) + sizeof(Klass*); - } + return ObjLayout::oop_base_offset_in_bytes(); } // for error reporting diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index 098e6bfa90f..45902e63147 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -34,6 +34,7 @@ #include "oops/arrayOop.hpp" #include "oops/compressedKlass.inline.hpp" #include "oops/instanceKlass.hpp" +#include "oops/objLayout.inline.hpp" #include "oops/markWord.inline.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/atomic.hpp" @@ -95,43 +96,48 @@ void oopDesc::init_mark() { } Klass* oopDesc::klass() const { - if (UseCompactObjectHeaders) { - return mark().klass(); - } else if (UseCompressedClassPointers) { - return CompressedKlassPointers::decode_not_null(_metadata._compressed_klass); - } else { - return _metadata._klass; + switch (ObjLayout::klass_mode()) { + case ObjLayout::Compact: + return mark().klass(); + case ObjLayout::Compressed: + return CompressedKlassPointers::decode_not_null(_metadata._compressed_klass); + default: + return _metadata._klass; } } Klass* oopDesc::klass_or_null() const { - if (UseCompactObjectHeaders) { - return mark().klass_or_null(); - } else if (UseCompressedClassPointers) { - return CompressedKlassPointers::decode(_metadata._compressed_klass); - } else { - return _metadata._klass; + switch (ObjLayout::klass_mode()) { + case ObjLayout::Compact: + return mark().klass_or_null(); + case ObjLayout::Compressed: + return CompressedKlassPointers::decode(_metadata._compressed_klass); + default: + return _metadata._klass; } } Klass* oopDesc::klass_or_null_acquire() const { - if (UseCompactObjectHeaders) { - return mark_acquire().klass(); - } else if (UseCompressedClassPointers) { - narrowKlass narrow_klass = Atomic::load_acquire(&_metadata._compressed_klass); - return CompressedKlassPointers::decode(narrow_klass); - } else { - return Atomic::load_acquire(&_metadata._klass); + switch (ObjLayout::klass_mode()) { + case ObjLayout::Compact: + return mark_acquire().klass(); + case ObjLayout::Compressed: { + narrowKlass narrow_klass = Atomic::load_acquire(&_metadata._compressed_klass); + return CompressedKlassPointers::decode(narrow_klass); + } + default: + return Atomic::load_acquire(&_metadata._klass); } } Klass* oopDesc::klass_without_asserts() const { - if (UseCompactObjectHeaders) { - return mark().klass_without_asserts(); - } else if (UseCompressedClassPointers) { - return CompressedKlassPointers::decode_without_asserts(_metadata._compressed_klass); - } else { - return _metadata._klass; + switch (ObjLayout::klass_mode()) { + case ObjLayout::Compact: + return mark().klass_without_asserts(); + case ObjLayout::Compressed: + return CompressedKlassPointers::decode_without_asserts(_metadata._compressed_klass); + default: + return _metadata._klass; } } diff --git a/src/hotspot/share/oops/stackChunkOop.hpp b/src/hotspot/share/oops/stackChunkOop.hpp index 38f26d091f0..57ab6316c2a 100644 --- a/src/hotspot/share/oops/stackChunkOop.hpp +++ b/src/hotspot/share/oops/stackChunkOop.hpp @@ -98,12 +98,6 @@ class stackChunkOopDesc : public instanceOopDesc { inline uint8_t lockstack_size() const; inline void set_lockstack_size(uint8_t value); - inline ObjectWaiter* object_waiter() const; - inline void set_object_waiter(ObjectWaiter* obj_waiter); - - inline ObjectMonitor* current_pending_monitor() const; - inline ObjectMonitor* current_waiting_monitor() const; - inline oop cont() const; template inline oop cont() const; diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp index d647904bf5b..4b2c160cd81 100644 --- a/src/hotspot/share/oops/stackChunkOop.inline.hpp +++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp @@ -92,9 +92,6 @@ inline void stackChunkOopDesc::set_max_thawing_size(int value) { inline uint8_t stackChunkOopDesc::lockstack_size() const { return jdk_internal_vm_StackChunk::lockStackSize(as_oop()); } inline void stackChunkOopDesc::set_lockstack_size(uint8_t value) { jdk_internal_vm_StackChunk::set_lockStackSize(this, value); } -inline ObjectWaiter* stackChunkOopDesc::object_waiter() const { return (ObjectWaiter*)jdk_internal_vm_StackChunk::objectWaiter(as_oop()); } -inline void stackChunkOopDesc::set_object_waiter(ObjectWaiter* obj) { jdk_internal_vm_StackChunk::set_objectWaiter(this, (address)obj); } - inline oop stackChunkOopDesc::cont() const { return jdk_internal_vm_StackChunk::cont(as_oop()); } inline void stackChunkOopDesc::set_cont(oop value) { jdk_internal_vm_StackChunk::set_cont(this, value); } template @@ -171,22 +168,6 @@ inline void stackChunkOopDesc::set_preempted(bool value) { set_flag(FLAG_PREEMPTED, value); } -inline ObjectMonitor* stackChunkOopDesc::current_pending_monitor() const { - ObjectWaiter* waiter = object_waiter(); - if (waiter != nullptr && waiter->at_monitorenter()) { - return waiter->monitor(); - } - return nullptr; -} - -inline ObjectMonitor* stackChunkOopDesc::current_waiting_monitor() const { - ObjectWaiter* waiter = object_waiter(); - if (waiter != nullptr && waiter->is_wait()) { - return waiter->monitor(); - } - return nullptr; -} - inline bool stackChunkOopDesc::has_lockstack() const { return is_flag(FLAG_HAS_LOCKSTACK); } inline void stackChunkOopDesc::set_has_lockstack(bool value) { set_flag(FLAG_HAS_LOCKSTACK, value); } diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 45a067a830b..d4b55ec2d8d 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -355,6 +355,12 @@ product(bool, SuperWordReductions, true, \ "Enable reductions support in superword.") \ \ + product_pd(uint, SuperWordStoreToLoadForwardingFailureDetection, DIAGNOSTIC, \ + "if >0, auto-vectorization detects possible store-to-load " \ + "forwarding failures. The number specifies over how many " \ + "loop iterations this detection spans.") \ + range(0, 4096) \ + \ product(bool, UseCMoveUnconditionally, false, \ "Use CMove (scalar and vector) ignoring profitability test.") \ \ diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index bef4cfce4d5..6252e31d898 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -424,6 +424,9 @@ void PhaseChaitin::Register_Allocate() { live.compute(_lrg_map.max_lrg_id()); _live = &live; } + + C->print_method(PHASE_INITIAL_LIVENESS, 4); + // Create the interference graph using virtual copies build_ifg_virtual(); // Include stack slots this time @@ -464,6 +467,8 @@ void PhaseChaitin::Register_Allocate() { _live = &live; } + C->print_method(PHASE_AGGRESSIVE_COALESCING, 4); + // Build physical interference graph uint must_spill = 0; must_spill = build_ifg_physical(&live_arena); @@ -504,6 +509,9 @@ void PhaseChaitin::Register_Allocate() { live.compute(_lrg_map.max_lrg_id()); // Compute LIVE _live = &live; } + + C->print_method(PHASE_INITIAL_SPILLING, 4); + build_ifg_physical(&live_arena); _ifg->SquareUp(); _ifg->Compute_Effective_Degree(); @@ -518,6 +526,10 @@ void PhaseChaitin::Register_Allocate() { } _lrg_map.compress_uf_map_for_nodes(); + if (OptoCoalesce) { + C->print_method(PHASE_CONSERVATIVE_COALESCING, 4); + } + #ifdef ASSERT verify(&live_arena, true); #endif @@ -580,6 +592,9 @@ void PhaseChaitin::Register_Allocate() { live.compute(_lrg_map.max_lrg_id()); _live = &live; } + + C->print_method(PHASE_ITERATIVE_SPILLING, 4); + must_spill = build_ifg_physical(&live_arena); _ifg->SquareUp(); _ifg->Compute_Effective_Degree(); @@ -593,6 +608,11 @@ void PhaseChaitin::Register_Allocate() { coalesce.coalesce_driver(); } _lrg_map.compress_uf_map_for_nodes(); + + if (OptoCoalesce) { + C->print_method(PHASE_CONSERVATIVE_COALESCING, 4); + } + #ifdef ASSERT verify(&live_arena, true); #endif @@ -607,6 +627,8 @@ void PhaseChaitin::Register_Allocate() { spills = Select(); } + C->print_method(PHASE_AFTER_ITERATIVE_SPILLING, 4); + // Count number of Simplify-Select trips per coloring success. _allocator_attempts += _trip_cnt + 1; _allocator_successes += 1; @@ -614,9 +636,13 @@ void PhaseChaitin::Register_Allocate() { // Peephole remove copies post_allocate_copy_removal(); + C->print_method(PHASE_POST_ALLOCATION_COPY_REMOVAL, 4); + // Merge multidefs if multiple defs representing the same value are used in a single block. merge_multidefs(); + C->print_method(PHASE_MERGE_MULTI_DEFS, 4); + #ifdef ASSERT // Verify the graph after RA. verify(&live_arena); @@ -645,6 +671,8 @@ void PhaseChaitin::Register_Allocate() { // Convert CISC spills fixup_spills(); + C->print_method(PHASE_FIX_UP_SPILLS, 4); + // Log regalloc results CompileLog* log = Compile::current()->log(); if (log != nullptr) { diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 1b148db20e0..7e4760e2cd6 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -5162,7 +5162,7 @@ void Compile::print_method(CompilerPhaseType cpt, int level, Node* n) { const char* name = ss.as_string(); if (should_print_igv(level)) { - _igv_printer->print_method(name, level); + _igv_printer->print_graph(name); } if (should_print_phase(cpt)) { print_ideal_ir(CompilerPhaseTypeHelper::to_name(cpt)); @@ -5204,6 +5204,15 @@ bool Compile::should_print_phase(CompilerPhaseType cpt) { return false; } +#ifndef PRODUCT +void Compile::init_igv() { + if (_igv_printer == nullptr) { + _igv_printer = IdealGraphPrinter::printer(); + _igv_printer->set_compile(this); + } +} +#endif + bool Compile::should_print_igv(const int level) { #ifndef PRODUCT if (PrintIdealGraphLevel < 0) { // disabled by the user @@ -5211,9 +5220,8 @@ bool Compile::should_print_igv(const int level) { } bool need = directive()->IGVPrintLevelOption >= level; - if (need && !_igv_printer) { - _igv_printer = IdealGraphPrinter::printer(); - _igv_printer->set_compile(this); + if (need) { + Compile::init_igv(); } return need; #else @@ -5281,17 +5289,23 @@ void Compile::igv_print_method_to_file(const char* phase_name, bool append) { _debug_file_printer->update_compiled_method(C->method()); } tty->print_cr("Method %s to %s", append ? "appended" : "printed", file_name); - _debug_file_printer->print(phase_name, (Node*)C->root()); + _debug_file_printer->print_graph(phase_name); } void Compile::igv_print_method_to_network(const char* phase_name) { + ResourceMark rm; + GrowableArray empty_list; + igv_print_graph_to_network(phase_name, (Node*) C->root(), empty_list); +} + +void Compile::igv_print_graph_to_network(const char* name, Node* node, GrowableArray& visible_nodes) { if (_debug_network_printer == nullptr) { _debug_network_printer = new IdealGraphPrinter(C); } else { _debug_network_printer->update_compiled_method(C->method()); } tty->print_cr("Method printed over network stream to IGV"); - _debug_network_printer->print(phase_name, (Node*)C->root()); + _debug_network_printer->print(name, C->root(), visible_nodes); } #endif diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 6285d4a5548..7c251bd4bd9 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -711,14 +711,16 @@ class Compile : public Phase { void print_method(CompilerPhaseType cpt, int level, Node* n = nullptr); #ifndef PRODUCT + void init_igv(); void dump_igv(const char* graph_name, int level = 3) { if (should_print_igv(level)) { - _igv_printer->print_method(graph_name, level); + _igv_printer->print_graph(graph_name); } } void igv_print_method_to_file(const char* phase_name = "Debug", bool append = false); void igv_print_method_to_network(const char* phase_name = "Debug"); + void igv_print_graph_to_network(const char* name, Node* node, GrowableArray& visible_nodes); static IdealGraphPrinter* debug_file_printer() { return _debug_file_printer; } static IdealGraphPrinter* debug_network_printer() { return _debug_network_printer; } #endif diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index 40aec858205..ec9233935e7 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -53,6 +53,7 @@ const char *IdealGraphPrinter::COMPILATION_OSR_PROPERTY = "osr"; const char *IdealGraphPrinter::METHOD_NAME_PROPERTY = "name"; const char *IdealGraphPrinter::METHOD_IS_PUBLIC_PROPERTY = "public"; const char *IdealGraphPrinter::METHOD_IS_STATIC_PROPERTY = "static"; +const char *IdealGraphPrinter::FALSE_VALUE = "false"; const char *IdealGraphPrinter::TRUE_VALUE = "true"; const char *IdealGraphPrinter::NODE_NAME_PROPERTY = "name"; const char *IdealGraphPrinter::EDGE_NAME_PROPERTY = "name"; @@ -68,6 +69,12 @@ const char *IdealGraphPrinter::BYTECODES_ELEMENT = "bytecodes"; const char *IdealGraphPrinter::METHOD_BCI_PROPERTY = "bci"; const char *IdealGraphPrinter::METHOD_SHORT_NAME_PROPERTY = "shortName"; const char *IdealGraphPrinter::CONTROL_FLOW_ELEMENT = "controlFlow"; +const char *IdealGraphPrinter::GRAPH_STATES_ELEMENT = "graphStates"; +const char *IdealGraphPrinter::STATE_ELEMENT = "state"; +const char *IdealGraphPrinter::DIFFERENCE_ELEMENT = "difference"; +const char *IdealGraphPrinter::DIFFERENCE_VALUE_PROPERTY = "value"; +const char *IdealGraphPrinter::VISIBLE_NODES_ELEMENT = "visibleNodes"; +const char *IdealGraphPrinter::ALL_PROPERTY = "all"; const char *IdealGraphPrinter::BLOCK_NAME_PROPERTY = "name"; const char *IdealGraphPrinter::BLOCK_DOMINATOR_PROPERTY = "dom"; const char *IdealGraphPrinter::BLOCK_ELEMENT = "block"; @@ -349,7 +356,7 @@ void IdealGraphPrinter::set_traverse_outs(bool b) { _traverse_outs = b; } -void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { +void IdealGraphPrinter::visit_node(Node* n, bool edges) { if (edges) { @@ -775,7 +782,7 @@ Node* IdealGraphPrinter::get_load_node(const Node* node) { return load; } -void IdealGraphPrinter::walk_nodes(Node* start, bool edges, VectorSet* temp_set) { +void IdealGraphPrinter::walk_nodes(Node* start, bool edges) { VectorSet visited; GrowableArray nodeStack(Thread::current()->resource_area(), 0, 0, nullptr); nodeStack.push(start); @@ -796,7 +803,7 @@ void IdealGraphPrinter::walk_nodes(Node* start, bool edges, VectorSet* temp_set) continue; } - visit_node(n, edges, temp_set); + visit_node(n, edges); if (_traverse_outs) { for (DUIterator i = n->outs(); n->has_out(i); i++) { @@ -812,14 +819,14 @@ void IdealGraphPrinter::walk_nodes(Node* start, bool edges, VectorSet* temp_set) } } -void IdealGraphPrinter::print_method(const char *name, int level) { - if (C->should_print_igv(level)) { - print(name, (Node *) C->root()); - } +void IdealGraphPrinter::print_graph(const char* name) { + ResourceMark rm; + GrowableArray empty_list; + print(name, (Node*) C->root(), empty_list); } // Print current ideal graph -void IdealGraphPrinter::print(const char *name, Node *node) { +void IdealGraphPrinter::print(const char* name, Node* node, GrowableArray& visible_nodes) { if (!_current_method || !_should_send_method || node == nullptr) return; @@ -830,8 +837,6 @@ void IdealGraphPrinter::print(const char *name, Node *node) { print_attr(GRAPH_NAME_PROPERTY, (const char *)name); end_head(); - VectorSet temp_set; - head(NODES_ELEMENT); if (C->cfg() != nullptr) { // Compute the maximum estimated frequency in the current graph. @@ -843,11 +848,11 @@ void IdealGraphPrinter::print(const char *name, Node *node) { } } } - walk_nodes(node, false, &temp_set); + walk_nodes(node, false); tail(NODES_ELEMENT); head(EDGES_ELEMENT); - walk_nodes(node, true, &temp_set); + walk_nodes(node, true); tail(EDGES_ELEMENT); if (C->cfg() != nullptr) { head(CONTROL_FLOW_ELEMENT); @@ -877,6 +882,25 @@ void IdealGraphPrinter::print(const char *name, Node *node) { } tail(CONTROL_FLOW_ELEMENT); } + if (visible_nodes.is_nonempty()) { + head(GRAPH_STATES_ELEMENT); + head(STATE_ELEMENT); + begin_elem(DIFFERENCE_ELEMENT); + print_attr(DIFFERENCE_VALUE_PROPERTY, "0"); + end_elem(); + + begin_head(VISIBLE_NODES_ELEMENT); + print_attr(ALL_PROPERTY, FALSE_VALUE); + end_head(); + for (int i = 0; i < visible_nodes.length(); ++i) { + begin_elem(NODE_ELEMENT); + print_attr(NODE_ID_PROPERTY, visible_nodes.at(i)->_igv_idx); + end_elem(); + } + tail(VISIBLE_NODES_ELEMENT); + tail(STATE_ELEMENT); + tail(GRAPH_STATES_ELEMENT); + } tail(GRAPH_ELEMENT); _xml->flush(); } diff --git a/src/hotspot/share/opto/idealGraphPrinter.hpp b/src/hotspot/share/opto/idealGraphPrinter.hpp index a06f2396f63..b6794667911 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.hpp +++ b/src/hotspot/share/opto/idealGraphPrinter.hpp @@ -59,6 +59,12 @@ class IdealGraphPrinter : public CHeapObj { static const char *CONTROL_FLOW_ELEMENT; static const char *REMOVE_EDGE_ELEMENT; static const char *REMOVE_NODE_ELEMENT; + static const char *GRAPH_STATES_ELEMENT; + static const char *STATE_ELEMENT; + static const char *DIFFERENCE_ELEMENT; + static const char *DIFFERENCE_VALUE_PROPERTY; + static const char *VISIBLE_NODES_ELEMENT; + static const char *ALL_PROPERTY; static const char *COMPILATION_ID_PROPERTY; static const char *COMPILATION_OSR_PROPERTY; static const char *METHOD_NAME_PROPERTY; @@ -69,6 +75,7 @@ class IdealGraphPrinter : public CHeapObj { static const char *SUCCESSOR_ELEMENT; static const char *METHOD_IS_PUBLIC_PROPERTY; static const char *METHOD_IS_STATIC_PROPERTY; + static const char *FALSE_VALUE; static const char *TRUE_VALUE; static const char *NODE_NAME_PROPERTY; static const char *EDGE_NAME_PROPERTY; @@ -101,13 +108,13 @@ class IdealGraphPrinter : public CHeapObj { void print_method(ciMethod* method, int bci, InlineTree* tree); void print_inline_tree(InlineTree* tree); - void visit_node(Node* n, bool edges, VectorSet* temp_set); + void visit_node(Node* n, bool edges); void print_bci_and_line_number(JVMState* caller); void print_field(const Node* node); ciField* get_field(const Node* node); ciField* find_source_field_of_array_access(const Node* node, uint& depth); static Node* get_load_node(const Node* node); - void walk_nodes(Node *start, bool edges, VectorSet* temp_set); + void walk_nodes(Node* start, bool edges); void begin_elem(const char *s); void end_elem(); void begin_head(const char *s); @@ -137,8 +144,8 @@ class IdealGraphPrinter : public CHeapObj { void print_inlining(); void begin_method(); void end_method(); - void print_method(const char *name, int level = 0); - void print(const char *name, Node *root); + void print_graph(const char* name); + void print(const char* name, Node* root, GrowableArray& hidden_nodes); void set_compile(Compile* compile) {C = compile; } void update_compiled_method(ciMethod* current_method); }; diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 226fddce29b..39bac0bc14f 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -3257,7 +3257,10 @@ bool LibraryCallKit::inline_native_getEventWriter() { set_all_memory(input_memory_state); Node* input_io_state = i_o(); - Node* excluded_mask = _gvn.intcon(32768); + // The most significant bit of the u2 is used to denote thread exclusion + Node* excluded_shift = _gvn.intcon(15); + Node* excluded_mask = _gvn.intcon(1 << 15); + // The epoch generation is the range [1-32767] Node* epoch_mask = _gvn.intcon(32767); // TLS @@ -3411,7 +3414,7 @@ bool LibraryCallKit::inline_native_getEventWriter() { record_for_igvn(vthread_compare_io); PhiNode* tid = new PhiNode(vthread_compare_rgn, TypeLong::LONG); record_for_igvn(tid); - PhiNode* exclusion = new PhiNode(vthread_compare_rgn, TypeInt::BOOL); + PhiNode* exclusion = new PhiNode(vthread_compare_rgn, TypeInt::CHAR); record_for_igvn(exclusion); PhiNode* pinVirtualThread = new PhiNode(vthread_compare_rgn, TypeInt::BOOL); record_for_igvn(pinVirtualThread); @@ -3476,7 +3479,8 @@ bool LibraryCallKit::inline_native_getEventWriter() { store_to_memory(tid_is_not_equal, event_writer_pin_field, _gvn.transform(pinVirtualThread), T_BOOLEAN, MemNode::unordered); // Store the exclusion state to the event writer. - store_to_memory(tid_is_not_equal, event_writer_excluded_field, _gvn.transform(exclusion), T_BOOLEAN, MemNode::unordered); + Node* excluded_bool = _gvn.transform(new URShiftINode(_gvn.transform(exclusion), excluded_shift)); + store_to_memory(tid_is_not_equal, event_writer_excluded_field, excluded_bool, T_BOOLEAN, MemNode::unordered); // Store the tid to the event writer. store_to_memory(tid_is_not_equal, event_writer_tid_field, tid, T_LONG, MemNode::unordered); @@ -3543,7 +3547,9 @@ void LibraryCallKit::extend_setCurrentThread(Node* jt, Node* thread) { Node* input_memory_state = reset_memory(); set_all_memory(input_memory_state); - Node* excluded_mask = _gvn.intcon(32768); + // The most significant bit of the u2 is used to denote thread exclusion + Node* excluded_mask = _gvn.intcon(1 << 15); + // The epoch generation is the range [1-32767] Node* epoch_mask = _gvn.intcon(32767); Node* const carrierThread = generate_current_thread(jt); diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index a4bec870b18..ed2cee63122 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -283,62 +283,57 @@ IfProjNode* PhaseIdealLoop::clone_parse_predicate_to_unswitched_loop(ParsePredic return new_predicate_proj; } -// Clones Assertion Predicates to both unswitched loops starting at 'old_predicate_proj' by following its control inputs. -// It also rewires the control edges of data nodes with dependencies in the loop from the old predicates to the new -// cloned predicates. +// Clones Template Assertion Predicates to both unswitched loops starting at 'old_predicate_proj' by following its +// control inputs. It also rewires the control edges of data nodes with dependencies in the loop from the old predicates +// to the new cloned predicates. void PhaseIdealLoop::clone_assertion_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, - Deoptimization::DeoptReason reason, ParsePredicateSuccessProj* old_parse_predicate_proj, - ParsePredicateSuccessProj* fast_loop_parse_predicate_proj, - ParsePredicateSuccessProj* slow_loop_parse_predicate_proj) { - assert(fast_loop_parse_predicate_proj->in(0)->is_ParsePredicate() && - slow_loop_parse_predicate_proj->in(0)->is_ParsePredicate(), "sanity check"); - // Only need to clone range check predicates as those can be changed and duplicated by inserting pre/main/post loops - // and doing loop unrolling. Push the original predicates on a list to later process them in reverse order to keep the + ParsePredicateNode* true_path_loop_parse_predicate, + ParsePredicateNode* false_path_loop_parse_predicate) { + // Push the original Template Assertion Predicates on a list to later process them in reverse order to keep the // original predicate order. Unique_Node_List list; - get_assertion_predicates(old_parse_predicate_proj, list); + get_template_assertion_predicates(old_parse_predicate_proj, list); Node_List to_process; - // Process in reverse order such that 'create_new_if_for_predicate' can be used in - // 'clone_assertion_predicate_for_unswitched_loops' and the original order is maintained. for (int i = list.size() - 1; i >= 0; i--) { - Node* predicate = list.at(i); - assert(predicate->in(0)->is_If(), "must be If node"); - IfNode* iff = predicate->in(0)->as_If(); - assert(predicate->is_Proj() && predicate->as_Proj()->is_IfProj(), "predicate must be a projection of an if node"); - IfProjNode* predicate_proj = predicate->as_IfProj(); + IfTrueNode* template_assertion_predicate_success_proj = list.at(i)->as_IfTrue(); + assert(template_assertion_predicate_success_proj->in(0)->is_If(), "must be If node"); - IfProjNode* fast_proj = clone_assertion_predicate_for_unswitched_loops(iff, predicate_proj, reason, fast_loop_parse_predicate_proj); - assert(assertion_predicate_has_loop_opaque_node(fast_proj->in(0)->as_If()), "must find Assertion Predicate for fast loop"); - IfProjNode* slow_proj = clone_assertion_predicate_for_unswitched_loops(iff, predicate_proj, reason, slow_loop_parse_predicate_proj); - assert(assertion_predicate_has_loop_opaque_node(slow_proj->in(0)->as_If()), "must find Assertion Predicate for slow loop"); + IfTrueNode* true_path_loop_proj = + clone_assertion_predicate_for_unswitched_loops(template_assertion_predicate_success_proj, + true_path_loop_parse_predicate); + IfTrueNode* false_path_loop_proj = + clone_assertion_predicate_for_unswitched_loops(template_assertion_predicate_success_proj, + false_path_loop_parse_predicate); // Update control dependent data nodes. - for (DUIterator j = predicate->outs(); predicate->has_out(j); j++) { - Node* fast_node = predicate->out(j); - if (loop->is_member(get_loop(ctrl_or_self(fast_node)))) { - assert(fast_node->in(0) == predicate, "only control edge"); - Node* slow_node = old_new[fast_node->_idx]; - assert(slow_node->in(0) == predicate, "only control edge"); - _igvn.replace_input_of(fast_node, 0, fast_proj); - to_process.push(slow_node); + for (DUIterator j = template_assertion_predicate_success_proj->outs(); + template_assertion_predicate_success_proj->has_out(j); + j++) { + Node* true_path_loop_node = template_assertion_predicate_success_proj->out(j); + if (loop->is_member(get_loop(ctrl_or_self(true_path_loop_node)))) { + assert(true_path_loop_node->in(0) == template_assertion_predicate_success_proj, "only control edge"); + Node* false_path_loop_node = old_new[true_path_loop_node->_idx]; + assert(false_path_loop_node->in(0) == template_assertion_predicate_success_proj, "only control edge"); + _igvn.replace_input_of(true_path_loop_node, 0, true_path_loop_proj); + to_process.push(false_path_loop_node); --j; } } - // Have to delay updates to the slow loop so uses of predicate are not modified while we iterate on them. + // Have to delay updates to the false path loop so uses of predicate are not modified while we iterate on them. while (to_process.size() > 0) { Node* slow_node = to_process.pop(); - _igvn.replace_input_of(slow_node, 0, slow_proj); + _igvn.replace_input_of(slow_node, 0, false_path_loop_proj); } } } -// Put all Assertion Predicate projections on a list, starting at 'predicate' and going up in the tree. If 'get_opaque' +// Put all Template Assertion Predicate projections on a list, starting at 'predicate' and going up in the tree. If 'get_opaque' // is set, then the OpaqueTemplateAssertionPredicateNode nodes of the Assertion Predicates are put on the list instead // of the projections. -void PhaseIdealLoop::get_assertion_predicates(ParsePredicateSuccessProj* parse_predicate_proj, Unique_Node_List& list, - const bool get_opaque) { +void PhaseIdealLoop::get_template_assertion_predicates(ParsePredicateSuccessProj* parse_predicate_proj, Unique_Node_List& list, + const bool get_opaque) { Deoptimization::DeoptReason deopt_reason = parse_predicate_proj->in(0)->as_ParsePredicate()->deopt_reason(); PredicateBlockIterator predicate_iterator(parse_predicate_proj, deopt_reason); TemplateAssertionPredicateCollector template_assertion_predicate_collector(list, get_opaque); @@ -348,39 +343,38 @@ void PhaseIdealLoop::get_assertion_predicates(ParsePredicateSuccessProj* parse_p // Clone an Assertion Predicate for an unswitched loop. OpaqueLoopInit and OpaqueLoopStride nodes are cloned and uncommon // traps are kept for the predicate (a Halt node is used later when creating pre/main/post loops and copying this cloned // predicate again). -IfProjNode* PhaseIdealLoop::clone_assertion_predicate_for_unswitched_loops(IfNode* template_assertion_predicate, - IfProjNode* predicate, - Deoptimization::DeoptReason reason, - ParsePredicateSuccessProj* parse_predicate_proj) { - TemplateAssertionExpression template_assertion_expression(template_assertion_predicate->in(1)->as_OpaqueTemplateAssertionPredicate()); - OpaqueTemplateAssertionPredicateNode* cloned_opaque_node = template_assertion_expression.clone(parse_predicate_proj->in(0)->in(0), this); - IfProjNode* if_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, - template_assertion_predicate->Opcode(), false); - _igvn.replace_input_of(if_proj->in(0), 1, cloned_opaque_node); - _igvn.replace_input_of(parse_predicate_proj->in(0), 0, if_proj); - set_idom(parse_predicate_proj->in(0), if_proj, dom_depth(if_proj)); - return if_proj; +IfTrueNode* +PhaseIdealLoop::clone_assertion_predicate_for_unswitched_loops(IfTrueNode* template_assertion_predicate_success_proj, + ParsePredicateNode* unswitched_loop_parse_predicate) { + TemplateAssertionPredicate template_assertion_predicate(template_assertion_predicate_success_proj); + IfTrueNode* template_success_proj = template_assertion_predicate.clone(unswitched_loop_parse_predicate->in(0), this); + assert(assertion_predicate_has_loop_opaque_node(template_success_proj->in(0)->as_If()), + "must find Assertion Predicate for fast loop"); + _igvn.replace_input_of(unswitched_loop_parse_predicate, 0, template_success_proj); + set_idom(unswitched_loop_parse_predicate, template_success_proj, dom_depth(template_success_proj)); + return template_success_proj; } // Clone the old Parse Predicates and Assertion Predicates before the unswitch If to the unswitched loops after the // unswitch If. void PhaseIdealLoop::clone_parse_and_assertion_predicates_to_unswitched_loop(IdealLoopTree* loop, Node_List& old_new, - IfProjNode*& iffast_pred, IfProjNode*& ifslow_pred) { + IfProjNode*& true_path_loop_entry, + IfProjNode*& false_path_loop_entry) { LoopNode* head = loop->_head->as_Loop(); Node* entry = head->skip_strip_mined()->in(LoopNode::EntryControl); const Predicates predicates(entry); clone_loop_predication_predicates_to_unswitched_loop(loop, old_new, predicates.loop_predicate_block(), - Deoptimization::Reason_predicate, iffast_pred, ifslow_pred); + Deoptimization::Reason_predicate, true_path_loop_entry, false_path_loop_entry); clone_loop_predication_predicates_to_unswitched_loop(loop, old_new, predicates.profiled_loop_predicate_block(), - Deoptimization::Reason_profile_predicate, iffast_pred, ifslow_pred); + Deoptimization::Reason_profile_predicate, true_path_loop_entry, false_path_loop_entry); const PredicateBlock* loop_limit_check_predicate_block = predicates.loop_limit_check_predicate_block(); if (loop_limit_check_predicate_block->has_parse_predicate() && !head->is_CountedLoop()) { // Don't clone the Loop Limit Check Parse Predicate if we already have a counted loop (a Loop Limit Check Predicate // is only created when converting a LoopNode to a CountedLoopNode). clone_parse_predicate_to_unswitched_loops(loop_limit_check_predicate_block, Deoptimization::Reason_loop_limit_check, - iffast_pred, ifslow_pred); + true_path_loop_entry, false_path_loop_entry); } } @@ -388,16 +382,17 @@ void PhaseIdealLoop::clone_parse_and_assertion_predicates_to_unswitched_loop(Ide void PhaseIdealLoop::clone_loop_predication_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, const PredicateBlock* predicate_block, Deoptimization::DeoptReason reason, - IfProjNode*& iffast_pred, - IfProjNode*& ifslow_pred) { + IfProjNode*& true_path_loop_entry, + IfProjNode*& false_path_loop_entry) { if (predicate_block->has_parse_predicate()) { // We currently only clone Assertion Predicates if there are Parse Predicates. This is not entirely correct and will // be changed with the complete fix for Assertion Predicates. - clone_parse_predicate_to_unswitched_loops(predicate_block, reason, iffast_pred, ifslow_pred); - assert(iffast_pred->in(0)->is_ParsePredicate() && ifslow_pred->in(0)->is_ParsePredicate(), + clone_parse_predicate_to_unswitched_loops(predicate_block, reason, true_path_loop_entry, false_path_loop_entry); + assert(true_path_loop_entry->in(0)->is_ParsePredicate() && false_path_loop_entry->in(0)->is_ParsePredicate(), "must be success projections of the cloned Parse Predicates"); - clone_assertion_predicates_to_unswitched_loop(loop, old_new, reason, predicate_block->parse_predicate_success_proj(), - iffast_pred->as_IfTrue(), ifslow_pred->as_IfTrue()); + clone_assertion_predicates_to_unswitched_loop(loop, old_new, predicate_block->parse_predicate_success_proj(), + true_path_loop_entry->in(0)->as_ParsePredicate(), + false_path_loop_entry->in(0)->as_ParsePredicate()); } } @@ -1250,9 +1245,9 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod // Fall through into rest of the cleanup code which will move any dependent nodes to the skeleton predicates of the // upper bound test. We always need to create skeleton predicates in order to properly remove dead loops when later // splitting the predicated loop into (unreachable) sub-loops (i.e. done by unrolling, peeling, pre/main/post etc.). - IfTrueNode* template_assertion_predicate_proj = - create_template_assertion_predicate(if_opcode, cl, parse_predicate_proj, upper_bound_proj, scale, offset, range, - deopt_reason); + IfTrueNode* template_assertion_predicate_proj = create_template_assertion_predicate(cl, parse_predicate, + upper_bound_proj, scale, offset, + range); // Eliminate the old range check in the loop body. // When a range check is eliminated, data dependent nodes (Load and range check CastII nodes) are now dependent on 2 @@ -1288,15 +1283,16 @@ void PhaseIdealLoop::eliminate_hoisted_range_check(IfTrueNode* hoisted_check_pro // Each newly created Hoisted Check Predicate is accompanied by two Template Assertion Predicates. Later, we initialize // them by making a copy of them when splitting a loop into sub loops. The Assertion Predicates ensure that dead sub // loops are removed properly. -IfTrueNode* PhaseIdealLoop::create_template_assertion_predicate(const int if_opcode, CountedLoopNode* loop_head, - ParsePredicateSuccessProj* parse_predicate_proj, +IfTrueNode* PhaseIdealLoop::create_template_assertion_predicate(CountedLoopNode* loop_head, + ParsePredicateNode* parse_predicate, IfProjNode* new_control, const int scale, Node* offset, - Node* range, Deoptimization::DeoptReason deopt_reason) { + Node* range) { TemplateAssertionPredicateCreator template_assertion_predicate_creator(loop_head, scale, offset, range, this); - return template_assertion_predicate_creator.create_with_uncommon_trap(new_control, parse_predicate_proj, deopt_reason, - if_opcode); - + IfTrueNode* template_success_proj = template_assertion_predicate_creator.create(new_control); + _igvn.replace_input_of(parse_predicate, 0, template_success_proj); + set_idom(parse_predicate, template_success_proj, dom_depth(template_success_proj)); + return template_success_proj; } // Insert Hoisted Check Predicates for null checks and range checks and additional Template Assertion Predicates for diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 9175d79e6dd..e6a56410bd7 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -2768,7 +2768,7 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) { // unrolling or splitting this main-loop further. TemplateAssertionPredicateCreator template_assertion_predicate_creator(cl, scale_con , int_offset, int_limit, this); - loop_entry = template_assertion_predicate_creator.create_with_halt(loop_entry); + loop_entry = template_assertion_predicate_creator.create(loop_entry); assert(assertion_predicate_has_loop_opaque_node(loop_entry->in(0)->as_If()), "unexpected"); // Initialized Assertion Predicate for the value of the initial main-loop. diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 44a72fda644..e52f31b1e11 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -2834,7 +2834,7 @@ Node* CountedLoopNode::skip_assertion_predicates_with_halt() { ctrl = skip_strip_mined()->in(LoopNode::EntryControl); } if (is_main_loop() || is_post_loop()) { - AssertionPredicatesWithHalt assertion_predicates(ctrl); + AssertionPredicates assertion_predicates(ctrl); return assertion_predicates.entry(); } return ctrl; @@ -4470,7 +4470,7 @@ void PhaseIdealLoop::collect_useful_template_assertion_predicates_for_loop(Ideal const PredicateBlock* profiled_loop_predicate_block = predicates.profiled_loop_predicate_block(); if (profiled_loop_predicate_block->has_parse_predicate()) { ParsePredicateSuccessProj* parse_predicate_proj = profiled_loop_predicate_block->parse_predicate_success_proj(); - get_assertion_predicates(parse_predicate_proj, useful_predicates, true); + get_template_assertion_predicates(parse_predicate_proj, useful_predicates, true); } } @@ -4478,7 +4478,7 @@ void PhaseIdealLoop::collect_useful_template_assertion_predicates_for_loop(Ideal const PredicateBlock* loop_predicate_block = predicates.loop_predicate_block(); if (loop_predicate_block->has_parse_predicate()) { ParsePredicateSuccessProj* parse_predicate_proj = loop_predicate_block->parse_predicate_success_proj(); - get_assertion_predicates(parse_predicate_proj, useful_predicates, true); + get_template_assertion_predicates(parse_predicate_proj, useful_predicates, true); } } } diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index cc67240975d..07ae390bd2e 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -947,7 +947,7 @@ class PhaseIdealLoop : public PhaseTransform { DEBUG_ONLY(static bool assertion_predicate_has_loop_opaque_node(IfNode* iff);) private: DEBUG_ONLY(static void count_opaque_loop_nodes(Node* n, uint& init, uint& stride);) - static void get_assertion_predicates(ParsePredicateSuccessProj* parse_predicate_proj, Unique_Node_List& list, bool get_opaque = false); + static void get_template_assertion_predicates(ParsePredicateSuccessProj* parse_predicate_proj, Unique_Node_List& list, bool get_opaque = false); void update_main_loop_assertion_predicates(CountedLoopNode* main_loop_head); void initialize_assertion_predicates_for_peeled_loop(CountedLoopNode* peeled_loop_head, CountedLoopNode* remaining_loop_head, @@ -1389,10 +1389,8 @@ class PhaseIdealLoop : public PhaseTransform { void loop_predication_follow_branches(Node *c, IdealLoopTree *loop, float loop_trip_cnt, PathFrequency& pf, Node_Stack& stack, VectorSet& seen, Node_List& if_proj_list); - IfTrueNode* create_template_assertion_predicate(int if_opcode, CountedLoopNode* loop_head, - ParsePredicateSuccessProj* parse_predicate_proj, - IfProjNode* new_control, int scale, Node* offset, - Node* range, Deoptimization::DeoptReason deopt_reason); + IfTrueNode* create_template_assertion_predicate(CountedLoopNode* loop_head, ParsePredicateNode* parse_predicate, + IfProjNode* new_control, int scale, Node* offset, Node* range); void eliminate_hoisted_range_check(IfTrueNode* hoisted_check_proj, IfTrueNode* template_assertion_predicate_proj); // Helper function to collect predicate for eliminating the useless ones @@ -1661,23 +1659,24 @@ class PhaseIdealLoop : public PhaseTransform { public: // Clone Parse Predicates to slow and fast loop when unswitching a loop void clone_parse_and_assertion_predicates_to_unswitched_loop(IdealLoopTree* loop, Node_List& old_new, - IfProjNode*& iffast_pred, IfProjNode*& ifslow_pred); + IfProjNode*& true_path_loop_entry, + IfProjNode*& false_path_loop_entry); private: void clone_loop_predication_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, const PredicateBlock* predicate_block, - Deoptimization::DeoptReason reason, IfProjNode*& iffast_pred, - IfProjNode*& ifslow_pred); + Deoptimization::DeoptReason reason, + IfProjNode*& true_path_loop_entry, + IfProjNode*& false_path_loop_entry); void clone_parse_predicate_to_unswitched_loops(const PredicateBlock* predicate_block, Deoptimization::DeoptReason reason, IfProjNode*& iffast_pred, IfProjNode*& ifslow_pred); IfProjNode* clone_parse_predicate_to_unswitched_loop(ParsePredicateSuccessProj* parse_predicate_proj, Node* new_entry, Deoptimization::DeoptReason reason, bool slow_loop); void clone_assertion_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, - Deoptimization::DeoptReason reason, ParsePredicateSuccessProj* old_parse_predicate_proj, - ParsePredicateSuccessProj* fast_loop_parse_predicate_proj, - ParsePredicateSuccessProj* slow_loop_parse_predicate_proj); - IfProjNode* clone_assertion_predicate_for_unswitched_loops(IfNode* template_assertion_predicate, IfProjNode* predicate, - Deoptimization::DeoptReason reason, - ParsePredicateSuccessProj* parse_predicate_proj); + ParsePredicateSuccessProj* old_parse_predicate_proj, + ParsePredicateNode* true_path_loop_parse_predicate, + ParsePredicateNode* false_path_loop_parse_predicate); + IfTrueNode* clone_assertion_predicate_for_unswitched_loops(IfTrueNode* template_assertion_predicate_success_proj, + ParsePredicateNode* unswitched_loop_parse_predicate); static void check_cloned_parse_predicate_for_unswitching(const Node* new_entry, bool is_fast_loop) PRODUCT_RETURN; bool _created_loop_node; diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index 6fcbabdab90..4ac91175f78 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -134,6 +134,14 @@ class MachOper : public ResourceObj { return ::as_VectorSRegister(reg(ra_, node, idx)); } #endif +#if defined(S390) + VectorRegister as_VectorRegister(PhaseRegAlloc *ra_, const Node *node) const { + return ::as_VectorRegister(reg(ra_, node)); + } + VectorRegister as_VectorRegister(PhaseRegAlloc *ra_, const Node *node, int idx) const { + return ::as_VectorRegister(reg(ra_, node, idx)); + } +#endif #if defined(AARCH64) PRegister as_PRegister(PhaseRegAlloc* ra_, const Node* node) const { return ::as_PRegister(reg(ra_, node)); diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index 1ca3a4b16ce..83ac80c043f 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -541,6 +541,12 @@ class LoadKlassNode : public LoadPNode { //------------------------------LoadNKlassNode--------------------------------- // Load a narrow Klass from an object. +// With compact headers, the input address (adr) does not point at the exact +// header position where the (narrow) class pointer is located, but into the +// middle of the mark word (see oopDesc::klass_offset_in_bytes()). This node +// implicitly shifts the loaded value (markWord::klass_shift_at_offset bits) to +// extract the actual class pointer. C2's type system is agnostic on whether the +// input address directly points into the class pointer. class LoadNKlassNode : public LoadNNode { public: LoadNKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk, MemOrd mo) diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 3f82c472163..cf371bb3fff 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -1830,6 +1830,8 @@ class PrintBFS { bool _print_blocks = false; bool _print_old = false; bool _dump_only = false; + bool _print_igv = false; + void print_options_help(bool print_examples); bool parse_options(); @@ -2047,6 +2049,11 @@ void PrintBFS::print() { const Node* n = _print_list.at(i); print_node(n); } + if (_print_igv) { + Compile* C = Compile::current(); + C->init_igv(); + C->igv_print_graph_to_network("PrintBFS", (Node*) C->root(), _print_list); + } } else { _output->print_cr("No nodes to print."); } @@ -2089,6 +2096,7 @@ void PrintBFS::print_options_help(bool print_examples) { _output->print_cr(" @: print old nodes - before matching (if available)"); _output->print_cr(" B: print scheduling blocks (if available)"); _output->print_cr(" $: dump only, no header, no other columns"); + _output->print_cr(" !: show nodes on IGV (sent over network stream)"); _output->print_cr(""); _output->print_cr("recursively follow edges to nodes with permitted visit types,"); _output->print_cr("on the boundary additionally display nodes allowed in boundary types"); @@ -2202,6 +2210,9 @@ bool PrintBFS::parse_options() { case '$': _dump_only = true; break; + case '!': + _print_igv = true; + break; case 'h': print_options_help(false); return false; diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index f7b17361913..73cf9234808 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -2836,7 +2836,7 @@ void Parse::do_one_bytecode() { jio_snprintf(buffer, sizeof(buffer), "Bytecode %d: %s", bci(), Bytecodes::name(bc())); bool old = printer->traverse_outs(); printer->set_traverse_outs(true); - printer->print_method(buffer, perBytecode); + printer->print_graph(buffer); printer->set_traverse_outs(old); } #endif diff --git a/src/hotspot/share/opto/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index 7a83f8c7f27..dcdf3aa3f86 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -93,6 +93,15 @@ flags(BEFORE_MATCHING, "Before matching") \ flags(MATCHING, "After matching") \ flags(GLOBAL_CODE_MOTION, "Global code motion") \ + flags(INITIAL_LIVENESS, "Initial liveness") \ + flags(AGGRESSIVE_COALESCING, "Aggressive coalescing") \ + flags(INITIAL_SPILLING, "Initial spilling") \ + flags(CONSERVATIVE_COALESCING, "Conservative coalescing") \ + flags(ITERATIVE_SPILLING, "Iterative spilling") \ + flags(AFTER_ITERATIVE_SPILLING, "After iterative spilling") \ + flags(POST_ALLOCATION_COPY_REMOVAL, "Post-allocation copy removal") \ + flags(MERGE_MULTI_DEFS, "Merge multiple definitions") \ + flags(FIX_UP_SPILLS, "Fix up spills") \ flags(REGISTER_ALLOCATION, "Register Allocation") \ flags(BLOCK_ORDERING, "Block Ordering") \ flags(PEEPHOLE, "Peephole") \ diff --git a/src/hotspot/share/opto/predicates.cpp b/src/hotspot/share/opto/predicates.cpp index 5e600eab2f0..b57a4d6fdf1 100644 --- a/src/hotspot/share/opto/predicates.cpp +++ b/src/hotspot/share/opto/predicates.cpp @@ -33,10 +33,10 @@ // Walk over all Initialized Assertion Predicates and return the entry into the first Initialized Assertion Predicate // (i.e. not belonging to an Initialized Assertion Predicate anymore) -Node* AssertionPredicatesWithHalt::find_entry(Node* start_proj) { +Node* AssertionPredicates::find_entry(Node* start_proj) { assert(start_proj != nullptr, "should not be null"); Node* entry = start_proj; - while (AssertionPredicateWithHalt::is_predicate(entry)) { + while (AssertionPredicate::is_predicate(entry)) { entry = entry->in(0)->in(0); } return entry; @@ -48,7 +48,7 @@ bool may_be_assertion_predicate_if(const Node* node) { return node->is_IfTrue() && RegularPredicate::may_be_predicate_if(node->as_IfProj()); } -bool AssertionPredicateWithHalt::is_predicate(const Node* maybe_success_proj) { +bool AssertionPredicate::is_predicate(const Node* maybe_success_proj) { if (!may_be_assertion_predicate_if(maybe_success_proj)) { return false; } @@ -57,14 +57,14 @@ bool AssertionPredicateWithHalt::is_predicate(const Node* maybe_success_proj) { // Check if the If node of `predicate_proj` has an OpaqueTemplateAssertionPredicate (Template Assertion Predicate) or // an OpaqueInitializedAssertionPredicate (Initialized Assertion Predicate) node as input. -bool AssertionPredicateWithHalt::has_assertion_predicate_opaque(const Node* predicate_proj) { +bool AssertionPredicate::has_assertion_predicate_opaque(const Node* predicate_proj) { IfNode* iff = predicate_proj->in(0)->as_If(); Node* bol = iff->in(1); return bol->is_OpaqueTemplateAssertionPredicate() || bol->is_OpaqueInitializedAssertionPredicate(); } // Check if the other projection (UCT projection) of `success_proj` has a Halt node as output. -bool AssertionPredicateWithHalt::has_halt(const Node* success_proj) { +bool AssertionPredicate::has_halt(const Node* success_proj) { ProjNode* other_proj = success_proj->as_IfProj()->other_if_proj(); return other_proj->outcnt() == 1 && other_proj->unique_out()->Opcode() == Op_Halt; } @@ -82,7 +82,7 @@ ParsePredicateNode* ParsePredicate::init_parse_predicate(Node* parse_predicate_p return nullptr; } -Deoptimization::DeoptReason RegularPredicateWithUCT::uncommon_trap_reason(IfProjNode* if_proj) { +Deoptimization::DeoptReason RuntimePredicate::uncommon_trap_reason(IfProjNode* if_proj) { CallStaticJavaNode* uct_call = if_proj->is_uncommon_trap_if_pattern(); if (uct_call == nullptr) { return Deoptimization::Reason_none; @@ -90,7 +90,7 @@ Deoptimization::DeoptReason RegularPredicateWithUCT::uncommon_trap_reason(IfProj return Deoptimization::trap_request_reason(uct_call->uncommon_trap_request()); } -bool RegularPredicateWithUCT::is_predicate(Node* maybe_success_proj) { +bool RuntimePredicate::is_predicate(Node* maybe_success_proj) { if (RegularPredicate::may_be_predicate_if(maybe_success_proj)) { return has_valid_uncommon_trap(maybe_success_proj); } else { @@ -98,7 +98,7 @@ bool RegularPredicateWithUCT::is_predicate(Node* maybe_success_proj) { } } -bool RegularPredicateWithUCT::has_valid_uncommon_trap(const Node* success_proj) { +bool RuntimePredicate::has_valid_uncommon_trap(const Node* success_proj) { assert(RegularPredicate::may_be_predicate_if(success_proj), "must have been checked before"); const Deoptimization::DeoptReason deopt_reason = uncommon_trap_reason(success_proj->as_IfProj()); return (deopt_reason == Deoptimization::Reason_loop_limit_check || @@ -106,7 +106,7 @@ bool RegularPredicateWithUCT::has_valid_uncommon_trap(const Node* success_proj) deopt_reason == Deoptimization::Reason_profile_predicate); } -bool RegularPredicateWithUCT::is_predicate(const Node* node, Deoptimization::DeoptReason deopt_reason) { +bool RuntimePredicate::is_predicate(const Node* node, const Deoptimization::DeoptReason deopt_reason) { if (RegularPredicate::may_be_predicate_if(node)) { return deopt_reason == uncommon_trap_reason(node->as_IfProj()); } else { @@ -128,16 +128,6 @@ bool RegularPredicate::may_be_predicate_if(const Node* node) { return false; } -// Runtime Predicates always have an UCT since they could normally fail at runtime. In this case we execute the trap -// on the failing path. -bool RuntimePredicate::is_predicate(Node* node) { - return RegularPredicateWithUCT::is_predicate(node); -} - -bool RuntimePredicate::is_predicate(Node* node, Deoptimization::DeoptReason deopt_reason) { - return RegularPredicateWithUCT::is_predicate(node, deopt_reason); -} - // Rewire any non-CFG nodes dependent on this Template Assertion Predicate (i.e. with a control input to this // Template Assertion Predicate) to the 'target_predicate' based on the 'data_in_loop_body' check. void TemplateAssertionPredicate::rewire_loop_data_dependencies(IfTrueNode* target_predicate, @@ -161,6 +151,21 @@ bool TemplateAssertionPredicate::is_predicate(Node* node) { return if_node->in(1)->is_OpaqueTemplateAssertionPredicate(); } +// Clone this Template Assertion Predicate and replace the OpaqueLoopInitNode with the provided 'new_opaque_init' node. +IfTrueNode* TemplateAssertionPredicate::clone(Node* new_control, PhaseIdealLoop* phase) const { + assert(PhaseIdealLoop::assertion_predicate_has_loop_opaque_node(_if_node), + "must find OpaqueLoop* nodes for Template Assertion Predicate"); + TemplateAssertionExpression template_assertion_expression(opaque_node()); + OpaqueTemplateAssertionPredicateNode* new_opaque_node = template_assertion_expression.clone(new_control, phase); + AssertionPredicateIfCreator assertion_predicate_if_creator(phase); + IfTrueNode* success_proj = assertion_predicate_if_creator.create_for_template(new_control, _if_node->Opcode(), + new_opaque_node, + _if_node->assertion_predicate_type()); + assert(PhaseIdealLoop::assertion_predicate_has_loop_opaque_node(success_proj->in(0)->as_If()), + "Template Assertion Predicates must have OpaqueLoop* nodes in the bool expression"); + return success_proj; +} + // Clone this Template Assertion Predicate and replace the OpaqueLoopInitNode with the provided 'new_opaque_init' node. IfTrueNode* TemplateAssertionPredicate::clone_and_replace_init(Node* new_control, OpaqueLoopInitNode* new_opaque_init, PhaseIdealLoop* phase) const { @@ -168,7 +173,7 @@ IfTrueNode* TemplateAssertionPredicate::clone_and_replace_init(Node* new_control "must find OpaqueLoop* nodes for Template Assertion Predicate"); TemplateAssertionExpression template_assertion_expression(opaque_node()); OpaqueTemplateAssertionPredicateNode* new_opaque_node = - template_assertion_expression.clone_and_replace_init(new_opaque_init, new_control, phase); + template_assertion_expression.clone_and_replace_init(new_control, new_opaque_init, phase); AssertionPredicateIfCreator assertion_predicate_if_creator(phase); IfTrueNode* success_proj = assertion_predicate_if_creator.create_for_template(new_control, _if_node->Opcode(), new_opaque_node, @@ -295,16 +300,16 @@ class ReplaceInitAndStrideStrategy : public TransformStrategyForOpaqueLoopNodes // OpaqueTemplateAssertionPredicate to and including the OpaqueLoop* nodes). The cloned nodes are rewired to reflect the // same graph structure as found for this Template Assertion Expression. The cloned nodes get 'new_ctrl' as ctrl. There // is no other update done for the cloned nodes. Return the newly cloned OpaqueTemplateAssertionPredicate. -OpaqueTemplateAssertionPredicateNode* TemplateAssertionExpression::clone(Node* new_ctrl, PhaseIdealLoop* phase) { - CloneStrategy clone_init_and_stride_strategy(phase, new_ctrl); - return clone(clone_init_and_stride_strategy, new_ctrl, phase); +OpaqueTemplateAssertionPredicateNode* TemplateAssertionExpression::clone(Node* new_control, PhaseIdealLoop* phase) { + CloneStrategy clone_init_and_stride_strategy(phase, new_control); + return clone(clone_init_and_stride_strategy, new_control, phase); } // Same as clone() but instead of cloning the OpaqueLoopInitNode, we replace it with the provided 'new_init' node. OpaqueTemplateAssertionPredicateNode* -TemplateAssertionExpression::clone_and_replace_init(Node* new_init, Node* new_ctrl, PhaseIdealLoop* phase) { - ReplaceInitAndCloneStrideStrategy replace_init_and_clone_stride_strategy(new_init, new_ctrl, phase); - return clone(replace_init_and_clone_stride_strategy, new_ctrl, phase); +TemplateAssertionExpression::clone_and_replace_init(Node* new_control, Node* new_init, PhaseIdealLoop* phase) { + ReplaceInitAndCloneStrideStrategy replace_init_and_clone_stride_strategy(new_init, new_control, phase); + return clone(replace_init_and_clone_stride_strategy, new_control, phase); } // Same as clone() but instead of cloning the OpaqueLoopInit and OpaqueLoopStride node, we replace them with the provided @@ -617,26 +622,6 @@ void AssertionPredicateIfCreator::create_halt_node(IfFalseNode* fail_proj, Ideal _phase->register_control(halt, loop, fail_proj); } -// Creates an init and last value Template Assertion Predicate connected together from a Parse Predicate with an UCT on -// the failing path. Returns the success projection of the last value Template Assertion Predicate. -IfTrueNode* TemplateAssertionPredicateCreator::create_with_uncommon_trap( - Node* new_control, ParsePredicateSuccessProj* parse_predicate_success_proj, - const Deoptimization::DeoptReason deopt_reason, const int if_opcode) { - OpaqueLoopInitNode* opaque_init = create_opaque_init(new_control); - bool does_overflow; - OpaqueTemplateAssertionPredicateNode* template_assertion_predicate_expression = - create_for_init_value(new_control, opaque_init, does_overflow); - IfTrueNode* template_predicate_success_proj = - create_if_node_with_uncommon_trap(template_assertion_predicate_expression, parse_predicate_success_proj, - deopt_reason, if_opcode, does_overflow, - AssertionPredicateType::InitValue); - template_assertion_predicate_expression = create_for_last_value(template_predicate_success_proj, opaque_init, - does_overflow); - return create_if_node_with_uncommon_trap(template_assertion_predicate_expression, parse_predicate_success_proj, - deopt_reason, if_opcode, does_overflow, - AssertionPredicateType::LastValue); -} - OpaqueLoopInitNode* TemplateAssertionPredicateCreator::create_opaque_init(Node* new_control) { OpaqueLoopInitNode* opaque_init = new OpaqueLoopInitNode(_phase->C, _loop_head->init_trip()); _phase->register_new_node(opaque_init, new_control); @@ -650,17 +635,6 @@ TemplateAssertionPredicateCreator::create_for_init_value(Node* new_control, Opaq return expression_creator.create_for_template(new_control, opaque_init, does_overflow); } -IfTrueNode* TemplateAssertionPredicateCreator::create_if_node_with_uncommon_trap( - OpaqueTemplateAssertionPredicateNode* template_assertion_predicate_expression, - ParsePredicateSuccessProj* parse_predicate_success_proj, const Deoptimization::DeoptReason deopt_reason, - const int if_opcode, const bool does_overflow, const AssertionPredicateType assertion_predicate_type) { - IfTrueNode* success_proj = _phase->create_new_if_for_predicate(parse_predicate_success_proj, nullptr, deopt_reason, - does_overflow ? Op_If : if_opcode, false, - assertion_predicate_type); - _phase->igvn().replace_input_of(success_proj->in(0), 1, template_assertion_predicate_expression); - return success_proj; -} - OpaqueTemplateAssertionPredicateNode* TemplateAssertionPredicateCreator::create_for_last_value(Node* new_control, OpaqueLoopInitNode* opaque_init, bool& does_overflow) const { @@ -683,7 +657,7 @@ Node* TemplateAssertionPredicateCreator::create_last_value(Node* new_control, Op return last_value; } -IfTrueNode* TemplateAssertionPredicateCreator::create_if_node_with_halt( +IfTrueNode* TemplateAssertionPredicateCreator::create_if_node( Node* new_control, OpaqueTemplateAssertionPredicateNode* template_assertion_predicate_expression, const bool does_overflow, const AssertionPredicateType assertion_predicate_type) { AssertionPredicateIfCreator assertion_predicate_if_creator(_phase); @@ -694,18 +668,18 @@ IfTrueNode* TemplateAssertionPredicateCreator::create_if_node_with_halt( // Creates an init and last value Template Assertion Predicate connected together with a Halt node on the failing path. // Returns the success projection of the last value Template Assertion Predicate latter. -IfTrueNode* TemplateAssertionPredicateCreator::create_with_halt(Node* new_control) { +IfTrueNode* TemplateAssertionPredicateCreator::create(Node* new_control) { OpaqueLoopInitNode* opaque_init = create_opaque_init(new_control); bool does_overflow; OpaqueTemplateAssertionPredicateNode* template_assertion_predicate_expression = create_for_init_value(new_control, opaque_init, does_overflow); IfTrueNode* template_predicate_success_proj = - create_if_node_with_halt(new_control, template_assertion_predicate_expression, does_overflow, - AssertionPredicateType::InitValue); + create_if_node(new_control, template_assertion_predicate_expression, does_overflow, + AssertionPredicateType::InitValue); template_assertion_predicate_expression = create_for_last_value(template_predicate_success_proj, opaque_init, does_overflow); - return create_if_node_with_halt(template_predicate_success_proj, template_assertion_predicate_expression, - does_overflow, AssertionPredicateType::LastValue); + return create_if_node(template_predicate_success_proj, template_assertion_predicate_expression, + does_overflow, AssertionPredicateType::LastValue); } InitializedAssertionPredicateCreator::InitializedAssertionPredicateCreator(PhaseIdealLoop* phase) diff --git a/src/hotspot/share/opto/predicates.hpp b/src/hotspot/share/opto/predicates.hpp index 342650cd966..4b8440f5aae 100644 --- a/src/hotspot/share/opto/predicates.hpp +++ b/src/hotspot/share/opto/predicates.hpp @@ -252,15 +252,15 @@ class NodeInLoopBody : public StackObj { virtual bool check(Node* node) const = 0; }; -// Class to represent Assertion Predicates with a HaltNode instead of an UCT (i.e. either an Initialized Assertion -// Predicate or a Template Assertion Predicate created after the initial one at Loop Predication). -class AssertionPredicatesWithHalt : public StackObj { - Node* _entry; +// Class to represent Assertion Predicates (i.e. either Initialized and/or Template Assertion Predicates). +class AssertionPredicates : public StackObj { + Node* const _entry; static Node* find_entry(Node* start_proj); public: - AssertionPredicatesWithHalt(Node* assertion_predicate_proj) : _entry(find_entry(assertion_predicate_proj)) {} + explicit AssertionPredicates(Node* assertion_predicate_proj) : _entry(find_entry(assertion_predicate_proj)) {} + NONCOPYABLE(AssertionPredicates); // Returns the control input node into the first assertion predicate If. If there are no assertion predicates, it // returns the same node initially passed to the constructor. @@ -269,15 +269,14 @@ class AssertionPredicatesWithHalt : public StackObj { } }; -// Class to represent a single Assertion Predicate with a HaltNode. This could either be: +// Class to represent a single Assertion Predicate. This could either be: // - A Template Assertion Predicate. // - An Initialized Assertion Predicate. -// Note that all other Regular Predicates have an UCT node. -class AssertionPredicateWithHalt : public StackObj { +class AssertionPredicate : public StackObj { static bool has_assertion_predicate_opaque(const Node* predicate_proj); + static bool has_halt(const Node* success_proj); public: static bool is_predicate(const Node* maybe_success_proj); - static bool has_halt(const Node* success_proj); }; // Utility class representing a Regular Predicate which is either a Runtime Predicate or an Assertion Predicate. @@ -286,19 +285,6 @@ class RegularPredicate : public StackObj { static bool may_be_predicate_if(const Node* node); }; -// Class to represent a single Regular Predicate with an UCT. This could either be: -// - A Runtime Predicate -// - A Template Assertion Predicate -// Note that all other Regular Predicates have a Halt node. -class RegularPredicateWithUCT : public StackObj { - static Deoptimization::DeoptReason uncommon_trap_reason(IfProjNode* if_proj); - - public: - static bool is_predicate(Node* maybe_success_proj); - static bool is_predicate(const Node* node, Deoptimization::DeoptReason deopt_reason); - static bool has_valid_uncommon_trap(const Node* success_proj); -}; - // Class to represent a Parse Predicate. class ParsePredicate : public Predicate { ParsePredicateSuccessProj* _success_proj; @@ -356,6 +342,8 @@ class RuntimePredicate : public Predicate { private: static bool is_predicate(Node* maybe_success_proj); + static bool has_valid_uncommon_trap(const Node* success_proj); + static Deoptimization::DeoptReason uncommon_trap_reason(IfProjNode* if_proj); public: Node* entry() const override { @@ -370,7 +358,7 @@ class RuntimePredicate : public Predicate { return _success_proj; } - static bool is_predicate(Node* node, Deoptimization::DeoptReason deopt_reason); + static bool is_predicate(const Node* node, Deoptimization::DeoptReason deopt_reason); }; // Class to represent a Template Assertion Predicate. @@ -405,6 +393,7 @@ class TemplateAssertionPredicate : public Predicate { return _if_node->assertion_predicate_type() == AssertionPredicateType::LastValue; } + IfTrueNode* clone(Node* new_control, PhaseIdealLoop* phase) const; IfTrueNode* clone_and_replace_init(Node* new_control, OpaqueLoopInitNode* new_opaque_init, PhaseIdealLoop* phase) const; void replace_opaque_stride_input(Node* new_stride, PhaseIterGVN& igvn) const; IfTrueNode* initialize(PhaseIdealLoop* phase, Node* new_control) const; @@ -466,8 +455,9 @@ class TemplateAssertionExpression : public StackObj { Node* new_ctrl, PhaseIdealLoop* phase); public: - OpaqueTemplateAssertionPredicateNode* clone(Node* new_ctrl, PhaseIdealLoop* phase); - OpaqueTemplateAssertionPredicateNode* clone_and_replace_init(Node* new_init, Node* new_ctrl, PhaseIdealLoop* phase); + OpaqueTemplateAssertionPredicateNode* clone(Node* new_control, PhaseIdealLoop* phase); + OpaqueTemplateAssertionPredicateNode* clone_and_replace_init(Node* new_control, Node* new_init, + PhaseIdealLoop* phase); OpaqueTemplateAssertionPredicateNode* clone_and_replace_init_and_stride(Node* new_control, Node* new_init, Node* new_stride, PhaseIdealLoop* phase); void replace_opaque_stride_input(Node* new_stride, PhaseIterGVN& igvn); @@ -570,7 +560,7 @@ class AssertionPredicateIfCreator : public StackObj { void create_halt_node(IfFalseNode* fail_proj, IdealLoopTree* loop, const char* halt_message); }; -// This class is used to create a Template Assertion Predicate either with an UCT or a Halt Node from scratch. +// This class is used to create a Template Assertion Predicate either with a Halt Node from scratch. class TemplateAssertionPredicateCreator : public StackObj { CountedLoopNode* const _loop_head; const int _scale; @@ -584,13 +574,9 @@ class TemplateAssertionPredicateCreator : public StackObj { OpaqueTemplateAssertionPredicateNode* create_for_last_value(Node* new_control, OpaqueLoopInitNode* opaque_init, bool& does_overflow) const; Node* create_last_value(Node* new_control, OpaqueLoopInitNode* opaque_init) const; - IfTrueNode* create_if_node_with_uncommon_trap(OpaqueTemplateAssertionPredicateNode* template_assertion_predicate_expression, - ParsePredicateSuccessProj* parse_predicate_success_proj, - Deoptimization::DeoptReason deopt_reason, int if_opcode, - bool does_overflow, AssertionPredicateType assertion_predicate_type); - IfTrueNode* create_if_node_with_halt(Node* new_control, - OpaqueTemplateAssertionPredicateNode* template_assertion_predicate_expression, - bool does_overflow, AssertionPredicateType assertion_predicate_type); + IfTrueNode* create_if_node(Node* new_control, + OpaqueTemplateAssertionPredicateNode* template_assertion_predicate_expression, + bool does_overflow, AssertionPredicateType assertion_predicate_type); public: TemplateAssertionPredicateCreator(CountedLoopNode* loop_head, int scale, Node* offset, Node* range, @@ -602,9 +588,7 @@ class TemplateAssertionPredicateCreator : public StackObj { _phase(phase) {} NONCOPYABLE(TemplateAssertionPredicateCreator); - IfTrueNode* create_with_uncommon_trap(Node* new_control, ParsePredicateSuccessProj* parse_predicate_success_proj, - Deoptimization::DeoptReason deopt_reason, int if_opcode); - IfTrueNode* create_with_halt(Node* new_control); + IfTrueNode* create(Node* new_control); }; // This class creates a new Initialized Assertion Predicate either from a template or from scratch. diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 20c8dfbff17..8000e4fd39e 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -1868,6 +1868,7 @@ bool SuperWord::schedule_and_apply() const { } if (!vtransform.schedule()) { return false; } + if (vtransform.has_store_to_load_forwarding_failure()) { return false; } vtransform.apply(); return true; } diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 70cd46c900d..407a4a20a9b 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -77,7 +77,7 @@ const Type::TypeInfo Type::_type_info[Type::lastype] = { { Bad, T_ILLEGAL, "vectora:", false, Op_VecA, relocInfo::none }, // VectorA. { Bad, T_ILLEGAL, "vectors:", false, 0, relocInfo::none }, // VectorS { Bad, T_ILLEGAL, "vectord:", false, Op_RegL, relocInfo::none }, // VectorD - { Bad, T_ILLEGAL, "vectorx:", false, 0, relocInfo::none }, // VectorX + { Bad, T_ILLEGAL, "vectorx:", false, Op_VecX, relocInfo::none }, // VectorX { Bad, T_ILLEGAL, "vectory:", false, 0, relocInfo::none }, // VectorY { Bad, T_ILLEGAL, "vectorz:", false, 0, relocInfo::none }, // VectorZ #else // all other diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp index fc4eaccff5c..4d152189625 100644 --- a/src/hotspot/share/opto/vectorization.cpp +++ b/src/hotspot/share/opto/vectorization.cpp @@ -31,7 +31,7 @@ #include "opto/vectorization.hpp" #ifndef PRODUCT -static void print_con_or_idx(const Node* n) { +void VPointer::print_con_or_idx(const Node* n) { if (n == nullptr) { tty->print("( 0)"); } else if (n->is_ConI()) { @@ -1369,12 +1369,12 @@ void VPointer::print() const { tty->print("adr: %4d, ", _adr != nullptr ? _adr->_idx : 0); tty->print(" base"); - print_con_or_idx(_base); + VPointer::print_con_or_idx(_base); tty->print(" + offset(%4d)", _offset); tty->print(" + invar"); - print_con_or_idx(_invar); + VPointer::print_con_or_idx(_invar); tty->print_cr(" + scale(%4d) * iv]", _scale); } @@ -2168,15 +2168,15 @@ void AlignmentSolver::trace_start_solve() const { // iv = init + pre_iter * pre_stride + main_iter * main_stride tty->print(" iv = init"); - print_con_or_idx(_init_node); + VPointer::print_con_or_idx(_init_node); tty->print_cr(" + pre_iter * pre_stride(%d) + main_iter * main_stride(%d)", _pre_stride, _main_stride); // adr = base + offset + invar + scale * iv tty->print(" adr = base"); - print_con_or_idx(_base); + VPointer::print_con_or_idx(_base); tty->print(" + offset(%d) + invar", _offset); - print_con_or_idx(_invar); + VPointer::print_con_or_idx(_invar); tty->print_cr(" + scale(%d) * iv", _scale); } } diff --git a/src/hotspot/share/opto/vectorization.hpp b/src/hotspot/share/opto/vectorization.hpp index b084edd44b3..98aa3336ded 100644 --- a/src/hotspot/share/opto/vectorization.hpp +++ b/src/hotspot/share/opto/vectorization.hpp @@ -870,6 +870,7 @@ class VPointer : public ArenaObj { static int cmp_for_sort(const VPointer** p1, const VPointer** p2); NOT_PRODUCT( void print() const; ) + NOT_PRODUCT( static void print_con_or_idx(const Node* n); ) #ifndef PRODUCT class Tracer { diff --git a/src/hotspot/share/opto/vtransform.cpp b/src/hotspot/share/opto/vtransform.cpp index 7c7aca3b90e..d09a4c899f6 100644 --- a/src/hotspot/share/opto/vtransform.cpp +++ b/src/hotspot/share/opto/vtransform.cpp @@ -144,6 +144,274 @@ void VTransformApplyResult::trace(VTransformNode* vtnode) const { } #endif +// We use two comparisons, because a subtraction could underflow. +#define RETURN_CMP_VALUE_IF_NOT_EQUAL(a, b) \ + if (a < b) { return -1; } \ + if (a > b) { return 1; } + +// Helper-class for VTransformGraph::has_store_to_load_forwarding_failure. +// It represents a memory region: [ptr, ptr + memory_size) +class VMemoryRegion : public StackObj { +private: + Node* _base; // ptr = base + offset + invar + scale * iv + int _scale; + Node* _invar; + int _offset; + uint _memory_size; + bool _is_load; // load or store? + uint _schedule_order; + +public: + VMemoryRegion() {} // empty constructor for GrowableArray + VMemoryRegion(const VPointer& vpointer, int iv_offset, int vector_length, uint schedule_order) : + _base(vpointer.base()), + _scale(vpointer.scale_in_bytes()), + _invar(vpointer.invar()), + _offset(vpointer.offset_in_bytes() + _scale * iv_offset), + _memory_size(vpointer.memory_size() * vector_length), + _is_load(vpointer.mem()->is_Load()), + _schedule_order(schedule_order) {} + + Node* base() const { return _base; } + int scale() const { return _scale; } + Node* invar() const { return _invar; } + int offset() const { return _offset; } + uint memory_size() const { return _memory_size; } + bool is_load() const { return _is_load; } + uint schedule_order() const { return _schedule_order; } + + static int cmp_for_sort_by_group(VMemoryRegion* r1, VMemoryRegion* r2) { + RETURN_CMP_VALUE_IF_NOT_EQUAL(r1->base()->_idx, r2->base()->_idx); + RETURN_CMP_VALUE_IF_NOT_EQUAL(r1->scale(), r2->scale()); + int r1_invar_idx = r1->invar() == nullptr ? 0 : r1->invar()->_idx; + int r2_invar_idx = r2->invar() == nullptr ? 0 : r2->invar()->_idx; + RETURN_CMP_VALUE_IF_NOT_EQUAL(r1_invar_idx, r2_invar_idx); + return 0; // equal + } + + static int cmp_for_sort(VMemoryRegion* r1, VMemoryRegion* r2) { + int cmp_group = cmp_for_sort_by_group(r1, r2); + if (cmp_group != 0) { return cmp_group; } + + RETURN_CMP_VALUE_IF_NOT_EQUAL(r1->offset(), r2->offset()); + return 0; // equal + } + + enum Aliasing { DIFFERENT_GROUP, BEFORE, EXACT_OVERLAP, PARTIAL_OVERLAP, AFTER }; + + Aliasing aliasing(VMemoryRegion& other) { + VMemoryRegion* p1 = this; + VMemoryRegion* p2 = &other; + if (cmp_for_sort_by_group(p1, p2) != 0) { return DIFFERENT_GROUP; } + + jlong offset1 = p1->offset(); + jlong offset2 = p2->offset(); + jlong memory_size1 = p1->memory_size(); + jlong memory_size2 = p2->memory_size(); + + if (offset1 >= offset2 + memory_size2) { return AFTER; } + if (offset2 >= offset1 + memory_size1) { return BEFORE; } + if (offset1 == offset2 && memory_size1 == memory_size2) { return EXACT_OVERLAP; } + return PARTIAL_OVERLAP; + } + +#ifndef PRODUCT + void print() const { + tty->print("VMemoryRegion[%s %dbytes, schedule_order(%4d), base", + _is_load ? "load " : "store", _memory_size, _schedule_order); + VPointer::print_con_or_idx(_base); + tty->print(" + offset(%4d)", _offset); + tty->print(" + invar"); + VPointer::print_con_or_idx(_invar); + tty->print_cr(" + scale(%4d) * iv]", _scale); + } +#endif +}; + +// Store-to-load-forwarding is a CPU memory optimization, where a load can directly fetch +// its value from the store-buffer, rather than from the L1 cache. This is many CPU cycles +// faster. However, this optimization comes with some restrictions, depending on the CPU. +// Generally, store-to-load-forwarding works if the load and store memory regions match +// exactly (same start and width). Generally problematic are partial overlaps - though +// some CPU's can handle even some subsets of these cases. We conservatively assume that +// all such partial overlaps lead to a store-to-load-forwarding failures, which means the +// load has to stall until the store goes from the store-buffer into the L1 cache, incurring +// a penalty of many CPU cycles. +// +// Example (with "iteration distance" 2): +// for (int i = 10; i < SIZE; i++) { +// aI[i] = aI[i - 2] + 1; +// } +// +// load_4_bytes( ptr + -8) +// store_4_bytes(ptr + 0) * +// load_4_bytes( ptr + -4) | +// store_4_bytes(ptr + 4) | * +// load_4_bytes( ptr + 0) <-+ | +// store_4_bytes(ptr + 8) | +// load_4_bytes( ptr + 4) <---+ +// store_4_bytes(ptr + 12) +// ... +// +// In the scalar loop, we can forward the stores from 2 iterations back. +// +// Assume we have 2-element vectors (2*4 = 8 bytes), with the "iteration distance" 2 +// example. This gives us this machine code: +// load_8_bytes( ptr + -8) +// store_8_bytes(ptr + 0) | +// load_8_bytes( ptr + 0) v +// store_8_bytes(ptr + 8) | +// load_8_bytes( ptr + 8) v +// store_8_bytes(ptr + 16) +// ... +// +// We packed 2 iterations, and the stores can perfectly forward to the loads of +// the next 2 iterations. +// +// Example (with "iteration distance" 3): +// for (int i = 10; i < SIZE; i++) { +// aI[i] = aI[i - 3] + 1; +// } +// +// load_4_bytes( ptr + -12) +// store_4_bytes(ptr + 0) * +// load_4_bytes( ptr + -8) | +// store_4_bytes(ptr + 4) | +// load_4_bytes( ptr + -4) | +// store_4_bytes(ptr + 8) | +// load_4_bytes( ptr + 0) <-+ +// store_4_bytes(ptr + 12) +// ... +// +// In the scalar loop, we can forward the stores from 3 iterations back. +// +// Unfortunately, vectorization can introduce such store-to-load-forwarding failures. +// Assume we have 2-element vectors (2*4 = 8 bytes), with the "iteration distance" 3 +// example. This gives us this machine code: +// load_8_bytes( ptr + -12) +// store_8_bytes(ptr + 0) | | +// load_8_bytes( ptr + -4) x | +// store_8_bytes(ptr + 8) || +// load_8_bytes( ptr + 4) xx <-- partial overlap with 2 stores +// store_8_bytes(ptr + 16) +// ... +// +// We see that eventually all loads are dependent on earlier stores, but the values cannot +// be forwarded because there is some partial overlap. +// +// Preferably, we would have some latency-based cost-model that accounts for such forwarding +// failures, and decide if vectorization with forwarding failures is still profitable. For +// now we go with a simpler heuristic: we simply forbid vectorization if we can PROVE that +// there will be a forwarding failure. This approach has at least 2 possible weaknesses: +// +// (1) There may be forwarding failures in cases where we cannot prove it. +// Example: +// for (int i = 10; i < SIZE; i++) { +// bI[i] = aI[i - 3] + 1; +// } +// +// We do not know if aI and bI refer to the same array or not. However, it is reasonable +// to assume that if we have two different array references, that they most likely refer +// to different arrays (i.e. no aliasing), where we would have no forwarding failures. +// (2) There could be some loops where vectorization introduces forwarding failures, and thus +// the latency of the loop body is high, but this does not matter because it is dominated +// by other latency/throughput based costs in the loop body. +// +// Performance measurements with the JMH benchmark StoreToLoadForwarding.java have indicated +// that there is some iteration threshold: if the failure happens between a store and load that +// have an iteration distance below this threshold, the latency is the limiting factor, and we +// should not vectorize to avoid the latency penalty of store-to-load-forwarding failures. If +// the iteration distance is larger than this threshold, the throughput is the limiting factor, +// and we should vectorize in these cases to improve throughput. +// +bool VTransformGraph::has_store_to_load_forwarding_failure(const VLoopAnalyzer& vloop_analyzer) const { + if (SuperWordStoreToLoadForwardingFailureDetection == 0) { return false; } + + // Collect all pointers for scalar and vector loads/stores. + ResourceMark rm; + GrowableArray memory_regions; + + // To detect store-to-load-forwarding failures at the iteration threshold or below, we + // simulate a super-unrolling to reach SuperWordStoreToLoadForwardingFailureDetection + // iterations at least. This is a heuristic, and we are not trying to be very precise + // with the iteration distance. If we have already unrolled more than the iteration + // threshold, i.e. if "SuperWordStoreToLoadForwardingFailureDetection < unrolled_count", + // then we simply check if there are any store-to-load-forwarding failures in the unrolled + // loop body, which may be at larger distance than the desired threshold. We cannot do any + // more fine-grained analysis, because the unrolling has lost the information about the + // iteration distance. + int simulated_unrolling_count = SuperWordStoreToLoadForwardingFailureDetection; + int unrolled_count = vloop_analyzer.vloop().cl()->unrolled_count(); + uint simulated_super_unrolling_count = MAX2(1, simulated_unrolling_count / unrolled_count); + int iv_stride = vloop_analyzer.vloop().iv_stride(); + int schedule_order = 0; + for (uint k = 0; k < simulated_super_unrolling_count; k++) { + int iv_offset = k * iv_stride; // virtual super-unrolling + for (int i = 0; i < _schedule.length(); i++) { + VTransformNode* vtn = _schedule.at(i); + if (vtn->is_load_or_store_in_loop()) { + const VPointer& p = vtn->vpointer(vloop_analyzer); + if (p.valid()) { + VTransformVectorNode* vector = vtn->isa_Vector(); + uint vector_length = vector != nullptr ? vector->nodes().length() : 1; + memory_regions.push(VMemoryRegion(p, iv_offset, vector_length, schedule_order++)); + } + } + } + } + + // Sort the pointers by group (same base, invar and stride), and then by offset. + memory_regions.sort(VMemoryRegion::cmp_for_sort); + +#ifndef PRODUCT + if (_trace._verbose) { + tty->print_cr("VTransformGraph::has_store_to_load_forwarding_failure:"); + tty->print_cr(" simulated_unrolling_count = %d", simulated_unrolling_count); + tty->print_cr(" simulated_super_unrolling_count = %d", simulated_super_unrolling_count); + for (int i = 0; i < memory_regions.length(); i++) { + VMemoryRegion& region = memory_regions.at(i); + region.print(); + } + } +#endif + + // For all pairs of pointers in the same group, check if they have a partial overlap. + for (int i = 0; i < memory_regions.length(); i++) { + VMemoryRegion& region1 = memory_regions.at(i); + + for (int j = i + 1; j < memory_regions.length(); j++) { + VMemoryRegion& region2 = memory_regions.at(j); + + const VMemoryRegion::Aliasing aliasing = region1.aliasing(region2); + if (aliasing == VMemoryRegion::Aliasing::DIFFERENT_GROUP || + aliasing == VMemoryRegion::Aliasing::BEFORE) { + break; // We have reached the next group or pointers that are always after. + } else if (aliasing == VMemoryRegion::Aliasing::EXACT_OVERLAP) { + continue; + } else { + assert(aliasing == VMemoryRegion::Aliasing::PARTIAL_OVERLAP, "no other case can happen"); + if ((region1.is_load() && !region2.is_load() && region1.schedule_order() > region2.schedule_order()) || + (!region1.is_load() && region2.is_load() && region1.schedule_order() < region2.schedule_order())) { + // We predict that this leads to a store-to-load-forwarding failure penalty. +#ifndef PRODUCT + if (_trace._rejections) { + tty->print_cr("VTransformGraph::has_store_to_load_forwarding_failure:"); + tty->print_cr(" Partial overlap of store->load. We predict that this leads to"); + tty->print_cr(" a store-to-load-forwarding failure penalty which makes"); + tty->print_cr(" vectorization unprofitable. These are the two pointers:"); + region1.print(); + region2.print(); + } +#endif + return true; + } + } + } + } + + return false; +} + Node* VTransformNode::find_transformed_input(int i, const GrowableArray& vnode_idx_to_transformed_node) const { Node* n = vnode_idx_to_transformed_node.at(in(i)->_idx); assert(n != nullptr, "must find input IR node"); diff --git a/src/hotspot/share/opto/vtransform.hpp b/src/hotspot/share/opto/vtransform.hpp index ee298e7fe72..8ceca318f4a 100644 --- a/src/hotspot/share/opto/vtransform.hpp +++ b/src/hotspot/share/opto/vtransform.hpp @@ -66,6 +66,8 @@ class VTransformVectorNode; class VTransformElementWiseVectorNode; class VTransformBoolVectorNode; class VTransformReductionVectorNode; +class VTransformLoadVectorNode; +class VTransformStoreVectorNode; // Result from VTransformNode::apply class VTransformApplyResult { @@ -157,6 +159,7 @@ class VTransformGraph : public StackObj { const GrowableArray& vtnodes() const { return _vtnodes; } bool schedule(); + bool has_store_to_load_forwarding_failure(const VLoopAnalyzer& vloop_analyzer) const; void apply_memops_reordering_with_schedule() const; void apply_vectorization_for_each_vtnode(uint& max_vector_length, uint& max_vector_width) const; @@ -221,6 +224,7 @@ class VTransform : public StackObj { VTransformGraph& graph() { return _graph; } bool schedule() { return _graph.schedule(); } + bool has_store_to_load_forwarding_failure() const { return _graph.has_store_to_load_forwarding_failure(_vloop_analyzer); } void apply(); private: @@ -310,6 +314,11 @@ class VTransformNode : public ArenaObj { virtual VTransformElementWiseVectorNode* isa_ElementWiseVector() { return nullptr; } virtual VTransformBoolVectorNode* isa_BoolVector() { return nullptr; } virtual VTransformReductionVectorNode* isa_ReductionVector() { return nullptr; } + virtual VTransformLoadVectorNode* isa_LoadVector() { return nullptr; } + virtual VTransformStoreVectorNode* isa_StoreVector() { return nullptr; } + + virtual bool is_load_or_store_in_loop() const { return false; } + virtual const VPointer& vpointer(const VLoopAnalyzer& vloop_analyzer) const { ShouldNotReachHere(); } virtual VTransformApplyResult apply(const VLoopAnalyzer& vloop_analyzer, const GrowableArray& vnode_idx_to_transformed_node) const = 0; @@ -333,6 +342,8 @@ class VTransformScalarNode : public VTransformNode { VTransformNode(vtransform, n->req()), _node(n) {} Node* node() const { return _node; } virtual VTransformScalarNode* isa_Scalar() override { return this; } + virtual bool is_load_or_store_in_loop() const override { return _node->is_Load() || _node->is_Store(); } + virtual const VPointer& vpointer(const VLoopAnalyzer& vloop_analyzer) const override { return vloop_analyzer.vpointers().vpointer(node()->as_Mem()); } virtual VTransformApplyResult apply(const VLoopAnalyzer& vloop_analyzer, const GrowableArray& vnode_idx_to_transformed_node) const override; NOT_PRODUCT(virtual const char* name() const override { return "Scalar"; };) @@ -347,6 +358,7 @@ class VTransformInputScalarNode : public VTransformScalarNode { VTransformInputScalarNode(VTransform& vtransform, Node* n) : VTransformScalarNode(vtransform, n) {} virtual VTransformInputScalarNode* isa_InputScalar() override { return this; } + virtual bool is_load_or_store_in_loop() const override { return false; } NOT_PRODUCT(virtual const char* name() const override { return "InputScalar"; };) }; @@ -472,6 +484,9 @@ class VTransformLoadVectorNode : public VTransformVectorNode { VTransformLoadVectorNode(VTransform& vtransform, uint number_of_nodes) : VTransformVectorNode(vtransform, 3, number_of_nodes) {} LoadNode::ControlDependency control_dependency() const; + virtual VTransformLoadVectorNode* isa_LoadVector() override { return this; } + virtual bool is_load_or_store_in_loop() const override { return true; } + virtual const VPointer& vpointer(const VLoopAnalyzer& vloop_analyzer) const override { return vloop_analyzer.vpointers().vpointer(nodes().at(0)->as_Mem()); } virtual VTransformApplyResult apply(const VLoopAnalyzer& vloop_analyzer, const GrowableArray& vnode_idx_to_transformed_node) const override; NOT_PRODUCT(virtual const char* name() const override { return "LoadVector"; };) @@ -482,6 +497,9 @@ class VTransformStoreVectorNode : public VTransformVectorNode { // req = 4 -> [ctrl, mem, adr, val] VTransformStoreVectorNode(VTransform& vtransform, uint number_of_nodes) : VTransformVectorNode(vtransform, 4, number_of_nodes) {} + virtual VTransformStoreVectorNode* isa_StoreVector() override { return this; } + virtual bool is_load_or_store_in_loop() const override { return true; } + virtual const VPointer& vpointer(const VLoopAnalyzer& vloop_analyzer) const override { return vloop_analyzer.vpointers().vpointer(nodes().at(0)->as_Mem()); } virtual VTransformApplyResult apply(const VLoopAnalyzer& vloop_analyzer, const GrowableArray& vnode_idx_to_transformed_node) const override; NOT_PRODUCT(virtual const char* name() const override { return "StoreVector"; };) diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index 6efe45caf14..7bea3441fa5 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -288,7 +288,7 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR CHECK_NULL); ResourceMark rm(THREAD); - ClassFileStream st((u1*)buf, bufLen, nullptr, ClassFileStream::verify); + ClassFileStream st((u1*)buf, bufLen, nullptr); Handle class_loader (THREAD, JNIHandles::resolve(loaderRef)); Handle protection_domain; ClassLoadInfo cl_info(protection_domain); @@ -321,8 +321,6 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) SystemDictionary::class_name_symbol(name, vmSymbols::java_lang_NoClassDefFoundError(), CHECK_NULL); - //%note jni_3 - Handle protection_domain; // Find calling class Klass* k = thread->security_get_caller_class(0); // default to the system loader when no context @@ -344,15 +342,13 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) if (mirror != nullptr) { Klass* fromClass = java_lang_Class::as_Klass(mirror); loader = Handle(THREAD, fromClass->class_loader()); - protection_domain = Handle(THREAD, fromClass->protection_domain()); } } else { loader = Handle(THREAD, k->class_loader()); } } - result = find_class_from_class_loader(env, class_name, true, loader, - protection_domain, true, thread); + result = find_class_from_class_loader(env, class_name, true, loader, true, thread); if (log_is_enabled(Debug, class, resolve) && result != nullptr) { trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); @@ -537,8 +533,7 @@ JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message)) InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); Symbol* name = k->name(); Handle class_loader (THREAD, k->class_loader()); - Handle protection_domain (THREAD, k->protection_domain()); - THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK); + THROW_MSG_LOADER_(name, (char *)message, class_loader, JNI_OK); ShouldNotReachHere(); return 0; // Mute compiler. JNI_END @@ -2929,10 +2924,9 @@ static jfieldID bufferCapacityField = nullptr; static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) { Handle loader; // null (bootstrap) loader - Handle protection_domain; // null protection domain TempNewSymbol sym = SymbolTable::new_symbol(name); - jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL); + jclass result = find_class_from_class_loader(env, sym, true, loader, true, CHECK_NULL); if (log_is_enabled(Debug, class, resolve) && result != nullptr) { trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index a027351ff7b..b8e7f9c1ea2 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -151,29 +151,22 @@ and thus can only support use of handles passed in. */ -static void trace_class_resolution_impl(Klass* to_class, TRAPS) { +extern void trace_class_resolution(Klass* to_class) { ResourceMark rm; int line_number = -1; const char * source_file = nullptr; const char * trace = "explicit"; InstanceKlass* caller = nullptr; - JavaThread* jthread = THREAD; + JavaThread* jthread = JavaThread::current(); if (jthread->has_last_Java_frame()) { vframeStream vfst(jthread); - // scan up the stack skipping ClassLoader, AccessController and PrivilegedAction frames - TempNewSymbol access_controller = SymbolTable::new_symbol("java/security/AccessController"); - Klass* access_controller_klass = SystemDictionary::resolve_or_fail(access_controller, false, CHECK); - TempNewSymbol privileged_action = SymbolTable::new_symbol("java/security/PrivilegedAction"); - Klass* privileged_action_klass = SystemDictionary::resolve_or_fail(privileged_action, false, CHECK); - + // Scan up the stack skipping ClassLoader frames. Method* last_caller = nullptr; while (!vfst.at_end()) { Method* m = vfst.method(); - if (!vfst.method()->method_holder()->is_subclass_of(vmClasses::ClassLoader_klass())&& - !vfst.method()->method_holder()->is_subclass_of(access_controller_klass) && - !vfst.method()->method_holder()->is_subclass_of(privileged_action_klass)) { + if (!vfst.method()->method_holder()->is_subclass_of(vmClasses::ClassLoader_klass())) { break; } last_caller = m; @@ -232,14 +225,6 @@ static void trace_class_resolution_impl(Klass* to_class, TRAPS) { } } -void trace_class_resolution(Klass* to_class) { - EXCEPTION_MARK; - trace_class_resolution_impl(to_class, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } -} - // java.lang.System ////////////////////////////////////////////////////////////////////// @@ -833,20 +818,10 @@ JVM_ENTRY(jclass, JVM_FindClassFromCaller(JNIEnv* env, const char* name, oop loader_oop = JNIHandles::resolve(loader); oop from_class = JNIHandles::resolve(caller); - oop protection_domain = nullptr; - // If loader is null, shouldn't call ClassLoader.checkPackageAccess; otherwise get - // NPE. Put it in another way, the bootstrap class loader has all permission and - // thus no checkPackageAccess equivalence in the VM class loader. - // The caller is also passed as null by the java code if there is no security - // manager to avoid the performance cost of getting the calling class. - if (from_class != nullptr && loader_oop != nullptr) { - protection_domain = java_lang_Class::as_Klass(from_class)->protection_domain(); - } - Handle h_loader(THREAD, loader_oop); - Handle h_prot(THREAD, protection_domain); + jclass result = find_class_from_class_loader(env, h_name, init, h_loader, - h_prot, false, THREAD); + false, THREAD); if (log_is_enabled(Debug, class, resolve) && result != nullptr) { trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); @@ -865,15 +840,11 @@ JVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name, ? (Klass*)nullptr : java_lang_Class::as_Klass(from_class_oop); oop class_loader = nullptr; - oop protection_domain = nullptr; if (from_class != nullptr) { class_loader = from_class->class_loader(); - protection_domain = from_class->protection_domain(); } Handle h_loader(THREAD, class_loader); - Handle h_prot (THREAD, protection_domain); - jclass result = find_class_from_class_loader(env, h_name, init, h_loader, - h_prot, true, thread); + jclass result = find_class_from_class_loader(env, h_name, init, h_loader, true, thread); if (log_is_enabled(Debug, class, resolve) && result != nullptr) { // this function is generally only used for class loading during verification. @@ -917,7 +888,7 @@ static jclass jvm_define_class_common(const char *name, CHECK_NULL); ResourceMark rm(THREAD); - ClassFileStream st((u1*)buf, len, source, ClassFileStream::verify); + ClassFileStream st((u1*)buf, len, source); Handle class_loader (THREAD, JNIHandles::resolve(loader)); Handle protection_domain (THREAD, JNIHandles::resolve(pd)); ClassLoadInfo cl_info(protection_domain); @@ -1003,7 +974,7 @@ static jclass jvm_lookup_define_class(jclass lookup, const char *name, Handle protection_domain (THREAD, JNIHandles::resolve(pd)); const char* source = is_nestmate ? host_class->external_name() : "__JVM_LookupDefineClass__"; - ClassFileStream st((u1*)buf, len, source, ClassFileStream::verify); + ClassFileStream st((u1*)buf, len, source); InstanceKlass* ik = nullptr; if (!is_hidden) { @@ -1121,9 +1092,7 @@ JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name) // The Java level wrapper will perform the necessary security check allowing // us to pass the null as the initiating class loader. Handle h_loader(THREAD, JNIHandles::resolve(loader)); - Klass* k = SystemDictionary::find_instance_or_array_klass(THREAD, klass_name, - h_loader, - Handle()); + Klass* k = SystemDictionary::find_instance_or_array_klass(THREAD, klass_name, h_loader); #if INCLUDE_CDS if (k == nullptr) { // If the class is not already loaded, try to see if it's in the shared @@ -2838,7 +2807,7 @@ static void thread_entry(JavaThread* thread, TRAPS) { JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) #if INCLUDE_CDS - if (CDSConfig::is_dumping_static_archive()) { + if (CDSConfig::allow_only_single_java_thread()) { // During java -Xshare:dump, if we allow multiple Java threads to // execute in parallel, symbols and classes may be loaded in // random orders which will make the resulting CDS archive @@ -2951,7 +2920,6 @@ JVM_END JVM_LEAF(void, JVM_Yield(JNIEnv *env, jclass threadClass)) - if (os::dont_yield()) return; HOTSPOT_THREAD_YIELD(); os::naked_yield(); JVM_END @@ -3070,45 +3038,6 @@ JVM_ENTRY(void, JVM_SetScopedValueCache(JNIEnv* env, jclass threadClass, thread->set_scopedValueCache(objs); JVM_END -// java.lang.SecurityManager /////////////////////////////////////////////////////////////////////// - -JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env)) - ResourceMark rm(THREAD); - JvmtiVMObjectAllocEventCollector oam; - vframeStream vfst(thread); - - if (vmClasses::reflect_CallerSensitive_klass() != nullptr) { - // This must only be called from SecurityManager.getClassContext - Method* m = vfst.method(); - if (!(m->method_holder() == vmClasses::SecurityManager_klass() && - m->name() == vmSymbols::getClassContext_name() && - m->signature() == vmSymbols::void_class_array_signature())) { - THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetClassContext must only be called from SecurityManager.getClassContext"); - } - } - - // Collect method holders - GrowableArray* klass_array = new GrowableArray(); - for (; !vfst.at_end(); vfst.security_next()) { - Method* m = vfst.method(); - // Native frames are not returned - if (!m->is_ignored_by_security_stack_walk() && !m->is_native()) { - Klass* holder = m->method_holder(); - assert(holder->is_klass(), "just checking"); - klass_array->append(holder); - } - } - - // Create result array of type [Ljava/lang/Class; - objArrayOop result = oopFactory::new_objArray(vmClasses::Class_klass(), klass_array->length(), CHECK_NULL); - // Fill in mirrors corresponding to method holders - for (int i = 0; i < klass_array->length(); i++) { - result->obj_at_put(i, klass_array->at(i)->java_mirror()); - } - - return (jobjectArray) JNIHandles::make_local(THREAD, result); -JVM_END - // java.lang.Package //////////////////////////////////////////////////////////////// @@ -3422,15 +3351,8 @@ JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon) { // Shared JNI/JVM entry points ////////////////////////////////////////////////////////////// jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, - Handle loader, Handle protection_domain, - jboolean throwError, TRAPS) { - // Security Note: - // The Java level wrapper will perform the necessary security check allowing - // us to pass the null as the initiating class loader. The VM is responsible for - // the checkPackageAccess relative to the initiating class loader via the - // protection_domain. The protection_domain is passed as null by the java code - // if there is no security manager in 3-arg Class.forName(). - Klass* klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL); + Handle loader, jboolean throwError, TRAPS) { + Klass* klass = SystemDictionary::resolve_or_fail(name, loader, throwError != 0, CHECK_NULL); // Check if we should initialize the class if (init && klass->is_instance_klass()) { diff --git a/src/hotspot/share/prims/jvm_misc.hpp b/src/hotspot/share/prims/jvm_misc.hpp index 28b39631bf4..18c8e3b6ad5 100644 --- a/src/hotspot/share/prims/jvm_misc.hpp +++ b/src/hotspot/share/prims/jvm_misc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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,7 +31,7 @@ // Useful entry points shared by JNI and JVM interface. // We do not allow real JNI or JVM entry point to call each other. -jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS); +jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, jboolean throwError, TRAPS); void trace_class_resolution(Klass* to_class); diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 422bbced802..debfc77c32c 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1080,12 +1080,7 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread ObjectMonitor *mon = target->current_waiting_monitor(); if (mon != nullptr) wait_obj = mon->object(); } else { - assert(vthread != nullptr, "no vthread oop"); - oop cont = java_lang_VirtualThread::continuation(vthread); - assert(cont != nullptr, "vthread with no continuation"); - stackChunkOop chunk = jdk_internal_vm_Continuation::tail(cont); - assert(chunk != nullptr, "unmounted vthread should have a chunk"); - ObjectMonitor *mon = chunk->current_waiting_monitor(); + ObjectMonitor *mon = java_lang_VirtualThread::current_waiting_monitor(vthread); if (mon != nullptr) wait_obj = mon->object(); } } @@ -1099,12 +1094,7 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread ObjectMonitor *mon = target->current_pending_monitor(); if (mon != nullptr) pending_obj = mon->object(); } else { - assert(vthread != nullptr, "no vthread oop"); - oop cont = java_lang_VirtualThread::continuation(vthread); - assert(cont != nullptr, "vthread with no continuation"); - stackChunkOop chunk = jdk_internal_vm_Continuation::tail(cont); - assert(chunk != nullptr, "unmounted vthread should have a chunk"); - ObjectMonitor *mon = chunk->current_pending_monitor(); + ObjectMonitor *mon = java_lang_VirtualThread::current_pending_monitor(vthread); if (mon != nullptr) pending_obj = mon->object(); } } @@ -2569,12 +2559,9 @@ GetCurrentContendedMonitorClosure::do_thread(Thread *target) { void GetCurrentContendedMonitorClosure::do_vthread(Handle target_h) { if (_target_jt == nullptr) { - oop cont = java_lang_VirtualThread::continuation(target_h()); - assert(cont != nullptr, "vthread with no continuation"); - stackChunkOop chunk = jdk_internal_vm_Continuation::tail(cont); - assert(chunk != nullptr, "unmounted vthread should have a chunk"); - if (chunk->current_pending_monitor() != nullptr) { - *_owned_monitor_ptr = JNIHandles::make_local(_calling_thread, chunk->current_pending_monitor()->object()); + ObjectMonitor *mon = java_lang_VirtualThread::current_pending_monitor(target_h()); + if (mon != nullptr) { + *_owned_monitor_ptr = JNIHandles::make_local(_calling_thread, mon->object()); } _result = JVMTI_ERROR_NONE; // target virtual thread is unmounted return; diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index 087f426c537..c68692a2fa1 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -1075,6 +1075,16 @@ bool JvmtiExport::has_early_class_hook_env() { return false; } +bool JvmtiExport::has_early_vmstart_env() { + JvmtiEnvIterator it; + for (JvmtiEnv* env = it.first(); env != nullptr; env = it.next(env)) { + if (env->early_vmstart_env()) { + return true; + } + } + return false; +} + bool JvmtiExport::_should_post_class_file_load_hook = false; // This flag is read by C2 during VM internal objects allocation diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp index e0fb84f2c03..324e437411a 100644 --- a/src/hotspot/share/prims/jvmtiExport.hpp +++ b/src/hotspot/share/prims/jvmtiExport.hpp @@ -371,6 +371,7 @@ class JvmtiExport : public AllStatic { } static bool is_early_phase() NOT_JVMTI_RETURN_(false); static bool has_early_class_hook_env() NOT_JVMTI_RETURN_(false); + static bool has_early_vmstart_env() NOT_JVMTI_RETURN_(false); // Return true if the class was modified by the hook. static bool post_class_file_load_hook(Symbol* h_name, Handle class_loader, Handle h_protection_domain, diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 344ef7802a2..a982ac97c47 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -1362,8 +1362,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() { ClassFileStream st((u1*)_class_defs[i].class_bytes, _class_defs[i].class_byte_count, - "__VM_RedefineClasses__", - ClassFileStream::verify); + "__VM_RedefineClasses__"); // Set redefined class handle in JvmtiThreadState class. // This redefined class is sent to agent event handler for class file diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index d4b5e293c09..a8607bb2efd 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -35,7 +35,6 @@ #include "classfile/classPrinter.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/modules.hpp" -#include "classfile/protectionDomainCache.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" @@ -2536,10 +2535,6 @@ WB_ENTRY(jlong, WB_ResolvedMethodItemsCount(JNIEnv* env, jobject o)) return (jlong) ResolvedMethodTable::items_count(); WB_END -WB_ENTRY(jint, WB_ProtectionDomainRemovedCount(JNIEnv* env, jobject o)) - return (jint) ProtectionDomainCacheTable::removed_entries_count(); -WB_END - WB_ENTRY(jint, WB_GetKlassMetadataSize(JNIEnv* env, jobject wb, jclass mirror)) Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(mirror)); // Return size in bytes. @@ -2966,7 +2961,6 @@ static JNINativeMethod methods[] = { {CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo }, {CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache }, {CC"resolvedMethodItemsCount", CC"()J", (void*)&WB_ResolvedMethodItemsCount }, - {CC"protectionDomainRemovedCount", CC"()I", (void*)&WB_ProtectionDomainRemovedCount }, {CC"getKlassMetadataSize", CC"(Ljava/lang/Class;)I",(void*)&WB_GetKlassMetadataSize}, {CC"createMetaspaceTestContext", CC"(JJ)J", (void*)&WB_CreateMetaspaceTestContext}, diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index e9262a48086..0b16a634489 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -46,6 +46,7 @@ #include "nmt/nmtCommon.hpp" #include "oops/compressedKlass.hpp" #include "oops/instanceKlass.hpp" +#include "oops/objLayout.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiAgentList.hpp" #include "prims/jvmtiExport.hpp" @@ -2533,19 +2534,23 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m // -Xshare:dump } else if (match_option(option, "-Xshare:dump")) { CDSConfig::enable_dumping_static_archive(); + CDSConfig::set_old_cds_flags_used(); // -Xshare:on } else if (match_option(option, "-Xshare:on")) { UseSharedSpaces = true; RequireSharedSpaces = true; + CDSConfig::set_old_cds_flags_used(); // -Xshare:auto || -XX:ArchiveClassesAtExit= } else if (match_option(option, "-Xshare:auto")) { UseSharedSpaces = true; RequireSharedSpaces = false; xshare_auto_cmd_line = true; + CDSConfig::set_old_cds_flags_used(); // -Xshare:off } else if (match_option(option, "-Xshare:off")) { UseSharedSpaces = false; RequireSharedSpaces = false; + CDSConfig::set_old_cds_flags_used(); // -Xverify } else if (match_option(option, "-Xverify", &tail)) { if (strcmp(tail, ":all") == 0 || strcmp(tail, "") == 0) { diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index be4fef5255c..18beb10f0b4 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -1524,7 +1524,6 @@ stackChunkOop Freeze::allocate_chunk(size_t stack_size, int argsize_md) assert(chunk->flags() == 0, ""); assert(chunk->is_gc_mode() == false, ""); assert(chunk->lockstack_size() == 0, ""); - assert(chunk->object_waiter() == nullptr, ""); // fields are uninitialized chunk->set_parent_access(_cont.last_nonempty_chunk()); @@ -2214,11 +2213,10 @@ NOINLINE intptr_t* Thaw::thaw_slow(stackChunkOop chunk, Continuation::t _preempted_case = chunk->preempted(); if (_preempted_case) { - if (chunk->object_waiter() != nullptr) { + ObjectWaiter* waiter = java_lang_VirtualThread::objectWaiter(_thread->vthread()); + if (waiter != nullptr) { // Mounted again after preemption. Resume the pending monitor operation, // which will be either a monitorenter or Object.wait() call. - assert(chunk->current_pending_monitor() != nullptr || chunk->current_waiting_monitor() != nullptr, ""); - ObjectWaiter* waiter = chunk->object_waiter(); ObjectMonitor* mon = waiter->monitor(); preempt_kind = waiter->is_wait() ? Continuation::freeze_on_wait : Continuation::freeze_on_monitorenter; diff --git a/src/hotspot/share/runtime/continuationJavaClasses.cpp b/src/hotspot/share/runtime/continuationJavaClasses.cpp index 5ab96f9cf4f..e76a151f481 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.cpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.cpp @@ -88,7 +88,6 @@ int jdk_internal_vm_StackChunk::_bottom_offset; int jdk_internal_vm_StackChunk::_flags_offset; int jdk_internal_vm_StackChunk::_maxThawingSize_offset; int jdk_internal_vm_StackChunk::_lockStackSize_offset; -int jdk_internal_vm_StackChunk::_objectWaiter_offset; int jdk_internal_vm_StackChunk::_cont_offset; #define STACKCHUNK_FIELDS_DO(macro) \ diff --git a/src/hotspot/share/runtime/continuationJavaClasses.hpp b/src/hotspot/share/runtime/continuationJavaClasses.hpp index d100ef17871..f9cd53ff9f0 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.hpp @@ -76,7 +76,6 @@ class jdk_internal_vm_Continuation: AllStatic { macro(jdk_internal_vm_StackChunk, pc, intptr_signature, false) \ macro(jdk_internal_vm_StackChunk, maxThawingSize, int_signature, false) \ macro(jdk_internal_vm_StackChunk, lockStackSize, byte_signature, false) \ - macro(jdk_internal_vm_StackChunk, objectWaiter, intptr_signature, false) \ class jdk_internal_vm_StackChunk: AllStatic { friend class JavaClasses; @@ -89,7 +88,6 @@ class jdk_internal_vm_StackChunk: AllStatic { static int _flags_offset; static int _maxThawingSize_offset; static int _lockStackSize_offset; - static int _objectWaiter_offset; static int _cont_offset; @@ -131,9 +129,6 @@ class jdk_internal_vm_StackChunk: AllStatic { static inline uint8_t lockStackSize(oop chunk); static inline void set_lockStackSize(oop chunk, uint8_t value); - static inline address objectWaiter(oop chunk); - static inline void set_objectWaiter(oop chunk, address mon); - // cont oop's processing is essential for the chunk's GC protocol static inline oop cont(oop chunk); template diff --git a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp index b4400c59c68..0e8bf2d6563 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp @@ -194,12 +194,4 @@ inline void jdk_internal_vm_StackChunk::set_lockStackSize(oop chunk, uint8_t val Atomic::store(chunk->field_addr(_lockStackSize_offset), value); } -inline address jdk_internal_vm_StackChunk::objectWaiter(oop chunk) { - return chunk->address_field(_objectWaiter_offset); -} - -inline void jdk_internal_vm_StackChunk::set_objectWaiter(oop chunk, address value) { - chunk->address_field_put(_objectWaiter_offset, value); -} - #endif // SHARE_RUNTIME_CONTINUATIONJAVACLASSES_INLINE_HPP diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 9992d42622f..10fd83750d4 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1065,7 +1065,7 @@ class BoxCacheBase : public CHeapObj { static InstanceKlass* find_cache_klass(Thread* thread, Symbol* klass_name) { ResourceMark rm(thread); char* klass_name_str = klass_name->as_C_string(); - InstanceKlass* ik = SystemDictionary::find_instance_klass(thread, klass_name, Handle(), Handle()); + InstanceKlass* ik = SystemDictionary::find_instance_klass(thread, klass_name, Handle()); guarantee(ik != nullptr, "%s must be loaded", klass_name_str); if (!ik->is_in_error_state()) { guarantee(ik->is_initialized(), "%s must be initialized", klass_name_str); diff --git a/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp b/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp index 8d9cbe33d12..843ee24c909 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -310,6 +310,17 @@ JVMFlag::Error JVMFlagAccess::set_impl(JVMFlag* flag, void* value, JVMFlagOrigin JVMFlag::Error JVMFlagAccess::set_ccstr(JVMFlag* flag, ccstr* value, JVMFlagOrigin origin) { if (flag == nullptr) return JVMFlag::INVALID_FLAG; if (!flag->is_ccstr()) return JVMFlag::WRONG_FORMAT; + const JVMTypedFlagLimit* constraint = (const JVMTypedFlagLimit*)JVMFlagLimit::get_constraint(flag); + if (constraint != nullptr && constraint->phase() <= JVMFlagLimit::validating_phase()) { + bool verbose = JVMFlagLimit::verbose_checks_needed() | (origin == JVMFlagOrigin::ERGONOMIC); + JVMFlag::Error err = ((JVMFlagConstraintFunc_ccstr)constraint->constraint_func())(*value, verbose); + if (err != JVMFlag::SUCCESS) { + if (origin == JVMFlagOrigin::ERGONOMIC) { + fatal("FLAG_SET_ERGO cannot be used to set an invalid value for %s", flag->name()); + } + return err; + } + } ccstr old_value = flag->get_ccstr(); trace_flag_changed(flag, old_value, *value, origin); char* new_value = nullptr; diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp index 1c02e929113..354e828372f 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,21 @@ #include "runtime/task.hpp" #include "utilities/powerOfTwo.hpp" +JVMFlag::Error AOTModeConstraintFunc(ccstr value, bool verbose) { + if (strcmp(value, "off") != 0 && + strcmp(value, "record") != 0 && + strcmp(value, "create") != 0 && + strcmp(value, "auto") != 0 && + strcmp(value, "on") != 0) { + JVMFlag::printError(verbose, + "Unrecognized value %s for AOTMode. Must be one of the following: " + "off, record, create, auto, on\n", + value); + return JVMFlag::VIOLATES_CONSTRAINT; + } + + return JVMFlag::SUCCESS; +} JVMFlag::Error ObjectAlignmentInBytesConstraintFunc(int value, bool verbose) { if (!is_power_of_2(value)) { JVMFlag::printError(verbose, diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp index cbe28456b8a..20d420a8e7e 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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,6 +34,7 @@ */ #define RUNTIME_CONSTRAINTS(f) \ + f(ccstr, AOTModeConstraintFunc) \ f(int, ObjectAlignmentInBytesConstraintFunc) \ f(int, ContendedPaddingWidthConstraintFunc) \ f(int, PerfDataSamplingIntervalFunc) \ diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 70b537bf2d7..11c13fe3c9e 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -697,9 +697,6 @@ const int ObjectAlignmentInBytes = 8; "Allow parallel defineClass requests for class loaders " \ "registering as parallel capable") \ \ - product_pd(bool, DontYieldALot, \ - "(Deprecated) Throw away obvious excess yield calls") \ - \ product(bool, DisablePrimordialThreadGuardPages, false, EXPERIMENTAL, \ "Disable the use of stack guard pages if the JVM is loaded " \ "on the primordial process thread") \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index 23df464aba8..d2338cd74d0 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -359,7 +359,11 @@ void print_statistics() { ThreadsSMRSupport::log_statistics(); - ClassLoader::print_counters(tty); + if (log_is_enabled(Info, perf, class, link)) { + LogStreamHandle(Info, perf, class, link) log; + log.print_cr("At VM exit:"); + ClassLoader::print_counters(&log); + } } // Note: before_exit() can be executed only once, if more than one threads @@ -437,6 +441,11 @@ void before_exit(JavaThread* thread, bool halt) { #if INCLUDE_CDS ClassListWriter::write_resolved_constants(); + + // Initiate Archive Workers shutdown. These workers are likely already + // shut down, but we need to make sure they really are. Otherwise, workers + // would fail hard on broken semaphores. + ArchiveWorkers::workers()->shutdown(); #endif // Hang forever on exit if we're reporting an error. diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 7d1998ca849..82473489f68 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -1134,11 +1134,9 @@ bool ObjectMonitor::VThreadMonitorEnter(JavaThread* current, ObjectWaiter* waite java_lang_VirtualThread::set_state(vthread, java_lang_VirtualThread::BLOCKING); // We didn't succeed in acquiring the monitor so increment _contentions and - // save ObjectWaiter* in the chunk since we will need it when resuming execution. + // save ObjectWaiter* in the vthread since we will need it when resuming execution. add_to_contentions(1); - oop cont = java_lang_VirtualThread::continuation(vthread); - stackChunkOop chunk = jdk_internal_vm_Continuation::tail(cont); - chunk->set_object_waiter(node); + java_lang_VirtualThread::set_objectWaiter(vthread, node); return false; } @@ -1202,11 +1200,8 @@ void ObjectMonitor::VThreadEpilog(JavaThread* current, ObjectWaiter* node) { UnlinkAfterAcquire(current, node); delete node; - // Remove the ObjectWaiter* from the stackChunk. - oop vthread = current->vthread(); - oop cont = java_lang_VirtualThread::continuation(vthread); - stackChunkOop chunk = jdk_internal_vm_Continuation::tail(cont); - chunk->set_object_waiter(nullptr); + // Clear the ObjectWaiter* from the vthread. + java_lang_VirtualThread::set_objectWaiter(current->vthread(), nullptr); if (JvmtiExport::should_post_monitor_contended_entered()) { // We are going to call thaw again after this and finish the VMTS @@ -2030,10 +2025,8 @@ void ObjectMonitor::VThreadWait(JavaThread* current, jlong millis) { java_lang_VirtualThread::set_state(vthread, millis == 0 ? java_lang_VirtualThread::WAITING : java_lang_VirtualThread::TIMED_WAITING); java_lang_VirtualThread::set_timeout(vthread, millis); - // Save the ObjectWaiter* in the chunk since we will need it when resuming execution. - oop cont = java_lang_VirtualThread::continuation(vthread); - stackChunkOop chunk = jdk_internal_vm_Continuation::tail(cont); - chunk->set_object_waiter(node); + // Save the ObjectWaiter* in the vthread since we will need it when resuming execution. + java_lang_VirtualThread::set_objectWaiter(vthread, node); } bool ObjectMonitor::VThreadWaitReenter(JavaThread* current, ObjectWaiter* node, ContinuationWrapper& cont) { @@ -2079,8 +2072,8 @@ bool ObjectMonitor::VThreadWaitReenter(JavaThread* current, ObjectWaiter* node, } delete node; - stackChunkOop chunk = cont.tail(); - chunk->set_object_waiter(nullptr); + // Clear the ObjectWaiter* from the vthread. + java_lang_VirtualThread::set_objectWaiter(current->vthread(), nullptr); return true; } } else { diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 2f665df5bba..54771f622e9 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -1042,8 +1042,6 @@ class os: AllStatic { // debugging support (mostly used by debug.cpp but also fatal error handler) static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address - static bool dont_yield(); // when true, JVM_Yield() is nop - // Thread priority helpers (implemented in OS-specific part) static OSReturn set_native_priority(Thread* thread, int native_prio); static OSReturn get_native_priority(const Thread* const thread, int* priority_ptr); diff --git a/src/hotspot/share/runtime/serviceThread.cpp b/src/hotspot/share/runtime/serviceThread.cpp index f5653ccd5f4..f4bffc72ef3 100644 --- a/src/hotspot/share/runtime/serviceThread.cpp +++ b/src/hotspot/share/runtime/serviceThread.cpp @@ -25,11 +25,8 @@ #include "precompiled.hpp" #include "classfile/classLoaderDataGraph.inline.hpp" #include "classfile/javaClasses.hpp" -#include "classfile/protectionDomainCache.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" -#include "classfile/systemDictionary.hpp" -#include "classfile/vmClasses.hpp" #include "gc/shared/oopStorage.hpp" #include "gc/shared/oopStorageSet.hpp" #include "interpreter/oopMapCache.hpp" @@ -40,15 +37,10 @@ #include "prims/resolvedMethodTable.hpp" #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" -#include "runtime/java.hpp" -#include "runtime/javaCalls.hpp" -#include "runtime/jniHandles.hpp" #include "runtime/lightweightSynchronizer.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" #include "runtime/serviceThread.hpp" -#include "services/diagnosticArgument.hpp" -#include "services/diagnosticFramework.hpp" #include "services/finalizerService.hpp" #include "services/gcNotifier.hpp" #include "services/lowMemoryDetector.hpp" @@ -88,7 +80,6 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { bool finalizerservice_work = false; bool resolved_method_table_work = false; bool thread_id_table_work = false; - bool protection_domain_table_work = false; bool oopstorage_work = false; JvmtiDeferredEvent jvmti_event; bool oop_handles_to_release = false; @@ -118,7 +109,6 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { (finalizerservice_work = FinalizerService::has_work()) | (resolved_method_table_work = ResolvedMethodTable::has_work()) | (thread_id_table_work = ThreadIdTable::has_work()) | - (protection_domain_table_work = ProtectionDomainCacheTable::has_work()) | (oopstorage_work = OopStorage::has_cleanup_work_and_reset()) | (oop_handles_to_release = JavaThread::has_oop_handles_to_release()) | (cldg_cleanup_work = ClassLoaderDataGraph::should_clean_metaspaces_and_reset()) | @@ -163,10 +153,6 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { ThreadIdTable::do_concurrent_work(jt); } - if (protection_domain_table_work) { - ProtectionDomainCacheTable::unlink(); - } - if (oopstorage_work) { cleanup_oopstorages(); } diff --git a/src/hotspot/share/runtime/signature.cpp b/src/hotspot/share/runtime/signature.cpp index 081bdd2e0d3..2dfb8d81037 100644 --- a/src/hotspot/share/runtime/signature.cpp +++ b/src/hotspot/share/runtime/signature.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -501,8 +501,7 @@ Symbol* SignatureStream::find_symbol() { return name; } -Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain, - FailureMode failure_mode, TRAPS) { +Klass* SignatureStream::as_klass(Handle class_loader, FailureMode failure_mode, TRAPS) { if (!is_reference()) { return nullptr; } @@ -511,11 +510,11 @@ Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain, if (failure_mode == ReturnNull) { // Note: SD::resolve_or_null returns null for most failure modes, // but not all. Circularity errors, invalid PDs, etc., throw. - k = SystemDictionary::resolve_or_null(name, class_loader, protection_domain, CHECK_NULL); + k = SystemDictionary::resolve_or_null(name, class_loader, CHECK_NULL); } else if (failure_mode == CachedOrNull) { NoSafepointVerifier nsv; // no loading, now, we mean it! assert(!HAS_PENDING_EXCEPTION, ""); - k = SystemDictionary::find_instance_klass(THREAD, name, class_loader, protection_domain); + k = SystemDictionary::find_instance_klass(THREAD, name, class_loader); // SD::find does not trigger loading, so there should be no throws // Still, bad things can happen, so we CHECK_NULL and ask callers // to do likewise. @@ -525,18 +524,17 @@ Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain, // The test here allows for an additional mode CNFException // if callers need to request the reflective error instead. bool throw_error = (failure_mode == NCDFError); - k = SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, CHECK_NULL); + k = SystemDictionary::resolve_or_fail(name, class_loader, throw_error, CHECK_NULL); } return k; } -oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain, - FailureMode failure_mode, TRAPS) { +oop SignatureStream::as_java_mirror(Handle class_loader, FailureMode failure_mode, TRAPS) { if (!is_reference()) { return Universe::java_mirror(type()); } - Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL); + Klass* klass = as_klass(class_loader, failure_mode, CHECK_NULL); if (klass == nullptr) { return nullptr; } @@ -551,10 +549,8 @@ void SignatureStream::skip_to_return_type() { ResolvingSignatureStream::ResolvingSignatureStream(Symbol* signature, Handle class_loader, - Handle protection_domain, bool is_method) - : SignatureStream(signature, is_method), - _class_loader(class_loader), _protection_domain(protection_domain) + : SignatureStream(signature, is_method), _class_loader(class_loader) { initialize_load_origin(nullptr); } @@ -576,7 +572,6 @@ void ResolvingSignatureStream::cache_handles() { assert(_load_origin != nullptr, ""); JavaThread* current = JavaThread::current(); _class_loader = Handle(current, _load_origin->class_loader()); - _protection_domain = Handle(current, _load_origin->protection_domain()); } #ifdef ASSERT diff --git a/src/hotspot/share/runtime/signature.hpp b/src/hotspot/share/runtime/signature.hpp index 25de9c0a1f0..ef18b0f03d3 100644 --- a/src/hotspot/share/runtime/signature.hpp +++ b/src/hotspot/share/runtime/signature.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -562,8 +562,8 @@ class SignatureStream : public StackObj { // free-standing lookups (bring your own CL/PD pair) enum FailureMode { ReturnNull, NCDFError, CachedOrNull }; - Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS); - oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS); + Klass* as_klass(Handle class_loader, FailureMode failure_mode, TRAPS); + oop as_java_mirror(Handle class_loader, FailureMode failure_mode, TRAPS); }; // Specialized SignatureStream: used for invoking SystemDictionary to either find @@ -573,7 +573,6 @@ class ResolvingSignatureStream : public SignatureStream { Klass* _load_origin; bool _handles_cached; Handle _class_loader; // cached when needed - Handle _protection_domain; // cached when needed void initialize_load_origin(Klass* load_origin) { _load_origin = load_origin; @@ -589,20 +588,18 @@ class ResolvingSignatureStream : public SignatureStream { public: ResolvingSignatureStream(Symbol* signature, Klass* load_origin, bool is_method = true); - ResolvingSignatureStream(Symbol* signature, Handle class_loader, Handle protection_domain, bool is_method = true); + ResolvingSignatureStream(Symbol* signature, Handle class_loader, bool is_method = true); ResolvingSignatureStream(const Method* method); Klass* as_klass(FailureMode failure_mode, TRAPS) { need_handles(); - return SignatureStream::as_klass(_class_loader, _protection_domain, - failure_mode, THREAD); + return SignatureStream::as_klass(_class_loader, failure_mode, THREAD); } oop as_java_mirror(FailureMode failure_mode, TRAPS) { if (is_reference()) { need_handles(); } - return SignatureStream::as_java_mirror(_class_loader, _protection_domain, - failure_mode, THREAD); + return SignatureStream::as_java_mirror(_class_loader, failure_mode, THREAD); } }; diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 29386a0c368..73f2e87f5c7 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -24,12 +24,15 @@ */ #include "precompiled.hpp" +#include "cds/aotLinkedClassBulkLoader.hpp" #include "cds/cds_globals.hpp" #include "cds/cdsConfig.hpp" +#include "cds/heapShared.hpp" #include "cds/metaspaceShared.hpp" #include "classfile/classLoader.hpp" #include "classfile/javaClasses.hpp" #include "classfile/javaThreadStatus.hpp" +#include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" @@ -350,12 +353,15 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { initialize_class(vmSymbols::java_lang_System(), CHECK); // The VM creates & returns objects of this class. Make sure it's initialized. initialize_class(vmSymbols::java_lang_Class(), CHECK); + initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK); Handle thread_group = create_initial_thread_group(CHECK); Universe::set_main_thread_group(thread_group()); initialize_class(vmSymbols::java_lang_Thread(), CHECK); create_initial_thread(thread_group, main_thread, CHECK); + HeapShared::init_box_classes(CHECK); + // The VM creates objects of this class. initialize_class(vmSymbols::java_lang_Module(), CHECK); @@ -379,7 +385,7 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { // Some values are actually configure-time constants but some can be set via the jlink tool and // so must be read dynamically. We treat them all the same. InstanceKlass* ik = SystemDictionary::find_instance_klass(THREAD, vmSymbols::java_lang_VersionProps(), - Handle(), Handle()); + Handle()); { ResourceMark rm(main_thread); JDK_Version::set_java_version(get_java_version_info(ik, vmSymbols::java_version_name())); @@ -403,6 +409,7 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK); initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK); initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK); + initialize_class(vmSymbols::java_lang_InternalError(), CHECK); } void Threads::initialize_jsr292_core_classes(TRAPS) { @@ -412,6 +419,10 @@ void Threads::initialize_jsr292_core_classes(TRAPS) { initialize_class(vmSymbols::java_lang_invoke_ResolvedMethodName(), CHECK); initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK); initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK); + + if (UseSharedSpaces) { + HeapShared::initialize_java_lang_invoke(CHECK); + } } jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { @@ -486,6 +497,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { // Timing (must come after argument parsing) TraceTime timer("Create VM", TRACETIME_LOG(Info, startuptime)); + // Initialize object layout after parsing the args + ObjLayout::initialize(); + // Initialize the os module after parsing the args jint os_init_2_result = os::init_2(); if (os_init_2_result != JNI_OK) return os_init_2_result; @@ -737,6 +751,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { } #endif + if (CDSConfig::is_using_aot_linked_classes()) { + AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR); + SystemDictionary::restore_archived_method_handle_intrinsics(); + } + // Start string deduplication thread if requested. if (StringDedup::is_enabled()) { StringDedup::start(); @@ -752,6 +771,13 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { // loaded until phase 2 completes call_initPhase2(CHECK_JNI_ERR); + if (CDSConfig::is_using_aot_linked_classes()) { + AOTLinkedClassBulkLoader::load_non_javabase_classes(THREAD); + } +#ifndef PRODUCT + HeapShared::initialize_test_class_from_archive(THREAD); +#endif + JFR_ONLY(Jfr::on_create_vm_2();) // Always call even when there are not JVMTI environments yet, since environments diff --git a/src/hotspot/share/runtime/vframe.cpp b/src/hotspot/share/runtime/vframe.cpp index 41a46c86a70..fbf82c69673 100644 --- a/src/hotspot/share/runtime/vframe.cpp +++ b/src/hotspot/share/runtime/vframe.cpp @@ -532,8 +532,7 @@ vframeStream::vframeStream(oop continuation, Handle continuation_scope) // Step back n frames, skip any pseudo frames in between. -// This function is used in Class.forName, Class.newInstance, Method.Invoke, -// AccessController.doPrivileged. +// This function is used in Class.forName, Class.newInstance, and Method.Invoke. void vframeStreamCommon::security_get_caller_frame(int depth) { assert(depth >= 0, "invalid depth: %d", depth); for (int n = 0; !at_end(); security_next()) { diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index bc941534242..a1c1551ae09 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1930,7 +1930,6 @@ declare_toplevel_type(jbyte*) \ declare_toplevel_type(jbyte**) \ declare_toplevel_type(jint*) \ - declare_toplevel_type(jniIdMapBase*) \ declare_unsigned_integer_type(juint) \ declare_unsigned_integer_type(julong) \ declare_toplevel_type(JNIHandleBlock*) \ diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index ac711520065..b807a42661c 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -695,7 +695,7 @@ void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) { loadAgentModule(CHECK); Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK); + Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK); JavaValue result(T_VOID); @@ -768,7 +768,7 @@ void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) { loadAgentModule(CHECK); Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK); + Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK); JavaValue result(T_VOID); JavaCalls::call_static(&result, k, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK); @@ -785,7 +785,7 @@ void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) { loadAgentModule(CHECK); Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK); + Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK); JavaValue result(T_VOID); JavaCalls::call_static(&result, k, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK); @@ -806,7 +806,7 @@ void JMXStatusDCmd::execute(DCmdSource source, TRAPS) { loadAgentModule(CHECK); Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK); + Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, k, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK); @@ -884,21 +884,17 @@ void CodeHeapAnalyticsDCmd::execute(DCmdSource source, TRAPS) { EventLogDCmd::EventLogDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _log("log", "Name of log to be printed. If omitted, all logs are printed.", "STRING", false, nullptr), - _max("max", "Maximum number of events to be printed (newest first). If omitted, all events are printed.", "STRING", false, nullptr) + _max("max", "Maximum number of events to be printed (newest first). If omitted or zero, all events are printed.", "INT", false, "0") { _dcmdparser.add_dcmd_option(&_log); _dcmdparser.add_dcmd_option(&_max); } void EventLogDCmd::execute(DCmdSource source, TRAPS) { - const char* max_value = _max.value(); - int max = -1; - if (max_value != nullptr) { - char* endptr = nullptr; - if (!parse_integer(max_value, &max)) { - output()->print_cr("Invalid max option: \"%s\".", max_value); - return; - } + int max = (int)_max.value(); + if (max < 0) { + output()->print_cr("Invalid max option: \"%d\".", max); + return; } const char* log_name = _log.value(); if (log_name != nullptr) { diff --git a/src/hotspot/share/services/diagnosticCommand.hpp b/src/hotspot/share/services/diagnosticCommand.hpp index c8e26504ece..92e5849cbcd 100644 --- a/src/hotspot/share/services/diagnosticCommand.hpp +++ b/src/hotspot/share/services/diagnosticCommand.hpp @@ -889,7 +889,7 @@ class ClassesDCmd : public DCmdWithParser { class EventLogDCmd : public DCmdWithParser { protected: DCmdArgument _log; - DCmdArgument _max; + DCmdArgument _max; public: static int num_arguments() { return 2; } EventLogDCmd(outputStream* output, bool heap); diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index ac7e1daf397..7729fb08808 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -160,7 +160,6 @@ void Management::initialize(TRAPS) { Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); Klass* k = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_agent_Agent(), loader, - Handle(), THREAD); if (k == nullptr) { vm_exit_during_initialization("Management agent initialization failure: " diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp index 10405a06048..0f87f76a2e8 100644 --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -188,30 +188,30 @@ void Exceptions::_throw(JavaThread* thread, const char* file, int line, Handle h void Exceptions::_throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, - Handle h_loader, Handle h_protection_domain) { + Handle h_loader) { // Check for special boot-strapping/compiler-thread handling if (special_exception(thread, file, line, Handle(), name, message)) return; // Create and throw exception Handle h_cause(thread, nullptr); - Handle h_exception = new_exception(thread, name, message, h_cause, h_loader, h_protection_domain); + Handle h_exception = new_exception(thread, name, message, h_cause, h_loader); _throw(thread, file, line, h_exception, message); } void Exceptions::_throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause, - Handle h_loader, Handle h_protection_domain) { + Handle h_loader) { // Check for special boot-strapping/compiler-thread handling if (special_exception(thread, file, line, Handle(), name, message)) return; // Create and throw exception and init cause - Handle h_exception = new_exception(thread, name, message, h_cause, h_loader, h_protection_domain); + Handle h_exception = new_exception(thread, name, message, h_cause, h_loader); _throw(thread, file, line, h_exception, message); } void Exceptions::_throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause, - Handle h_loader, Handle h_protection_domain) { + Handle h_loader) { // Check for special boot-strapping/compiler-thread handling if (special_exception(thread, file, line, Handle(), name)) return; // Create and throw exception - Handle h_exception = new_exception(thread, name, h_cause, h_loader, h_protection_domain); + Handle h_exception = new_exception(thread, name, h_cause, h_loader); _throw(thread, file, line, h_exception, nullptr); } @@ -229,13 +229,13 @@ void Exceptions::_throw_args(JavaThread* thread, const char* file, int line, Sym // Methods for default parameters. // NOTE: These must be here (and not in the header file) because of include circularities. void Exceptions::_throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause) { - _throw_msg_cause(thread, file, line, name, message, h_cause, Handle(thread, nullptr), Handle(thread, nullptr)); + _throw_msg_cause(thread, file, line, name, message, h_cause, Handle()); } void Exceptions::_throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message) { - _throw_msg(thread, file, line, name, message, Handle(thread, nullptr), Handle(thread, nullptr)); + _throw_msg(thread, file, line, name, message, Handle()); } void Exceptions::_throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause) { - _throw_cause(thread, file, line, name, h_cause, Handle(thread, nullptr), Handle(thread, nullptr)); + _throw_cause(thread, file, line, name, h_cause, Handle()); } @@ -297,7 +297,7 @@ void Exceptions::fthrow(JavaThread* thread, const char* file, int line, Symbol* // and returns a Handle Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, Symbol* signature, JavaCallArguments *args, - Handle h_loader, Handle h_protection_domain) { + Handle h_loader) { assert(Universe::is_fully_initialized(), "cannot be called during initialization"); assert(!thread->has_pending_exception(), "already has exception"); @@ -305,7 +305,7 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, Handle h_exception; // Resolve exception klass, and check for pending exception below. - Klass* klass = SystemDictionary::resolve_or_fail(name, h_loader, h_protection_domain, true, thread); + Klass* klass = SystemDictionary::resolve_or_fail(name, h_loader, true, thread); if (!thread->has_pending_exception()) { assert(klass != nullptr, "klass must exist"); @@ -329,8 +329,8 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, Symbol* signature, JavaCallArguments *args, Handle h_cause, - Handle h_loader, Handle h_protection_domain) { - Handle h_exception = new_exception(thread, name, signature, args, h_loader, h_protection_domain); + Handle h_loader) { + Handle h_exception = new_exception(thread, name, signature, args, h_loader); // Future: object initializer should take a cause argument if (h_cause.not_null()) { @@ -359,7 +359,7 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, // creating a new exception Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, Handle h_cause, - Handle h_loader, Handle h_protection_domain, + Handle h_loader, ExceptionMsgToUtf8Mode to_utf8_safe) { JavaCallArguments args; Symbol* signature = nullptr; @@ -369,14 +369,14 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, signature = vmSymbols::throwable_void_signature(); args.push_oop(h_cause); } - return new_exception(thread, name, signature, &args, h_loader, h_protection_domain); + return new_exception(thread, name, signature, &args, h_loader); } // Convenience method. Calls either the () or (String) method when // creating a new exception Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, const char* message, Handle h_cause, - Handle h_loader, Handle h_protection_domain, + Handle h_loader, ExceptionMsgToUtf8Mode to_utf8_safe) { JavaCallArguments args; Symbol* signature = nullptr; @@ -413,11 +413,10 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, args.push_oop(msg); signature = vmSymbols::string_void_signature(); } - return new_exception(thread, name, signature, &args, h_cause, h_loader, h_protection_domain); + return new_exception(thread, name, signature, &args, h_cause, h_loader); } -// Another convenience method that creates handles for null class loaders and -// protection domains and null causes. +// Another convenience method that creates handles for null class loaders and null causes. // If the last parameter 'to_utf8_mode' is safe_to_utf8, // it means we can safely ignore the encoding scheme of the message string and // convert it directly to a java UTF8 string. Otherwise, we need to take the @@ -428,11 +427,10 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name, const char* message, ExceptionMsgToUtf8Mode to_utf8_safe) { - Handle h_loader(thread, nullptr); - Handle h_prot(thread, nullptr); - Handle h_cause(thread, nullptr); + Handle h_loader; + Handle h_cause; return Exceptions::new_exception(thread, name, message, h_cause, h_loader, - h_prot, to_utf8_safe); + to_utf8_safe); } // invokedynamic uses wrap_dynamic_exception for: diff --git a/src/hotspot/share/utilities/exceptions.hpp b/src/hotspot/share/utilities/exceptions.hpp index 33eba68d6d9..0dca7971ef9 100644 --- a/src/hotspot/share/utilities/exceptions.hpp +++ b/src/hotspot/share/utilities/exceptions.hpp @@ -128,15 +128,15 @@ class Exceptions { static void _throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message); static void _throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, - Handle loader, Handle protection_domain); + Handle loader); static void _throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause); static void _throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause, - Handle h_loader, Handle h_protection_domain); + Handle h_loader); static void _throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause); static void _throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause, - Handle h_loader, Handle h_protection_domain); + Handle h_loader); static void _throw_args(JavaThread* thread, const char* file, int line, Symbol* name, Symbol* signature, @@ -150,21 +150,21 @@ class Exceptions { // Create and initialize a new exception static Handle new_exception(JavaThread* thread, Symbol* name, Symbol* signature, JavaCallArguments* args, - Handle loader, Handle protection_domain); + Handle loader); static Handle new_exception(JavaThread* thread, Symbol* name, Symbol* signature, JavaCallArguments* args, Handle cause, - Handle loader, Handle protection_domain); + Handle loader); static Handle new_exception(JavaThread* thread, Symbol* name, Handle cause, - Handle loader, Handle protection_domain, + Handle loader, ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); static Handle new_exception(JavaThread* thread, Symbol* name, const char* message, Handle cause, - Handle loader, Handle protection_domain, + Handle loader, ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); static Handle new_exception(JavaThread* thread, Symbol* name, @@ -268,8 +268,8 @@ class Exceptions { #define THROW_CAUSE(name, cause) \ { Exceptions::_throw_cause(THREAD_AND_LOCATION, name, cause); return; } -#define THROW_MSG_LOADER(name, message, loader, protection_domain) \ - { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader, protection_domain); return; } +#define THROW_MSG_LOADER(name, message, loader) \ + { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader); return; } #define THROW_ARG(name, signature, args) \ { Exceptions::_throw_args(THREAD_AND_LOCATION, name, signature, args); return; } @@ -286,8 +286,8 @@ class Exceptions { #define THROW_MSG_(name, message, result) \ { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message); return result; } -#define THROW_MSG_LOADER_(name, message, loader, protection_domain, result) \ - { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader, protection_domain); return result; } +#define THROW_MSG_LOADER_(name, message, loader, result) \ + { Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader); return result; } #define THROW_ARG_(name, signature, args, result) \ { Exceptions::_throw_args(THREAD_AND_LOCATION, name, signature, args); return result; } diff --git a/src/hotspot/share/utilities/powerOfTwo.hpp b/src/hotspot/share/utilities/powerOfTwo.hpp index 786977a347f..6c1e413f403 100644 --- a/src/hotspot/share/utilities/powerOfTwo.hpp +++ b/src/hotspot/share/utilities/powerOfTwo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -122,10 +122,9 @@ inline T next_power_of_2(T value) { // Find log2 value greater than this input template ::value)> -inline T ceil_log2(T value) { - T ret; - for (ret = 1; ((T)1 << ret) < value; ++ret); - return ret; +inline int ceil_log2(T value) { + assert(value > 0, "Invalid value"); + return log2i_graceful(value - 1) + 1; } // Return the largest power of two that is a submultiple of the given value. diff --git a/src/java.base/aix/classes/sun/nio/ch/DefaultSelectorProvider.java b/src/java.base/aix/classes/sun/nio/ch/DefaultSelectorProvider.java index 86d3ade19de..9438b67039b 100644 --- a/src/java.base/aix/classes/sun/nio/ch/DefaultSelectorProvider.java +++ b/src/java.base/aix/classes/sun/nio/ch/DefaultSelectorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,12 @@ package sun.nio.ch; -import java.security.AccessController; -import java.security.PrivilegedAction; - /** * Creates this platform's default SelectorProvider */ -@SuppressWarnings("removal") public class DefaultSelectorProvider { - private static final SelectorProviderImpl INSTANCE; - static { - PrivilegedAction pa = PollSelectorProvider::new; - INSTANCE = AccessController.doPrivileged(pa); - } + private static final SelectorProviderImpl INSTANCE = new PollSelectorProvider(); /** * Prevent instantiation. @@ -51,4 +43,4 @@ private DefaultSelectorProvider() { } public static SelectorProviderImpl get() { return INSTANCE; } -} \ No newline at end of file +} diff --git a/src/java.base/linux/classes/sun/nio/ch/DefaultSelectorProvider.java b/src/java.base/linux/classes/sun/nio/ch/DefaultSelectorProvider.java index fa925f54546..36e517f093a 100644 --- a/src/java.base/linux/classes/sun/nio/ch/DefaultSelectorProvider.java +++ b/src/java.base/linux/classes/sun/nio/ch/DefaultSelectorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,12 @@ package sun.nio.ch; -import java.security.AccessController; -import java.security.PrivilegedAction; - /** * Creates this platform's default SelectorProvider */ -@SuppressWarnings("removal") public class DefaultSelectorProvider { - private static final SelectorProviderImpl INSTANCE; - static { - PrivilegedAction pa = EPollSelectorProvider::new; - INSTANCE = AccessController.doPrivileged(pa); - } + private static final SelectorProviderImpl INSTANCE = new EPollSelectorProvider(); /** * Prevent instantiation. diff --git a/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java index 49b24a42b89..4cbd51ab49d 100644 --- a/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -115,8 +115,6 @@ public Map readAttributes(String[] attributes) @Override public DosFileAttributes readAttributes() throws IOException { - file.checkRead(); - int fd = -1; try { fd = file.openForAttributeAccess(followLinks); @@ -249,8 +247,6 @@ private int getDosAttribute(int fd) throws UnixException { * Updates the value of the user.DOSATTRIB extended attribute */ private void updateDosAttribute(int flag, boolean enable) throws IOException { - file.checkWrite(); - int fd = -1; try { fd = file.openForAttributeAccess(followLinks); diff --git a/src/java.base/macosx/classes/sun/nio/ch/DefaultSelectorProvider.java b/src/java.base/macosx/classes/sun/nio/ch/DefaultSelectorProvider.java index a010b1706d4..202d070c493 100644 --- a/src/java.base/macosx/classes/sun/nio/ch/DefaultSelectorProvider.java +++ b/src/java.base/macosx/classes/sun/nio/ch/DefaultSelectorProvider.java @@ -25,20 +25,12 @@ package sun.nio.ch; -import java.security.AccessController; -import java.security.PrivilegedAction; - /** * Creates this platform's default SelectorProvider */ -@SuppressWarnings("removal") public class DefaultSelectorProvider { - private static final SelectorProviderImpl INSTANCE; - static { - PrivilegedAction pa = KQueueSelectorProvider::new; - INSTANCE = AccessController.doPrivileged(pa); - } + private static final SelectorProviderImpl INSTANCE = new KQueueSelectorProvider(); /** * Prevent instantiation. diff --git a/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java b/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java index e071f25f22c..d39131a6de2 100644 --- a/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java +++ b/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,12 +29,15 @@ import java.nio.file.attribute.FileTime; import java.util.concurrent.TimeUnit; import static sun.nio.fs.BsdNativeDispatcher.*; -import static sun.nio.fs.UnixNativeDispatcher.lutimes; +import static sun.nio.fs.UnixConstants.ELOOP; +import static sun.nio.fs.UnixConstants.ENXIO; +import static sun.nio.fs.UnixNativeDispatcher.futimens; +import static sun.nio.fs.UnixNativeDispatcher.utimensat; class BsdFileAttributeViews { // - // Use setattrlist(2) system call which can set creation, modification, - // and access times. + // Use the futimens(2)/utimensat(2) system calls to set the access and + // modification times, and setattrlist(2) to set the creation time. // private static void setTimes(UnixPath path, FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime, @@ -47,34 +50,29 @@ private static void setTimes(UnixPath path, FileTime lastModifiedTime, return; } - // permission check - path.checkWrite(); - - boolean useLutimes = false; + // use a file descriptor if possible to avoid a race due to accessing + // a path more than once as the file at that path could change. + // if path is a symlink, then the open should fail with ELOOP and + // the path will be used instead of the file descriptor. + int fd = -1; try { - useLutimes = !followLinks && - UnixFileAttributes.get(path, false).isSymbolicLink(); + fd = path.openForAttributeAccess(followLinks); } catch (UnixException x) { - x.rethrowAsIOException(path); - } - - int fd = -1; - if (!useLutimes) { - try { - fd = path.openForAttributeAccess(followLinks); - } catch (UnixException x) { + if (!(x.errno() == ENXIO || (x.errno() == ELOOP))) { x.rethrowAsIOException(path); } } try { // not all volumes support setattrlist(2), so set the last - // modified and last access times using futimens(2)/lutimes(3) + // modified and last access times use futimens(2)/utimensat(2) if (lastModifiedTime != null || lastAccessTime != null) { // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { - UnixFileAttributes attrs = UnixFileAttributes.get(fd); + UnixFileAttributes attrs = fd >= 0 ? + UnixFileAttributes.get(fd) : + UnixFileAttributes.get(path, followLinks); if (lastModifiedTime == null) lastModifiedTime = attrs.lastModifiedTime(); if (lastAccessTime == null) @@ -85,20 +83,21 @@ private static void setTimes(UnixPath path, FileTime lastModifiedTime, } // update times - TimeUnit timeUnit = useLutimes ? - TimeUnit.MICROSECONDS : TimeUnit.NANOSECONDS; - long modValue = lastModifiedTime.to(timeUnit); - long accessValue= lastAccessTime.to(timeUnit); + long modValue = lastModifiedTime.to(TimeUnit.NANOSECONDS); + long accessValue= lastAccessTime.to(TimeUnit.NANOSECONDS); boolean retry = false; + int flags = followLinks ? 0 : UnixConstants.AT_SYMLINK_NOFOLLOW; try { - if (useLutimes) - lutimes(path, accessValue, modValue); - else + if (fd >= 0) futimens(fd, accessValue, modValue); + else + utimensat(UnixConstants.AT_FDCWD, path, accessValue, + modValue, flags); } catch (UnixException x) { - // if futimens fails with EINVAL and one/both of the times is - // negative then we adjust the value to the epoch and retry. + // if futimens/utimensat fails with EINVAL and one/both of + // the times is negative, then we adjust the value to the + // epoch and retry. if (x.errno() == UnixConstants.EINVAL && (modValue < 0L || accessValue < 0L)) { retry = true; @@ -110,34 +109,34 @@ private static void setTimes(UnixPath path, FileTime lastModifiedTime, if (modValue < 0L) modValue = 0L; if (accessValue < 0L) accessValue= 0L; try { - if (useLutimes) - lutimes(path, accessValue, modValue); - else + if (fd >= 0) futimens(fd, accessValue, modValue); + else + utimensat(UnixConstants.AT_FDCWD, path, accessValue, + modValue, flags); } catch (UnixException x) { x.rethrowAsIOException(path); } } } - // set the creation time using setattrlist + // set the creation time using setattrlist(2) if (createTime != null) { long createValue = createTime.to(TimeUnit.NANOSECONDS); int commonattr = UnixConstants.ATTR_CMN_CRTIME; try { - if (useLutimes) - setattrlist(path, commonattr, 0L, 0L, createValue, - followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); - else + if (fd >= 0) fsetattrlist(fd, commonattr, 0L, 0L, createValue, - followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); + followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); + else + setattrlist(path, commonattr, 0L, 0L, createValue, + followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); } catch (UnixException x) { x.rethrowAsIOException(path); } } } finally { - if (!useLutimes) - close(fd, e -> null); + close(fd, e -> null); } } diff --git a/src/java.base/macosx/classes/sun/nio/fs/BsdFileSystem.java b/src/java.base/macosx/classes/sun/nio/fs/BsdFileSystem.java index 3b99a456288..69a5d775b0b 100644 --- a/src/java.base/macosx/classes/sun/nio/fs/BsdFileSystem.java +++ b/src/java.base/macosx/classes/sun/nio/fs/BsdFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,13 +28,11 @@ import java.io.IOException; import java.nio.file.FileStore; import java.nio.file.WatchService; -import java.security.AccessController; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Set; import sun.nio.ch.IOStatus; -import sun.security.action.GetPropertyAction; import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixNativeDispatcher.chown; diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java b/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java index fc39b4ed634..3f63dee72d6 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java @@ -245,7 +245,7 @@ protected AlgorithmParameters engineGetParameters() { params.init((new DerValue( DerValue.tag_OctetString, nonceData).toByteArray())); } catch (NoSuchAlgorithmException | IOException exc) { - throw new RuntimeException(exc); + throw new ProviderException(exc); } } @@ -353,7 +353,7 @@ protected void engineInit(int opmode, Key key, break; default: // Should never happen - throw new RuntimeException("ChaCha20 in unsupported mode"); + throw new ProviderException("ChaCha20 in unsupported mode"); } init(opmode, key, newNonce); } @@ -426,7 +426,7 @@ protected void engineInit(int opmode, Key key, } break; default: - throw new RuntimeException("Invalid mode: " + mode); + throw new ProviderException("Invalid mode: " + mode); } // Continue with initialization @@ -730,7 +730,7 @@ protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen) try { engine.doFinal(in, inOfs, inLen, output, 0); } catch (ShortBufferException | KeyException exc) { - throw new RuntimeException(exc); + throw new ProviderException(exc); } finally { // Reset the cipher's state to post-init values. resetStartState(); @@ -767,7 +767,7 @@ protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out, try { bytesUpdated = engine.doFinal(in, inOfs, inLen, out, outOfs); } catch (KeyException ke) { - throw new RuntimeException(ke); + throw new ProviderException(ke); } finally { // Reset the cipher's state to post-init values. resetStartState(); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java b/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java index 5eebf98acc3..e13eec42905 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java @@ -56,14 +56,8 @@ public final class DHKeyAgreement private static class AllowKDF { - private static final boolean VALUE = getValue(); - - @SuppressWarnings("removal") - private static boolean getValue() { - return AccessController.doPrivileged( - (PrivilegedAction) - () -> Boolean.getBoolean("jdk.crypto.KeyAgreement.legacyKDF")); - } + private static final boolean VALUE = + Boolean.getBoolean("jdk.crypto.KeyAgreement.legacyKDF"); } /** diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index 478593dfac1..4f6495b8916 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -241,7 +241,7 @@ protected AlgorithmParameters engineGetParameters() { params.init(spec); return params; } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) { - throw new RuntimeException(e); + throw new ProviderException(e); } } @@ -781,7 +781,7 @@ int implGCMCrypt(ByteBuffer src, ByteBuffer dst) { int mergeBlock(byte[] buffer, int bufOfs, int bufLen, byte[] in, int inOfs, int inLen, byte[] block) { if (bufLen > blockSize) { - throw new RuntimeException("mergeBlock called on an ibuffer " + + throw new ProviderException("mergeBlock called on an ibuffer " + "too big: " + bufLen + " bytes"); } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java b/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java index ab8f2d7097b..3a8f19fa2fb 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java @@ -30,14 +30,12 @@ import java.io.*; import java.util.*; -import java.security.AccessController; import java.security.DigestInputStream; import java.security.DigestOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Key; import java.security.PrivateKey; -import java.security.PrivilegedAction; import java.security.KeyStoreSpi; import java.security.KeyStoreException; import java.security.UnrecoverableKeyException; @@ -835,15 +833,9 @@ public void engineLoad(InputStream stream, char[] password) // read the sealed key try { ois = new ObjectInputStream(dis); - final ObjectInputStream ois2 = ois; // Set a deserialization checker - @SuppressWarnings("removal") - var dummy = AccessController.doPrivileged( - (PrivilegedAction)() -> { - ois2.setObjectInputFilter( - new DeserializationChecker(fullLength)); - return null; - }); + ois.setObjectInputFilter( + new DeserializationChecker(fullLength)); entry.sealedKey = (SealedObject)ois.readObject(); entry.maxLength = fullLength; // NOTE: don't close ois here since we are still diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java b/src/java.base/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java index 01330678083..b5f5bc89f23 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -73,18 +73,13 @@ AlgorithmParameters getParameters() { return params; } - @SuppressWarnings("removal") final Key getKey(Cipher c, int maxLength) throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException { try (ObjectInputStream ois = SharedSecrets.getJavaxCryptoSealedObjectAccess() .getExtObjectInputStream(this, c)) { - AccessController.doPrivileged( - (PrivilegedAction) () -> { - ois.setObjectInputFilter(new DeserializationChecker(maxLength)); - return null; - }); + ois.setObjectInputFilter(new DeserializationChecker(maxLength)); try { @SuppressWarnings("unchecked") Key t = (Key) ois.readObject(); @@ -113,16 +108,8 @@ private static class DeserializationChecker implements ObjectInputFilter { private static final ObjectInputFilter OWN_FILTER; static { - @SuppressWarnings("removal") - String prop = AccessController.doPrivileged( - (PrivilegedAction) () -> { - String tmp = System.getProperty(KEY_SERIAL_FILTER); - if (tmp != null) { - return tmp; - } else { - return Security.getProperty(KEY_SERIAL_FILTER); - } - }); + String prop = System.getProperty( + KEY_SERIAL_FILTER, Security.getProperty(KEY_SERIAL_FILTER)); OWN_FILTER = prop == null ? null : ObjectInputFilter.Config.createFilter(prop); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java index c0766077ba9..6e3efe8c285 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java @@ -25,10 +25,8 @@ package com.sun.crypto.provider; -import java.security.AccessController; import java.security.Provider; import java.security.SecureRandom; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.List; import static sun.security.util.SecurityConstants.PROVIDER_VER; @@ -121,24 +119,12 @@ private void psA(String type, String algo, String cn, attrs)); } - @SuppressWarnings("removal") public SunJCE() { /* We are the "SunJCE" provider */ super("SunJCE", PROVIDER_VER, info); - // if there is no security manager installed, put directly into - // the provider - if (System.getSecurityManager() == null) { - putEntries(); - } else { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - putEntries(); - return null; - } - }); - } + putEntries(); + if (instance == null) { instance = this; } diff --git a/src/java.base/share/classes/java/io/BufferedInputStream.java b/src/java.base/share/classes/java/io/BufferedInputStream.java index c401873ce12..5ca55d838ae 100644 --- a/src/java.base/share/classes/java/io/BufferedInputStream.java +++ b/src/java.base/share/classes/java/io/BufferedInputStream.java @@ -28,7 +28,6 @@ import java.util.Arrays; import java.util.Objects; -import jdk.internal.misc.InternalLock; import jdk.internal.misc.Unsafe; import jdk.internal.util.ArraysSupport; @@ -74,9 +73,6 @@ public class BufferedInputStream extends FilterInputStream { private static final long BUF_OFFSET = U.objectFieldOffset(BufferedInputStream.class, "buf"); - // initialized to null when BufferedInputStream is sub-classed - private final InternalLock lock; - // initial buffer size (DEFAULT_BUFFER_SIZE or size specified to constructor) private final int initialSize; @@ -243,12 +239,9 @@ public BufferedInputStream(InputStream in, int size) { } initialSize = size; if (getClass() == BufferedInputStream.class) { - // use internal lock and lazily create buffer when not subclassed - lock = InternalLock.newLockOrNull(); + // lazily create buffer when not subclassed buf = EMPTY; } else { - // use monitors and eagerly create buffer when subclassed - lock = null; buf = new byte[size]; } } @@ -256,7 +249,7 @@ public BufferedInputStream(InputStream in, int size) { /** * Fills the buffer with more data, taking into account * shuffling and other tricks for dealing with marks. - * Assumes that it is being called by a locked method. + * Assumes that it is being called by a synchronized method. * This method also assumes that all data has already been read in, * hence pos > count. */ @@ -310,22 +303,7 @@ else if (pos >= buffer.length) { /* no room left in buffer */ * or an I/O error occurs. * @see java.io.FilterInputStream#in */ - public int read() throws IOException { - if (lock != null) { - lock.lock(); - try { - return implRead(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implRead(); - } - } - } - - private int implRead() throws IOException { + public synchronized int read() throws IOException { if (pos >= count) { fill(); if (pos >= count) @@ -397,22 +375,7 @@ private int read1(byte[] b, int off, int len) throws IOException { * or an I/O error occurs. * @throws IndexOutOfBoundsException {@inheritDoc} */ - public int read(byte[] b, int off, int len) throws IOException { - if (lock != null) { - lock.lock(); - try { - return implRead(b, off, len); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implRead(b, off, len); - } - } - } - - private int implRead(byte[] b, int off, int len) throws IOException { + public synchronized int read(byte[] b, int off, int len) throws IOException { ensureOpen(); if ((off | len | (off + len) | (b.length - (off + len))) < 0) { throw new IndexOutOfBoundsException(); @@ -444,22 +407,7 @@ private int implRead(byte[] b, int off, int len) throws IOException { * {@code in.skip(n)} throws an IOException, * or an I/O error occurs. */ - public long skip(long n) throws IOException { - if (lock != null) { - lock.lock(); - try { - return implSkip(n); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implSkip(n); - } - } - } - - private long implSkip(long n) throws IOException { + public synchronized long skip(long n) throws IOException { ensureOpen(); if (n <= 0) { return 0; @@ -500,22 +448,7 @@ private long implSkip(long n) throws IOException { * invoking its {@link #close()} method, * or an I/O error occurs. */ - public int available() throws IOException { - if (lock != null) { - lock.lock(); - try { - return implAvailable(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implAvailable(); - } - } - } - - private int implAvailable() throws IOException { + public synchronized int available() throws IOException { int n = count - pos; int avail = getInIfOpen().available(); return n > (Integer.MAX_VALUE - avail) @@ -531,22 +464,7 @@ private int implAvailable() throws IOException { * the mark position becomes invalid. * @see java.io.BufferedInputStream#reset() */ - public void mark(int readlimit) { - if (lock != null) { - lock.lock(); - try { - implMark(readlimit); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implMark(readlimit); - } - } - } - - private void implMark(int readlimit) { + public synchronized void mark(int readlimit) { marklimit = readlimit; markpos = pos; } @@ -567,22 +485,7 @@ private void implMark(int readlimit) { * method, or an I/O error occurs. * @see java.io.BufferedInputStream#mark(int) */ - public void reset() throws IOException { - if (lock != null) { - lock.lock(); - try { - implReset(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implReset(); - } - } - } - - private void implReset() throws IOException { + public synchronized void reset() throws IOException { ensureOpen(); if (markpos < 0) throw new IOException("Resetting to invalid mark"); @@ -628,23 +531,8 @@ public void close() throws IOException { } @Override - public long transferTo(OutputStream out) throws IOException { + public synchronized long transferTo(OutputStream out) throws IOException { Objects.requireNonNull(out, "out"); - if (lock != null) { - lock.lock(); - try { - return implTransferTo(out); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implTransferTo(out); - } - } - } - - private long implTransferTo(OutputStream out) throws IOException { if (getClass() == BufferedInputStream.class && markpos == -1) { int avail = count - pos; if (avail > 0) { diff --git a/src/java.base/share/classes/java/io/BufferedOutputStream.java b/src/java.base/share/classes/java/io/BufferedOutputStream.java index 687f0c91bc4..2ad9adad5ad 100644 --- a/src/java.base/share/classes/java/io/BufferedOutputStream.java +++ b/src/java.base/share/classes/java/io/BufferedOutputStream.java @@ -26,7 +26,6 @@ package java.io; import java.util.Arrays; -import jdk.internal.misc.InternalLock; import jdk.internal.misc.VM; /** @@ -47,9 +46,6 @@ public class BufferedOutputStream extends FilterOutputStream { private static final int DEFAULT_INITIAL_BUFFER_SIZE = 512; private static final int DEFAULT_MAX_BUFFER_SIZE = 8192; - // initialized to null when BufferedOutputStream is sub-classed - private final InternalLock lock; - /** * The internal buffer where data is stored. */ @@ -90,12 +86,9 @@ private BufferedOutputStream(OutputStream out, int initialSize, int maxSize) { } if (getClass() == BufferedOutputStream.class) { - // use InternalLock and resizable buffer when not sub-classed - this.lock = InternalLock.newLockOrNull(); - this.buf = new byte[initialSize]; // resizable + // resizable when not sub-classed + this.buf = new byte[initialSize]; } else { - // use monitors and no resizing when sub-classed - this.lock = null; this.buf = new byte[maxSize]; } this.maxBufSize = maxSize; @@ -136,8 +129,6 @@ private void flushBuffer() throws IOException { * Grow buf to fit an additional len bytes if needed. * If possible, it grows by len+1 to avoid flushing when len bytes * are added. A no-op if the buffer is not resizable. - * - * This method should only be called while holding the lock. */ private void growIfNeeded(int len) { int neededSize = count + len + 1; @@ -157,22 +148,7 @@ private void growIfNeeded(int len) { * @throws IOException if an I/O error occurs. */ @Override - public void write(int b) throws IOException { - if (lock != null) { - lock.lock(); - try { - implWrite(b); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(b); - } - } - } - - private void implWrite(int b) throws IOException { + public synchronized void write(int b) throws IOException { growIfNeeded(1); if (count >= buf.length) { flushBuffer(); @@ -198,22 +174,7 @@ private void implWrite(int b) throws IOException { * @throws IndexOutOfBoundsException {@inheritDoc} */ @Override - public void write(byte[] b, int off, int len) throws IOException { - if (lock != null) { - lock.lock(); - try { - implWrite(b, off, len); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(b, off, len); - } - } - } - - private void implWrite(byte[] b, int off, int len) throws IOException { + public synchronized void write(byte[] b, int off, int len) throws IOException { if (len >= maxBufSize) { /* If the request length exceeds the max size of the output buffer, flush the output buffer and then write the data directly. @@ -238,22 +199,7 @@ private void implWrite(byte[] b, int off, int len) throws IOException { * @see java.io.FilterOutputStream#out */ @Override - public void flush() throws IOException { - if (lock != null) { - lock.lock(); - try { - implFlush(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implFlush(); - } - } - } - - private void implFlush() throws IOException { + public synchronized void flush() throws IOException { flushBuffer(); out.flush(); } diff --git a/src/java.base/share/classes/java/io/BufferedReader.java b/src/java.base/share/classes/java/io/BufferedReader.java index c2f6b89e086..a51f0acaf00 100644 --- a/src/java.base/share/classes/java/io/BufferedReader.java +++ b/src/java.base/share/classes/java/io/BufferedReader.java @@ -32,7 +32,6 @@ import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import jdk.internal.misc.InternalLock; /** * Reads text from a character-input stream, buffering characters so as to @@ -181,37 +180,23 @@ private void fill() throws IOException { * @throws IOException If an I/O error occurs */ public int read() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implRead(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implRead(); - } - } - } - - private int implRead() throws IOException { - ensureOpen(); - for (;;) { - if (nextChar >= nChars) { - fill(); - if (nextChar >= nChars) - return -1; - } - if (skipLF) { - skipLF = false; - if (cb[nextChar] == '\n') { - nextChar++; - continue; + synchronized (lock) { + ensureOpen(); + for (;;) { + if (nextChar >= nChars) { + fill(); + if (nextChar >= nChars) + return -1; + } + if (skipLF) { + skipLF = false; + if (cb[nextChar] == '\n') { + nextChar++; + continue; + } } + return cb[nextChar++]; } - return cb[nextChar++]; } } @@ -296,36 +281,22 @@ private int read1(char[] cbuf, int off, int len) throws IOException { * @throws IOException {@inheritDoc} */ public int read(char[] cbuf, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implRead(cbuf, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implRead(cbuf, off, len); + synchronized (lock) { + ensureOpen(); + Objects.checkFromIndexSize(off, len, cbuf.length); + if (len == 0) { + return 0; } - } - } - - private int implRead(char[] cbuf, int off, int len) throws IOException { - ensureOpen(); - Objects.checkFromIndexSize(off, len, cbuf.length); - if (len == 0) { - return 0; - } - int n = read1(cbuf, off, len); - if (n <= 0) return n; - while ((n < len) && in.ready()) { - int n1 = read1(cbuf, off + n, len - n); - if (n1 <= 0) break; - n += n1; + int n = read1(cbuf, off, len); + if (n <= 0) return n; + while ((n < len) && in.ready()) { + int n1 = read1(cbuf, off + n, len - n); + if (n1 <= 0) break; + n += n1; + } + return n; } - return n; } /** @@ -347,81 +318,67 @@ private int implRead(char[] cbuf, int off, int len) throws IOException { * @throws IOException If an I/O error occurs */ String readLine(boolean ignoreLF, boolean[] term) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implReadLine(ignoreLF, term); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implReadLine(ignoreLF, term); - } - } - } + synchronized (lock) { + StringBuilder s = null; + int startChar; - private String implReadLine(boolean ignoreLF, boolean[] term) throws IOException { - StringBuilder s = null; - int startChar; + ensureOpen(); + boolean omitLF = ignoreLF || skipLF; + if (term != null) term[0] = false; - ensureOpen(); - boolean omitLF = ignoreLF || skipLF; - if (term != null) term[0] = false; + bufferLoop: + for (;;) { - bufferLoop: - for (;;) { - - if (nextChar >= nChars) - fill(); - if (nextChar >= nChars) { /* EOF */ - if (s != null && s.length() > 0) - return s.toString(); - else - return null; - } - boolean eol = false; - char c = 0; - int i; + if (nextChar >= nChars) + fill(); + if (nextChar >= nChars) { /* EOF */ + if (s != null && s.length() > 0) + return s.toString(); + else + return null; + } + boolean eol = false; + char c = 0; + int i; - /* Skip a leftover '\n', if necessary */ - if (omitLF && (cb[nextChar] == '\n')) - nextChar++; - skipLF = false; - omitLF = false; - - charLoop: - for (i = nextChar; i < nChars; i++) { - c = cb[i]; - if ((c == '\n') || (c == '\r')) { - if (term != null) term[0] = true; - eol = true; - break charLoop; + /* Skip a leftover '\n', if necessary */ + if (omitLF && (cb[nextChar] == '\n')) + nextChar++; + skipLF = false; + omitLF = false; + + charLoop: + for (i = nextChar; i < nChars; i++) { + c = cb[i]; + if ((c == '\n') || (c == '\r')) { + if (term != null) term[0] = true; + eol = true; + break charLoop; + } } - } - startChar = nextChar; - nextChar = i; + startChar = nextChar; + nextChar = i; - if (eol) { - String str; - if (s == null) { - str = new String(cb, startChar, i - startChar); - } else { - s.append(cb, startChar, i - startChar); - str = s.toString(); - } - nextChar++; - if (c == '\r') { - skipLF = true; + if (eol) { + String str; + if (s == null) { + str = new String(cb, startChar, i - startChar); + } else { + s.append(cb, startChar, i - startChar); + str = s.toString(); + } + nextChar++; + if (c == '\r') { + skipLF = true; + } + return str; } - return str; - } - if (s == null) - s = new StringBuilder(DEFAULT_EXPECTED_LINE_LENGTH); - s.append(cb, startChar, i - startChar); + if (s == null) + s = new StringBuilder(DEFAULT_EXPECTED_LINE_LENGTH); + s.append(cb, startChar, i - startChar); + } } } @@ -450,47 +407,33 @@ public long skip(long n) throws IOException { if (n < 0L) { throw new IllegalArgumentException("skip value is negative"); } - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implSkip(n); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implSkip(n); - } - } - } - - private long implSkip(long n) throws IOException { - ensureOpen(); - long r = n; - while (r > 0) { - if (nextChar >= nChars) - fill(); - if (nextChar >= nChars) /* EOF */ - break; - if (skipLF) { - skipLF = false; - if (cb[nextChar] == '\n') { - nextChar++; + synchronized (lock) { + ensureOpen(); + long r = n; + while (r > 0) { + if (nextChar >= nChars) + fill(); + if (nextChar >= nChars) /* EOF */ + break; + if (skipLF) { + skipLF = false; + if (cb[nextChar] == '\n') { + nextChar++; + } + } + long d = nChars - nextChar; + if (r <= d) { + nextChar += (int)r; + r = 0; + break; + } + else { + r -= d; + nextChar = nChars; } } - long d = nChars - nextChar; - if (r <= d) { - nextChar += (int)r; - r = 0; - break; - } - else { - r -= d; - nextChar = nChars; - } + return n - r; } - return n - r; } /** @@ -501,42 +444,28 @@ private long implSkip(long n) throws IOException { * @throws IOException If an I/O error occurs */ public boolean ready() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implReady(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implReady(); - } - } - } + synchronized (lock) { + ensureOpen(); - private boolean implReady() throws IOException { - ensureOpen(); - - /* - * If newline needs to be skipped and the next char to be read - * is a newline character, then just skip it right away. - */ - if (skipLF) { - /* Note that in.ready() will return true if and only if the next - * read on the stream will not block. + /* + * If newline needs to be skipped and the next char to be read + * is a newline character, then just skip it right away. */ - if (nextChar >= nChars && in.ready()) { - fill(); - } - if (nextChar < nChars) { - if (cb[nextChar] == '\n') - nextChar++; - skipLF = false; + if (skipLF) { + /* Note that in.ready() will return true if and only if the next + * read on the stream will not block. + */ + if (nextChar >= nChars && in.ready()) { + fill(); + } + if (nextChar < nChars) { + if (cb[nextChar] == '\n') + nextChar++; + skipLF = false; + } } + return (nextChar < nChars) || in.ready(); } - return (nextChar < nChars) || in.ready(); } /** @@ -566,28 +495,14 @@ public void mark(int readAheadLimit) throws IOException { if (readAheadLimit < 0) { throw new IllegalArgumentException("Read-ahead limit < 0"); } - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implMark(readAheadLimit); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implMark(readAheadLimit); - } + synchronized (lock) { + ensureOpen(); + this.readAheadLimit = readAheadLimit; + markedChar = nextChar; + markedSkipLF = skipLF; } } - private void implMark(int readAheadLimit) throws IOException { - ensureOpen(); - this.readAheadLimit = readAheadLimit; - markedChar = nextChar; - markedSkipLF = skipLF; - } - /** * Resets the stream to the most recent mark. * @@ -595,55 +510,27 @@ private void implMark(int readAheadLimit) throws IOException { * or if the mark has been invalidated */ public void reset() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implReset(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implReset(); - } + synchronized (lock) { + ensureOpen(); + if (markedChar < 0) + throw new IOException((markedChar == INVALIDATED) + ? "Mark invalid" + : "Stream not marked"); + nextChar = markedChar; + skipLF = markedSkipLF; } } - private void implReset() throws IOException { - ensureOpen(); - if (markedChar < 0) - throw new IOException((markedChar == INVALIDATED) - ? "Mark invalid" - : "Stream not marked"); - nextChar = markedChar; - skipLF = markedSkipLF; - } - public void close() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { + if (in == null) + return; try { - implClose(); + in.close(); } finally { - locker.unlock(); + in = null; + cb = null; } - } else { - synchronized (lock) { - implClose(); - } - } - } - - private void implClose() throws IOException { - if (in == null) - return; - try { - in.close(); - } finally { - in = null; - cb = null; } } diff --git a/src/java.base/share/classes/java/io/BufferedWriter.java b/src/java.base/share/classes/java/io/BufferedWriter.java index 17862a265ae..e3f8a21fe60 100644 --- a/src/java.base/share/classes/java/io/BufferedWriter.java +++ b/src/java.base/share/classes/java/io/BufferedWriter.java @@ -27,7 +27,6 @@ import java.util.Arrays; import java.util.Objects; -import jdk.internal.misc.InternalLock; import jdk.internal.misc.VM; /** @@ -162,58 +161,30 @@ private void growIfNeeded(int len) { * may be invoked by PrintStream. */ void flushBuffer() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implFlushBuffer(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFlushBuffer(); - } + synchronized (lock) { + ensureOpen(); + if (nextChar == 0) + return; + out.write(cb, 0, nextChar); + nextChar = 0; } } - private void implFlushBuffer() throws IOException { - ensureOpen(); - if (nextChar == 0) - return; - out.write(cb, 0, nextChar); - nextChar = 0; - } - /** * Writes a single character. * * @throws IOException If an I/O error occurs */ public void write(int c) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(c); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(c); - } + synchronized (lock) { + ensureOpen(); + growIfNeeded(1); + if (nextChar >= nChars) + flushBuffer(); + cb[nextChar++] = (char) c; } } - private void implWrite(int c) throws IOException { - ensureOpen(); - growIfNeeded(1); - if (nextChar >= nChars) - flushBuffer(); - cb[nextChar++] = (char) c; - } - /** * Our own little min method, to avoid loading java.lang.Math if we've run * out of file descriptors and we're trying to print a stack trace. @@ -245,46 +216,32 @@ private int min(int a, int b) { * @throws IOException If an I/O error occurs */ public void write(char[] cbuf, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(cbuf, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(cbuf, off, len); + synchronized (lock) { + ensureOpen(); + Objects.checkFromIndexSize(off, len, cbuf.length); + if (len == 0) { + return; } - } - } - private void implWrite(char[] cbuf, int off, int len) throws IOException { - ensureOpen(); - Objects.checkFromIndexSize(off, len, cbuf.length); - if (len == 0) { - return; - } - - if (len >= maxChars) { - /* If the request length exceeds the max size of the output buffer, - flush the buffer and then write the data directly. In this - way buffered streams will cascade harmlessly. */ - flushBuffer(); - out.write(cbuf, off, len); - return; - } - - growIfNeeded(len); - int b = off, t = off + len; - while (b < t) { - int d = min(nChars - nextChar, t - b); - System.arraycopy(cbuf, b, cb, nextChar, d); - b += d; - nextChar += d; - if (nextChar >= nChars) { + if (len >= maxChars) { + /* If the request length exceeds the max size of the output buffer, + flush the buffer and then write the data directly. In this + way buffered streams will cascade harmlessly. */ flushBuffer(); + out.write(cbuf, off, len); + return; + } + + growIfNeeded(len); + int b = off, t = off + len; + while (b < t) { + int d = min(nChars - nextChar, t - b); + System.arraycopy(cbuf, b, cb, nextChar, d); + b += d; + nextChar += d; + if (nextChar >= nChars) { + flushBuffer(); + } } } } @@ -312,35 +269,21 @@ private void implWrite(char[] cbuf, int off, int len) throws IOException { * @throws IOException If an I/O error occurs */ public void write(String s, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(s, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(s, off, len); + synchronized (lock) { + ensureOpen(); + growIfNeeded(len); + int b = off, t = off + len; + while (b < t) { + int d = min(nChars - nextChar, t - b); + s.getChars(b, b + d, cb, nextChar); + b += d; + nextChar += d; + if (nextChar >= nChars) + flushBuffer(); } } } - private void implWrite(String s, int off, int len) throws IOException { - ensureOpen(); - growIfNeeded(len); - int b = off, t = off + len; - while (b < t) { - int d = min(nChars - nextChar, t - b); - s.getChars(b, b + d, cb, nextChar); - b += d; - nextChar += d; - if (nextChar >= nChars) - flushBuffer(); - } - } - /** * Writes a line separator. The line separator string is defined by the * system property {@code line.separator}, and is not necessarily a single @@ -358,52 +301,24 @@ public void newLine() throws IOException { * @throws IOException If an I/O error occurs */ public void flush() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implFlush(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFlush(); - } + synchronized (lock) { + flushBuffer(); + out.flush(); } } - private void implFlush() throws IOException { - flushBuffer(); - out.flush(); - } - + @SuppressWarnings("try") public void close() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implClose(); - } finally { - locker.unlock(); + synchronized (lock) { + if (out == null) { + return; } - } else { - synchronized (lock) { - implClose(); + try (Writer w = out) { + flushBuffer(); + } finally { + out = null; + cb = null; } } } - - @SuppressWarnings("try") - private void implClose() throws IOException { - if (out == null) { - return; - } - try (Writer w = out) { - flushBuffer(); - } finally { - out = null; - cb = null; - } - } } diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java index 8ae4fc00773..3881b2380ad 100644 --- a/src/java.base/share/classes/java/io/Console.java +++ b/src/java.base/share/classes/java/io/Console.java @@ -25,8 +25,6 @@ package java.io; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.*; import java.nio.charset.Charset; import jdk.internal.access.JavaIOAccess; @@ -172,6 +170,19 @@ public Console println(Object obj) { throw newUnsupportedOperationException(); } + /** + * Terminates the current line in this console's output stream using + * {@link System#lineSeparator()} and then flushes the console. + * + * @return This console + * + * @since 24 + */ + @PreviewFeature(feature = PreviewFeature.Feature.IMPLICIT_CLASSES) + public Console println() { + return println(""); + } + /** * Writes a string representation of the specified object to this console's * output stream and then flushes the console. @@ -214,6 +225,24 @@ public String readln(String prompt) { throw newUnsupportedOperationException(); } + /** + * Reads a single line of text from this console. + * + * @throws IOError + * If an I/O error occurs. + * + * @return A string containing the line read from the console, not + * including any line-termination characters, or {@code null} + * if an end of stream has been reached without having read + * any characters. + * + * @since 24 + */ + @PreviewFeature(feature = PreviewFeature.Feature.IMPLICIT_CLASSES) + public String readln() { + throw newUnsupportedOperationException(); + } + /** * Writes a formatted string to this console's output stream using * the specified format string and arguments with the @@ -628,9 +657,8 @@ public Console console() { }); } - @SuppressWarnings("removal") private static Console instantiateConsole() { - Console c; + Console c = null; try { /* @@ -642,25 +670,19 @@ private static Console instantiateConsole() { * If no providers are available, or instantiation failed, java.base built-in * Console implementation is used. */ - c = AccessController.doPrivileged(new PrivilegedAction() { - public Console run() { - var consModName = System.getProperty("jdk.console", - JdkConsoleProvider.DEFAULT_PROVIDER_MODULE_NAME); + var consModName = System.getProperty("jdk.console", + JdkConsoleProvider.DEFAULT_PROVIDER_MODULE_NAME); - for (var jcp : ServiceLoader.load(ModuleLayer.boot(), JdkConsoleProvider.class)) { - if (consModName.equals(jcp.getClass().getModule().getName())) { - var jc = jcp.console(istty, CHARSET); - if (jc != null) { - return new ProxyingConsole(jc); - } - break; - } + for (var jcp : ServiceLoader.load(ModuleLayer.boot(), JdkConsoleProvider.class)) { + if (consModName.equals(jcp.getClass().getModule().getName())) { + var jc = jcp.console(istty, CHARSET); + if (jc != null) { + c = new ProxyingConsole(jc); } - return null; + break; } - }); + } } catch (ServiceConfigurationError _) { - c = null; } // If not found, default to built-in Console diff --git a/src/java.base/share/classes/java/io/File.java b/src/java.base/share/classes/java/io/File.java index b8eda9dcf83..3cfeb7ffdee 100644 --- a/src/java.base/share/classes/java/io/File.java +++ b/src/java.base/share/classes/java/io/File.java @@ -751,11 +751,6 @@ public URI toURI() { * application; {@code false} otherwise */ public boolean canRead() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(path); - } if (isInvalid()) { return false; } @@ -775,11 +770,6 @@ public boolean canRead() { * {@code false} otherwise. */ public boolean canWrite() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(path); - } if (isInvalid()) { return false; } @@ -794,11 +784,6 @@ public boolean canWrite() { * by this abstract pathname exists; {@code false} otherwise */ public boolean exists() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(path); - } if (isInvalid()) { return false; } @@ -820,11 +805,6 @@ public boolean exists() { * {@code false} otherwise */ public boolean isDirectory() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(path); - } if (isInvalid()) { return false; } @@ -848,11 +828,6 @@ public boolean isDirectory() { * {@code false} otherwise */ public boolean isFile() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(path); - } if (isInvalid()) { return false; } @@ -881,11 +856,6 @@ public boolean isFile() { * @since 1.2 */ public boolean isHidden() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(path); - } if (isInvalid()) { return false; } @@ -920,11 +890,6 @@ public boolean isHidden() { * epoch */ public long lastModified() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(path); - } if (isInvalid()) { return 0L; } @@ -947,11 +912,6 @@ public long lastModified() { * denoting system-dependent entities such as devices or pipes. */ public long length() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(path); - } if (isInvalid()) { return 0L; } @@ -983,9 +943,6 @@ public long length() { * @since 1.2 */ public boolean createNewFile() throws IOException { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) security.checkWrite(path); if (isInvalid()) { throw new IOException("Invalid file path"); } @@ -1007,11 +964,6 @@ public boolean createNewFile() throws IOException { * successfully deleted; {@code false} otherwise */ public boolean delete() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkDelete(path); - } if (isInvalid()) { return false; } @@ -1043,11 +995,6 @@ public boolean delete() { * @since 1.2 */ public void deleteOnExit() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkDelete(path); - } if (isInvalid()) { return; } @@ -1097,11 +1044,6 @@ public String[] list() { * I/O error occurs. */ private final String[] normalizedList() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(path); - } if (isInvalid()) { return null; } @@ -1275,11 +1217,6 @@ public File[] listFiles(FileFilter filter) { * created; {@code false} otherwise */ public boolean mkdir() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(path); - } if (isInvalid()) { return false; } @@ -1345,12 +1282,6 @@ public boolean renameTo(File dest) { if (dest == null) { throw new NullPointerException(); } - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(path); - security.checkWrite(dest.path); - } if (this.isInvalid() || dest.isInvalid()) { return false; } @@ -1380,11 +1311,6 @@ public boolean renameTo(File dest) { */ public boolean setLastModified(long time) { if (time < 0) throw new IllegalArgumentException("Negative time"); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(path); - } if (isInvalid()) { return false; } @@ -1406,11 +1332,6 @@ public boolean setLastModified(long time) { * @since 1.2 */ public boolean setReadOnly() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(path); - } if (isInvalid()) { return false; } @@ -1445,11 +1366,6 @@ public boolean setReadOnly() { * @since 1.6 */ public boolean setWritable(boolean writable, boolean ownerOnly) { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(path); - } if (isInvalid()) { return false; } @@ -1517,11 +1433,6 @@ public boolean setWritable(boolean writable) { * @since 1.6 */ public boolean setReadable(boolean readable, boolean ownerOnly) { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(path); - } if (isInvalid()) { return false; } @@ -1595,11 +1506,6 @@ public boolean setReadable(boolean readable) { * @since 1.6 */ public boolean setExecutable(boolean executable, boolean ownerOnly) { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(path); - } if (isInvalid()) { return false; } @@ -1652,11 +1558,6 @@ public boolean setExecutable(boolean executable) { * @since 1.6 */ public boolean canExecute() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkExec(path); - } if (isInvalid()) { return false; } @@ -1726,12 +1627,6 @@ public static File[] listRoots() { * @see FileStore#getTotalSpace */ public long getTotalSpace() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); - sm.checkRead(path); - } if (isInvalid()) { return 0L; } @@ -1764,12 +1659,6 @@ public long getTotalSpace() { * @see FileStore#getUnallocatedSpace */ public long getFreeSpace() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); - sm.checkRead(path); - } if (isInvalid()) { return 0L; } @@ -1805,12 +1694,6 @@ public long getFreeSpace() { * @see FileStore#getUsableSpace */ public long getUsableSpace() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); - sm.checkRead(path); - } if (isInvalid()) { return 0L; } @@ -1840,7 +1723,6 @@ private static int shortenSubName(int subNameLength, int excess, } return subNameLength; } - @SuppressWarnings("removal") static File generateFile(String prefix, String suffix, File dir) throws IOException { @@ -1897,11 +1779,8 @@ static File generateFile(String prefix, String suffix, File dir) File f = new File(dir, name); if (!name.equals(f.getName()) || f.isInvalid()) { - if (System.getSecurityManager() != null) - throw new IOException("Unable to create temporary file"); - else - throw new IOException("Unable to create temporary file, " - + name); + throw new IOException("Unable to create temporary file, " + + name); } return f; } @@ -1998,22 +1877,9 @@ public static File createTempFile(String prefix, String suffix, File tmpdir = (directory != null) ? directory : TempDirectory.location(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); File f; do { f = TempDirectory.generateFile(prefix, suffix, tmpdir); - - if (sm != null) { - try { - sm.checkWrite(f.getPath()); - } catch (SecurityException se) { - // don't reveal temporary directory location - if (directory == null) - throw new SecurityException("Unable to create temporary file"); - throw se; - } - } } while (FS.hasBooleanAttributes(f, FileSystem.BA_EXISTS)); if (!FS.createFileExclusively(f.getPath())) diff --git a/src/java.base/share/classes/java/io/FileInputStream.java b/src/java.base/share/classes/java/io/FileInputStream.java index e429faec09b..ab312fc8c5b 100644 --- a/src/java.base/share/classes/java/io/FileInputStream.java +++ b/src/java.base/share/classes/java/io/FileInputStream.java @@ -130,22 +130,13 @@ public FileInputStream(String name) throws FileNotFoundException { */ @SuppressWarnings("this-escape") public FileInputStream(File file) throws FileNotFoundException { - String name = (file != null ? file.getPath() : null); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(name); - } - if (name == null) { - throw new NullPointerException(); - } if (file.isInvalid()) { throw new FileNotFoundException("Invalid file path"); } + path = file.getPath(); fd = new FileDescriptor(); fd.attach(this); - path = name; - open(name); + open(path); FileCleanable.register(fd); // open set the fd, register the cleanup } @@ -166,14 +157,9 @@ public FileInputStream(File file) throws FileNotFoundException { */ @SuppressWarnings("this-escape") public FileInputStream(FileDescriptor fdObj) { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); if (fdObj == null) { throw new NullPointerException(); } - if (security != null) { - security.checkRead(fdObj); - } fd = fdObj; path = null; diff --git a/src/java.base/share/classes/java/io/FileOutputStream.java b/src/java.base/share/classes/java/io/FileOutputStream.java index 557bea0c3fc..6c5a30ea432 100644 --- a/src/java.base/share/classes/java/io/FileOutputStream.java +++ b/src/java.base/share/classes/java/io/FileOutputStream.java @@ -199,23 +199,15 @@ public FileOutputStream(File file) throws FileNotFoundException { public FileOutputStream(File file, boolean append) throws FileNotFoundException { - String name = (file != null ? file.getPath() : null); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(name); - } - if (name == null) { - throw new NullPointerException(); - } if (file.isInvalid()) { throw new FileNotFoundException("Invalid file path"); } + this.path = file.getPath(); + this.fd = new FileDescriptor(); fd.attach(this); - this.path = name; - open(name, append); + open(this.path, append); FileCleanable.register(fd); // open sets the fd, register the cleanup } @@ -236,14 +228,9 @@ public FileOutputStream(File file, boolean append) */ @SuppressWarnings("this-escape") public FileOutputStream(FileDescriptor fdObj) { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); if (fdObj == null) { throw new NullPointerException(); } - if (security != null) { - security.checkWrite(fdObj); - } this.fd = fdObj; this.path = null; diff --git a/src/java.base/share/classes/java/io/FilePermission.java b/src/java.base/share/classes/java/io/FilePermission.java index b11e0dd25be..30fa3978638 100644 --- a/src/java.base/share/classes/java/io/FilePermission.java +++ b/src/java.base/share/classes/java/io/FilePermission.java @@ -26,7 +26,8 @@ package java.io; import java.nio.file.*; -import java.security.*; +import java.security.Permission; +import java.security.PermissionCollection; import java.util.Enumeration; import java.util.Objects; import java.util.StringJoiner; @@ -36,7 +37,6 @@ import jdk.internal.access.JavaIOFilePermissionAccess; import jdk.internal.access.SharedSecrets; import sun.nio.fs.DefaultFileSystemProvider; -import sun.security.action.GetPropertyAction; import sun.security.util.FilePermCompat; import sun.security.util.SecurityConstants; @@ -181,8 +181,7 @@ public final class FilePermission extends Permission implements Serializable { private static final java.nio.file.FileSystem builtInFS = DefaultFileSystemProvider.theFileSystem(); - private static final Path here = builtInFS.getPath( - GetPropertyAction.privilegedGetProperty("user.dir")); + private static final Path here = builtInFS.getPath(jdk.internal.util.StaticProperty.userDir()); private static final Path EMPTY_PATH = builtInFS.getPath(""); private static final Path DASH_PATH = builtInFS.getPath("-"); @@ -361,25 +360,20 @@ private void init(int mask) { } // store only the canonical cpath if possible - cpath = AccessController.doPrivileged(new PrivilegedAction<>() { - public String run() { - try { - String path = cpath; - if (cpath.endsWith("*")) { - // call getCanonicalPath with a path with wildcard character - // replaced to avoid calling it with paths that are - // intended to match all entries in a directory - path = path.substring(0, path.length() - 1) + "-"; - path = new File(path).getCanonicalPath(); - return path.substring(0, path.length() - 1) + "*"; - } else { - return new File(path).getCanonicalPath(); - } - } catch (IOException ioe) { - return cpath; - } + try { + String path = cpath; + if (cpath.endsWith("*")) { + // call getCanonicalPath with a path with wildcard character + // replaced to avoid calling it with paths that are + // intended to match all entries in a directory + path = path.substring(0, path.length() - 1) + "-"; + path = new File(path).getCanonicalPath(); + cpath = path.substring(0, path.length() - 1) + "*"; + } else { + cpath = new File(path).getCanonicalPath(); } - }); + } catch (IOException ignore) { + } int len = cpath.length(); char last = ((len > 0) ? cpath.charAt(len - 1) : 0); diff --git a/src/java.base/share/classes/java/io/IO.java b/src/java.base/share/classes/java/io/IO.java index 7485f87f03f..a49a51041fc 100644 --- a/src/java.base/share/classes/java/io/IO.java +++ b/src/java.base/share/classes/java/io/IO.java @@ -63,6 +63,21 @@ public static void println(Object obj) { con().println(obj); } + /** + * Terminates the current line on the system console and then flushes + * that console. + * + *

The effect is as if {@link Console#println() println()} + * had been called on {@code System.console()}. + * + * @throws IOError if {@code System.console()} returns {@code null}, + * or if an I/O error occurs + * @since 24 + */ + public static void println() { + con().println(); + } + /** * Writes a string representation of the specified object to the system * console and then flushes that console. @@ -99,6 +114,24 @@ public static String readln(String prompt) { return con().readln(prompt); } + /** + * Reads a single line of text from the system console. + * + *

The effect is as if {@link Console#readln() readln()} + * had been called on {@code System.console()}. + * + * @return a string containing the line read from the system console, not + * including any line-termination characters. Returns {@code null} if an + * end of stream has been reached without having read any characters. + * + * @throws IOError if {@code System.console()} returns {@code null}, + * or if an I/O error occurs + * @since 24 + */ + public static String readln() { + return con().readln(); + } + private static Console con() { var con = System.console(); if (con != null) { diff --git a/src/java.base/share/classes/java/io/InputStreamReader.java b/src/java.base/share/classes/java/io/InputStreamReader.java index d3033b15b9f..6d43c4ae0cd 100644 --- a/src/java.base/share/classes/java/io/InputStreamReader.java +++ b/src/java.base/share/classes/java/io/InputStreamReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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,7 +28,6 @@ import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; -import jdk.internal.misc.InternalLock; import sun.nio.cs.StreamDecoder; /** @@ -62,20 +61,6 @@ public class InputStreamReader extends Reader { private final StreamDecoder sd; - /** - * Return the lock object for the given reader's stream decoder. - * If the reader type is trusted then an internal lock can be used. If the - * reader type is not trusted then the reader object is the lock. - */ - private static Object lockFor(InputStreamReader reader) { - Class clazz = reader.getClass(); - if (clazz == InputStreamReader.class || clazz == FileReader.class) { - return InternalLock.newLockOr(reader); - } else { - return reader; - } - } - /** * Creates an InputStreamReader that uses the * {@link Charset#defaultCharset() default charset}. @@ -88,7 +73,7 @@ private static Object lockFor(InputStreamReader reader) { public InputStreamReader(InputStream in) { super(in); Charset cs = Charset.defaultCharset(); - sd = StreamDecoder.forInputStreamReader(in, lockFor(this), cs); + sd = StreamDecoder.forInputStreamReader(in, this, cs); } /** @@ -110,7 +95,7 @@ public InputStreamReader(InputStream in, String charsetName) super(in); if (charsetName == null) throw new NullPointerException("charsetName"); - sd = StreamDecoder.forInputStreamReader(in, lockFor(this), charsetName); + sd = StreamDecoder.forInputStreamReader(in, this, charsetName); } /** @@ -126,7 +111,7 @@ public InputStreamReader(InputStream in, Charset cs) { super(in); if (cs == null) throw new NullPointerException("charset"); - sd = StreamDecoder.forInputStreamReader(in, lockFor(this), cs); + sd = StreamDecoder.forInputStreamReader(in, this, cs); } /** @@ -142,7 +127,7 @@ public InputStreamReader(InputStream in, CharsetDecoder dec) { super(in); if (dec == null) throw new NullPointerException("charset decoder"); - sd = StreamDecoder.forInputStreamReader(in, lockFor(this), dec); + sd = StreamDecoder.forInputStreamReader(in, this, dec); } /** diff --git a/src/java.base/share/classes/java/io/ObjectInputFilter.java b/src/java.base/share/classes/java/io/ObjectInputFilter.java index 9a04e1f58e3..9232111de07 100644 --- a/src/java.base/share/classes/java/io/ObjectInputFilter.java +++ b/src/java.base/share/classes/java/io/ObjectInputFilter.java @@ -29,8 +29,6 @@ import jdk.internal.util.StaticProperty; import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.security.Security; import java.util.ArrayList; import java.util.List; @@ -630,17 +628,13 @@ final class Config { configLog = System.getLogger("java.io.serialization"); // Get the values of the system properties, if they are defined - @SuppressWarnings("removal") String factoryClassName = StaticProperty.jdkSerialFilterFactory() != null ? StaticProperty.jdkSerialFilterFactory() - : AccessController.doPrivileged((PrivilegedAction) () -> - Security.getProperty(SERIAL_FILTER_FACTORY_PROPNAME)); + : Security.getProperty(SERIAL_FILTER_FACTORY_PROPNAME); - @SuppressWarnings("removal") String filterString = StaticProperty.jdkSerialFilter() != null ? StaticProperty.jdkSerialFilter() - : AccessController.doPrivileged((PrivilegedAction) () -> - Security.getProperty(SERIAL_FILTER_PROPNAME)); + : Security.getProperty(SERIAL_FILTER_PROPNAME); // Initialize the static filter if the jdk.serialFilter is present String filterMessage = null; @@ -734,11 +728,6 @@ public static ObjectInputFilter getSerialFilter() { */ public static void setSerialFilter(ObjectInputFilter filter) { Objects.requireNonNull(filter, "filter"); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(ObjectStreamConstants.SERIAL_FILTER_PERMISSION); - } if (invalidFilterMessage != null) { throw new IllegalStateException(invalidFilterMessage); } @@ -831,11 +820,6 @@ static BinaryOperator getSerialFilterFactorySingleton() { */ public static void setSerialFilterFactory(BinaryOperator filterFactory) { Objects.requireNonNull(filterFactory, "filterFactory"); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(ObjectStreamConstants.SERIAL_FILTER_PERMISSION); - } if (filterFactoryNoReplace.getAndSet(true)) { final String msg = serialFilterFactory != null ? "Cannot replace filter factory: " + serialFilterFactory.getClass().getName() diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 60d8cadf6a3..31d0aecf831 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -34,13 +34,7 @@ import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.nio.charset.StandardCharsets; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Arrays; -import java.util.Map; import java.util.Objects; import jdk.internal.access.JavaLangAccess; @@ -49,8 +43,6 @@ import jdk.internal.misc.Unsafe; import jdk.internal.util.ByteArray; import sun.reflect.misc.ReflectUtil; -import sun.security.action.GetBooleanAction; -import sun.security.action.GetIntegerAction; /** * An ObjectInputStream deserializes primitive data and objects previously @@ -278,8 +270,8 @@ protected Boolean computeValue(Class type) { * have been read. * See {@link #setObjectInputFilter(ObjectInputFilter)} */ - static final boolean SET_FILTER_AFTER_READ = GetBooleanAction - .privilegedGetProperty("jdk.serialSetFilterAfterRead"); + static final boolean SET_FILTER_AFTER_READ = + Boolean.getBoolean("jdk.serialSetFilterAfterRead"); /** * Property to control {@link GetField#get(String, Object)} conversion of @@ -287,8 +279,8 @@ protected Boolean computeValue(Class type) { * {@link GetField#get(String, Object)} returns null otherwise * throwing {@link ClassNotFoundException}. */ - private static final boolean GETFIELD_CNFE_RETURNS_NULL = GetBooleanAction - .privilegedGetProperty("jdk.serialGetFieldCnfeReturnsNull"); + private static final boolean GETFIELD_CNFE_RETURNS_NULL = + Boolean.getBoolean("jdk.serialGetFieldCnfeReturnsNull"); /** * Property to override the implementation limit on the number @@ -296,8 +288,8 @@ protected Boolean computeValue(Class type) { * The maximum number of interfaces allowed for a proxy is limited to 65535 by * {@link java.lang.reflect.Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}. */ - static final int PROXY_INTERFACE_LIMIT = Math.clamp(GetIntegerAction - .privilegedGetProperty("jdk.serialProxyInterfaceLimit", 65535), 0, 65535); + static final int PROXY_INTERFACE_LIMIT = + Math.clamp(Integer.getInteger("jdk.serialProxyInterfaceLimit", 65535), 0, 65535); } /* @@ -386,7 +378,6 @@ private static class Logging { */ @SuppressWarnings("this-escape") public ObjectInputStream(InputStream in) throws IOException { - verifySubclass(); bin = new BlockDataInputStream(in); handles = new HandleTable(10); vlist = new ValidationList(); @@ -416,11 +407,6 @@ public ObjectInputStream(InputStream in) throws IOException { * fails due to invalid serial filter or serial filter factory properties. */ protected ObjectInputStream() throws IOException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); - } bin = null; handles = null; vlist = null; @@ -907,13 +893,6 @@ protected boolean enableResolveObject(boolean enable) { if (enable == enableResolve) { return enable; } - if (enable) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SUBSTITUTION_PERMISSION); - } - } enableResolve = enable; return !enableResolve; } @@ -1309,11 +1288,6 @@ public final ObjectInputFilter getObjectInputFilter() { * @since 9 */ public final void setObjectInputFilter(ObjectInputFilter filter) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(ObjectStreamConstants.SERIAL_FILTER_PERMISSION); - } if (totalObjectRefs > 0 && !Caches.SET_FILTER_AFTER_READ) { throw new IllegalStateException( "filter can not be set after an object has been read"); @@ -1571,58 +1545,29 @@ public abstract boolean get(String name, boolean val) public abstract Object get(String name, Object val) throws IOException, ClassNotFoundException; } - /** - * Verifies that this (possibly subclass) instance can be constructed - * without violating security constraints: the subclass must not override - * security-sensitive non-final methods, or else the - * "enableSubclassImplementation" SerializablePermission is checked. - */ - private void verifySubclass() { - Class cl = getClass(); - if (cl == ObjectInputStream.class) { - return; - } - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - boolean result = Caches.subclassAudits.get(cl); - if (!result) { - sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); - } - } - /** * Performs reflective checks on given subclass to verify that it doesn't * override security-sensitive non-final methods. Returns TRUE if subclass * is "safe", FALSE otherwise. */ - @SuppressWarnings("removal") private static Boolean auditSubclass(Class subcl) { - return AccessController.doPrivileged( - new PrivilegedAction() { - public Boolean run() { - for (Class cl = subcl; - cl != ObjectInputStream.class; - cl = cl.getSuperclass()) - { - try { - cl.getDeclaredMethod( - "readUnshared", (Class[]) null); - return Boolean.FALSE; - } catch (NoSuchMethodException ex) { - } - try { - cl.getDeclaredMethod("readFields", (Class[]) null); - return Boolean.FALSE; - } catch (NoSuchMethodException ex) { - } - } - return Boolean.TRUE; - } + for (Class cl = subcl; + cl != ObjectInputStream.class; + cl = cl.getSuperclass()) + { + try { + cl.getDeclaredMethod( + "readUnshared", (Class[]) null); + return Boolean.FALSE; + } catch (NoSuchMethodException ex) { } - ); + try { + cl.getDeclaredMethod("readFields", (Class[]) null); + return Boolean.FALSE; + } catch (NoSuchMethodException ex) { + } + } + return Boolean.TRUE; } /** @@ -2702,16 +2647,11 @@ private static class Callback { final ObjectInputValidation obj; final int priority; Callback next; - @SuppressWarnings("removal") - final AccessControlContext acc; - Callback(ObjectInputValidation obj, int priority, Callback next, - @SuppressWarnings("removal") AccessControlContext acc) - { + Callback(ObjectInputValidation obj, int priority, Callback next) { this.obj = obj; this.priority = priority; this.next = next; - this.acc = acc; } } @@ -2740,12 +2680,10 @@ void register(ObjectInputValidation obj, int priority) prev = cur; cur = cur.next; } - @SuppressWarnings("removal") - AccessControlContext acc = AccessController.getContext(); if (prev != null) { - prev.next = new Callback(obj, priority, cur, acc); + prev.next = new Callback(obj, priority, cur); } else { - list = new Callback(obj, priority, list, acc); + list = new Callback(obj, priority, list); } } @@ -2756,23 +2694,15 @@ void register(ObjectInputValidation obj, int priority) * throws an InvalidObjectException, the callback process is terminated * and the exception propagated upwards. */ - @SuppressWarnings("removal") void doCallbacks() throws InvalidObjectException { try { while (list != null) { - AccessController.doPrivileged( - new PrivilegedExceptionAction() - { - public Void run() throws InvalidObjectException { - list.obj.validateObject(); - return null; - } - }, list.acc); + list.obj.validateObject(); list = list.next; } - } catch (PrivilegedActionException ex) { + } catch (InvalidObjectException ex) { list = null; - throw (InvalidObjectException) ex.getException(); + throw ex; } } diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 429c91ab673..5225c673705 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -26,8 +26,6 @@ package java.io; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -224,11 +222,8 @@ protected Boolean computeValue(Class type) { * value of "sun.io.serialization.extendedDebugInfo" property, * as true or false for extended information about exception's place */ - @SuppressWarnings("removal") private static final boolean extendedDebugInfo = - java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "sun.io.serialization.extendedDebugInfo")).booleanValue(); + Boolean.getBoolean("sun.io.serialization.extendedDebugInfo"); /** * Creates an ObjectOutputStream that writes to the specified OutputStream. @@ -247,7 +242,6 @@ protected Boolean computeValue(Class type) { */ @SuppressWarnings("this-escape") public ObjectOutputStream(OutputStream out) throws IOException { - verifySubclass(); bout = new BlockDataOutputStream(out); handles = new HandleTable(10, (float) 3.00); subs = new ReplaceTable(10, (float) 3.00); @@ -269,11 +263,6 @@ public ObjectOutputStream(OutputStream out) throws IOException { * @throws IOException if an I/O error occurs while creating this stream */ protected ObjectOutputStream() throws IOException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); - } bout = null; handles = null; subs = null; @@ -595,13 +584,6 @@ protected boolean enableReplaceObject(boolean enable) { if (enable == enableReplace) { return enable; } - if (enable) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SUBSTITUTION_PERMISSION); - } - } enableReplace = enable; return !enableReplace; } @@ -625,8 +607,8 @@ protected void writeStreamHeader() throws IOException { * stream. Subclasses of ObjectOutputStream may override this method to * customize the way in which class descriptors are written to the * serialization stream. The corresponding method in ObjectInputStream, - * {@link ObjectInputStream#readClassDescriptor readClassDescriptor}, should then be overridden to - * reconstitute the class descriptor from its custom stream representation. + * {@link ObjectInputStream#readClassDescriptor readClassDescriptor}, should then be + * overridden to reconstitute the class descriptor from its custom stream representation. * By default, this method writes class descriptors according to the format * defined in the * Java Object Serialization Specification. @@ -1022,58 +1004,29 @@ void writeTypeString(String str) throws IOException { } } - /** - * Verifies that this (possibly subclass) instance can be constructed - * without violating security constraints: the subclass must not override - * security-sensitive non-final methods, or else the - * "enableSubclassImplementation" SerializablePermission is checked. - */ - private void verifySubclass() { - Class cl = getClass(); - if (cl == ObjectOutputStream.class) { - return; - } - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - boolean result = Caches.subclassAudits.get(cl); - if (!result) { - sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); - } - } - /** * Performs reflective checks on given subclass to verify that it doesn't * override security-sensitive non-final methods. Returns TRUE if subclass * is "safe", FALSE otherwise. */ - @SuppressWarnings("removal") private static Boolean auditSubclass(Class subcl) { - return AccessController.doPrivileged( - new PrivilegedAction<>() { - public Boolean run() { - for (Class cl = subcl; - cl != ObjectOutputStream.class; - cl = cl.getSuperclass()) - { - try { - cl.getDeclaredMethod( - "writeUnshared", new Class[] { Object.class }); - return Boolean.FALSE; - } catch (NoSuchMethodException ex) { - } - try { - cl.getDeclaredMethod("putFields", (Class[]) null); - return Boolean.FALSE; - } catch (NoSuchMethodException ex) { - } - } - return Boolean.TRUE; - } + for (Class cl = subcl; + cl != ObjectOutputStream.class; + cl = cl.getSuperclass()) + { + try { + cl.getDeclaredMethod( + "writeUnshared", new Class[] { Object.class }); + return Boolean.FALSE; + } catch (NoSuchMethodException ex) { } - ); + try { + cl.getDeclaredMethod("putFields", (Class[]) null); + return Boolean.FALSE; + } catch (NoSuchMethodException ex) { + } + } + return Boolean.TRUE; } /** diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index 73bb162e843..4fb9847a4e8 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,21 +32,12 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.RecordComponent; -import java.lang.reflect.UndeclaredThrowableException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; -import java.security.AccessControlContext; -import java.security.AccessController; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.PermissionCollection; -import java.security.Permissions; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -58,13 +49,8 @@ import jdk.internal.event.SerializationMisdeclarationEvent; import jdk.internal.misc.Unsafe; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; import jdk.internal.reflect.ReflectionFactory; -import jdk.internal.access.SharedSecrets; -import jdk.internal.access.JavaSecurityAccess; import jdk.internal.util.ByteArray; -import sun.reflect.misc.ReflectUtil; /** * Serialization's descriptor for classes. It contains the name and @@ -98,12 +84,6 @@ public final class ObjectStreamClass implements Serializable { private static final ObjectStreamField[] serialPersistentFields = NO_FIELDS; - /** reflection factory for obtaining serialization constructors */ - @SuppressWarnings("removal") - private static final ReflectionFactory reflFactory = - AccessController.doPrivileged( - new ReflectionFactory.GetReflectionFactoryAction()); - private static class Caches { /** cache mapping local classes -> descriptors */ static final ClassCache localDescs = @@ -206,8 +186,6 @@ InvalidClassException newInvalidClassException() { /** session-cache of record deserialization constructor * (in de-serialized OSC only), or null */ private MethodHandle deserializationCtr; - /** protection domains that need to be checked when calling the constructor */ - private ProtectionDomain[] domains; /** class-defined writeObject method, or null if none */ private Method writeObjectMethod; @@ -280,20 +258,13 @@ public String getName() { * * @return the SUID of the class described by this descriptor */ - @SuppressWarnings("removal") public long getSerialVersionUID() { // REMIND: synchronize instead of relying on volatile? if (suid == null) { if (isRecord) return 0L; - suid = AccessController.doPrivileged( - new PrivilegedAction() { - public Long run() { - return computeDefaultSUID(cl); - } - } - ); + suid = computeDefaultSUID(cl); } return suid.longValue(); } @@ -304,19 +275,11 @@ public Long run() { * * @return the {@code Class} instance that this descriptor represents */ - @SuppressWarnings("removal") - @CallerSensitive public Class forClass() { if (cl == null) { return null; } requireInitialized(); - if (System.getSecurityManager() != null) { - Class caller = Reflection.getCallerClass(); - if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), cl.getClassLoader())) { - ReflectUtil.checkPackageAccess(cl); - } - } return cl; } @@ -369,7 +332,6 @@ static ObjectStreamClass lookup(Class cl, boolean all) { /** * Creates local class descriptor representing given class. */ - @SuppressWarnings("removal") private ObjectStreamClass(final Class cl) { this.cl = cl; name = cl.getName(); @@ -384,53 +346,44 @@ private ObjectStreamClass(final Class cl) { localDesc = this; if (serializable) { - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - if (isEnum) { - suid = 0L; - fields = NO_FIELDS; - return null; - } - if (cl.isArray()) { - fields = NO_FIELDS; - return null; - } - - suid = getDeclaredSUID(cl); - try { - fields = getSerialFields(cl); - computeFieldOffsets(); - } catch (InvalidClassException e) { - serializeEx = deserializeEx = + if (isEnum) { + suid = 0L; + fields = NO_FIELDS; + } else if (cl.isArray()) { + fields = NO_FIELDS; + } else { + suid = getDeclaredSUID(cl); + try { + fields = getSerialFields(cl); + computeFieldOffsets(); + } catch (InvalidClassException e) { + serializeEx = deserializeEx = new ExceptionInfo(e.classname, e.getMessage()); - fields = NO_FIELDS; - } + fields = NO_FIELDS; + } - if (isRecord) { - canonicalCtr = canonicalRecordCtr(cl); - deserializationCtrs = new DeserializationConstructorsCache(); - } else if (externalizable) { - cons = getExternalizableConstructor(cl); - } else { - cons = getSerializableConstructor(cl); - writeObjectMethod = getPrivateMethod(cl, "writeObject", - new Class[] { ObjectOutputStream.class }, + if (isRecord) { + canonicalCtr = canonicalRecordCtr(cl); + deserializationCtrs = new DeserializationConstructorsCache(); + } else if (externalizable) { + cons = getExternalizableConstructor(cl); + } else { + cons = getSerializableConstructor(cl); + writeObjectMethod = getPrivateMethod(cl, "writeObject", + new Class[]{ObjectOutputStream.class}, Void.TYPE); - readObjectMethod = getPrivateMethod(cl, "readObject", - new Class[] { ObjectInputStream.class }, + readObjectMethod = getPrivateMethod(cl, "readObject", + new Class[]{ObjectInputStream.class}, Void.TYPE); - readObjectNoDataMethod = getPrivateMethod( + readObjectNoDataMethod = getPrivateMethod( cl, "readObjectNoData", null, Void.TYPE); - hasWriteObjectData = (writeObjectMethod != null); - } - domains = getProtectionDomains(cons, cl); - writeReplaceMethod = getInheritableMethod( + hasWriteObjectData = (writeObjectMethod != null); + } + writeReplaceMethod = getInheritableMethod( cl, "writeReplace", null, Object.class); - readResolveMethod = getInheritableMethod( + readResolveMethod = getInheritableMethod( cl, "readResolve", null, Object.class); - return null; - } - }); + } } else { suid = 0L; fields = NO_FIELDS; @@ -474,66 +427,6 @@ public Void run() { ObjectStreamClass() { } - /** - * Creates a PermissionDomain that grants no permission. - */ - private ProtectionDomain noPermissionsDomain() { - PermissionCollection perms = new Permissions(); - perms.setReadOnly(); - return new ProtectionDomain(null, perms); - } - - /** - * Aggregate the ProtectionDomains of all the classes that separate - * a concrete class {@code cl} from its ancestor's class declaring - * a constructor {@code cons}. - * - * If {@code cl} is defined by the boot loader, or the constructor - * {@code cons} is declared by {@code cl}, or if there is no security - * manager, then this method does nothing and {@code null} is returned. - * - * @param cons A constructor declared by {@code cl} or one of its - * ancestors. - * @param cl A concrete class, which is either the class declaring - * the constructor {@code cons}, or a serializable subclass - * of that class. - * @return An array of ProtectionDomain representing the set of - * ProtectionDomain that separate the concrete class {@code cl} - * from its ancestor's declaring {@code cons}, or {@code null}. - */ - @SuppressWarnings("removal") - private ProtectionDomain[] getProtectionDomains(Constructor cons, - Class cl) { - ProtectionDomain[] domains = null; - if (cons != null && cl.getClassLoader() != null - && System.getSecurityManager() != null) { - Class cls = cl; - Class fnscl = cons.getDeclaringClass(); - Set pds = null; - while (cls != fnscl) { - ProtectionDomain pd = cls.getProtectionDomain(); - if (pd != null) { - if (pds == null) pds = new HashSet<>(); - pds.add(pd); - } - cls = cls.getSuperclass(); - if (cls == null) { - // that's not supposed to happen - // make a ProtectionDomain with no permission. - // should we throw instead? - if (pds == null) pds = new HashSet<>(); - else pds.clear(); - pds.add(noPermissionsDomain()); - break; - } - } - if (pds != null) { - domains = pds.toArray(new ProtectionDomain[0]); - } - } - return domains; - } - /** * Initializes class descriptor representing a proxy class. */ @@ -564,7 +457,6 @@ void initProxy(Class cl, writeReplaceMethod = localDesc.writeReplaceMethod; readResolveMethod = localDesc.readResolveMethod; deserializeEx = localDesc.deserializeEx; - domains = localDesc.domains; cons = localDesc.cons; } fieldRefl = getReflector(fields, localDesc); @@ -656,7 +548,6 @@ void initNonProxy(ObjectStreamClass model, if (deserializeEx == null) { deserializeEx = localDesc.deserializeEx; } - domains = localDesc.domains; assert cl.isRecord() ? localDesc.cons == null : true; cons = localDesc.cons; } @@ -1013,7 +904,6 @@ boolean hasReadResolveMethod() { * class is non-serializable or if the appropriate no-arg constructor is * inaccessible/unavailable. */ - @SuppressWarnings("removal") Object newInstance() throws InstantiationException, InvocationTargetException, UnsupportedOperationException @@ -1021,35 +911,7 @@ Object newInstance() requireInitialized(); if (cons != null) { try { - if (domains == null || domains.length == 0) { - return cons.newInstance(); - } else { - JavaSecurityAccess jsa = SharedSecrets.getJavaSecurityAccess(); - PrivilegedAction pea = () -> { - try { - return cons.newInstance(); - } catch (InstantiationException - | InvocationTargetException - | IllegalAccessException x) { - throw new UndeclaredThrowableException(x); - } - }; // Can't use PrivilegedExceptionAction with jsa - try { - return jsa.doIntersectionPrivilege(pea, - AccessController.getContext(), - new AccessControlContext(domains)); - } catch (UndeclaredThrowableException x) { - Throwable cause = x.getCause(); - if (cause instanceof InstantiationException ie) - throw ie; - if (cause instanceof InvocationTargetException ite) - throw ite; - if (cause instanceof IllegalAccessException iae) - throw iae; - // not supposed to happen - throw x; - } - } + return cons.newInstance(); } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed throw new InternalError(ex); @@ -1454,7 +1316,7 @@ private static Constructor getExternalizableConstructor(Class cl) { * returned constructor (if any). */ private static Constructor getSerializableConstructor(Class cl) { - return reflFactory.newConstructorForSerialization(cl); + return ReflectionFactory.getReflectionFactory().newConstructorForSerialization(cl); } /** @@ -1462,22 +1324,18 @@ private static Constructor getSerializableConstructor(Class cl) { * the not found ( which should never happen for correctly generated record * classes ). */ - @SuppressWarnings("removal") private static MethodHandle canonicalRecordCtr(Class cls) { assert cls.isRecord() : "Expected record, got: " + cls; - PrivilegedAction pa = () -> { - Class[] paramTypes = Arrays.stream(cls.getRecordComponents()) - .map(RecordComponent::getType) - .toArray(Class[]::new); - try { - Constructor ctr = cls.getDeclaredConstructor(paramTypes); - ctr.setAccessible(true); - return MethodHandles.lookup().unreflectConstructor(ctr); - } catch (IllegalAccessException | NoSuchMethodException e) { - return null; - } - }; - return AccessController.doPrivileged(pa); + Class[] paramTypes = Arrays.stream(cls.getRecordComponents()) + .map(RecordComponent::getType) + .toArray(Class[]::new); + try { + Constructor ctr = cls.getDeclaredConstructor(paramTypes); + ctr.setAccessible(true); + return MethodHandles.lookup().unreflectConstructor(ctr); + } catch (IllegalAccessException | NoSuchMethodException e) { + return null; + } } /** @@ -2358,7 +2216,6 @@ static final class RecordSupport { * and return * {@code Object} */ - @SuppressWarnings("removal") static MethodHandle deserializationCtr(ObjectStreamClass desc) { // check the cached value 1st MethodHandle mh = desc.deserializationCtr; @@ -2367,14 +2224,7 @@ static MethodHandle deserializationCtr(ObjectStreamClass desc) { if (mh != null) return desc.deserializationCtr = mh; // retrieve record components - RecordComponent[] recordComponents; - try { - Class cls = desc.forClass(); - PrivilegedExceptionAction pa = cls::getRecordComponents; - recordComponents = AccessController.doPrivileged(pa); - } catch (PrivilegedActionException e) { - throw new InternalError(e.getCause()); - } + RecordComponent[] recordComponents = desc.forClass().getRecordComponents(); // retrieve the canonical constructor // (T1, T2, ..., Tn):TR diff --git a/src/java.base/share/classes/java/io/ObjectStreamField.java b/src/java.base/share/classes/java/io/ObjectStreamField.java index 75c955440c1..465c29c101c 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamField.java +++ b/src/java.base/share/classes/java/io/ObjectStreamField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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,9 +26,6 @@ package java.io; import java.lang.reflect.Field; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; -import sun.reflect.misc.ReflectUtil; /** * A description of a Serializable field from a Serializable class. An array @@ -161,15 +158,7 @@ public String getName() { * @return a {@code Class} object representing the type of the * serializable field */ - @SuppressWarnings("removal") - @CallerSensitive public Class getType() { - if (System.getSecurityManager() != null) { - Class caller = Reflection.getCallerClass(); - if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), type.getClassLoader())) { - ReflectUtil.checkPackageAccess(type); - } - } return type; } diff --git a/src/java.base/share/classes/java/io/ObjectStreamReflection.java b/src/java.base/share/classes/java/io/ObjectStreamReflection.java new file mode 100644 index 00000000000..35c7019419c --- /dev/null +++ b/src/java.base/share/classes/java/io/ObjectStreamReflection.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +import jdk.internal.access.JavaObjectStreamReflectionAccess; +import jdk.internal.access.SharedSecrets; +import jdk.internal.util.ByteArray; + +/** + * Utilities relating to serialization and deserialization of objects. + */ +final class ObjectStreamReflection { + + // todo: these could be constants + private static final MethodHandle DRO_HANDLE; + private static final MethodHandle DWO_HANDLE; + + static { + try { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType droType = MethodType.methodType(void.class, ObjectStreamClass.class, Object.class, ObjectInputStream.class); + DRO_HANDLE = lookup.findStatic(ObjectStreamReflection.class, "defaultReadObject", droType); + MethodType dwoType = MethodType.methodType(void.class, ObjectStreamClass.class, Object.class, ObjectOutputStream.class); + DWO_HANDLE = lookup.findStatic(ObjectStreamReflection.class, "defaultWriteObject", dwoType); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new InternalError(e); + } + } + + /** + * Populate a serializable object from data acquired from the stream's + * {@link java.io.ObjectInputStream.GetField} object independently of + * the actual {@link ObjectInputStream} implementation which may + * arbitrarily override the {@link ObjectInputStream#readFields()} method + * in order to deserialize using a custom object format. + *

+ * The fields are populated using the mechanism defined in {@link ObjectStreamClass}, + * which requires objects and primitives to each be packed into a separate array + * whose relative field offsets are defined in the {@link ObjectStreamField} + * corresponding to each field. + * Utility methods on the {@code ObjectStreamClass} instance are then used + * to validate and perform the actual field accesses. + * + * @param streamClass the object stream class of the object (must not be {@code null}) + * @param obj the object to deserialize (must not be {@code null}) + * @param ois the object stream (must not be {@code null}) + * @throws IOException if the call to {@link ObjectInputStream#readFields} + * or one of its field accessors throws this exception type + * @throws ClassNotFoundException if the call to {@link ObjectInputStream#readFields} + * or one of its field accessors throws this exception type + */ + private static void defaultReadObject(ObjectStreamClass streamClass, Object obj, ObjectInputStream ois) + throws IOException, ClassNotFoundException { + ObjectInputStream.GetField getField = ois.readFields(); + byte[] bytes = new byte[streamClass.getPrimDataSize()]; + Object[] objs = new Object[streamClass.getNumObjFields()]; + for (ObjectStreamField field : streamClass.getFields(false)) { + int offset = field.getOffset(); + String fieldName = field.getName(); + switch (field.getTypeCode()) { + case 'B' -> bytes[offset] = getField.get(fieldName, (byte) 0); + case 'C' -> ByteArray.setChar(bytes, offset, getField.get(fieldName, (char) 0)); + case 'D' -> ByteArray.setDoubleRaw(bytes, offset, getField.get(fieldName, 0.0)); + case 'F' -> ByteArray.setFloatRaw(bytes, offset, getField.get(fieldName, 0.0f)); + case 'I' -> ByteArray.setInt(bytes, offset, getField.get(fieldName, 0)); + case 'J' -> ByteArray.setLong(bytes, offset, getField.get(fieldName, 0L)); + case 'S' -> ByteArray.setShort(bytes, offset, getField.get(fieldName, (short) 0)); + case 'Z' -> ByteArray.setBoolean(bytes, offset, getField.get(fieldName, false)); + case '[', 'L' -> objs[offset] = getField.get(fieldName, null); + default -> throw new IllegalStateException(); + } + } + streamClass.checkObjFieldValueTypes(obj, objs); + streamClass.setPrimFieldValues(obj, bytes); + streamClass.setObjFieldValues(obj, objs); + } + + /** + * Populate and write a stream's {@link java.io.ObjectOutputStream.PutField} object + * from field data acquired from a serializable object independently of + * the actual {@link ObjectOutputStream} implementation which may + * arbitrarily override the {@link ObjectOutputStream#putFields()} + * and {@link ObjectOutputStream#writeFields()} methods + * in order to deserialize using a custom object format. + *

+ * The fields are accessed using the mechanism defined in {@link ObjectStreamClass}, + * which causes objects and primitives to each be packed into a separate array + * whose relative field offsets are defined in the {@link ObjectStreamField} + * corresponding to each field. + * + * @param streamClass the object stream class of the object (must not be {@code null}) + * @param obj the object to serialize (must not be {@code null}) + * @param oos the object stream (must not be {@code null}) + * @throws IOException if the call to {@link ObjectInputStream#readFields} + * or one of its field accessors throws this exception type + */ + private static void defaultWriteObject(ObjectStreamClass streamClass, Object obj, ObjectOutputStream oos) + throws IOException { + ObjectOutputStream.PutField putField = oos.putFields(); + byte[] bytes = new byte[streamClass.getPrimDataSize()]; + Object[] objs = new Object[streamClass.getNumObjFields()]; + streamClass.getPrimFieldValues(obj, bytes); + streamClass.getObjFieldValues(obj, objs); + for (ObjectStreamField field : streamClass.getFields(false)) { + int offset = field.getOffset(); + String fieldName = field.getName(); + switch (field.getTypeCode()) { + case 'B' -> putField.put(fieldName, bytes[offset]); + case 'C' -> putField.put(fieldName, ByteArray.getChar(bytes, offset)); + case 'D' -> putField.put(fieldName, ByteArray.getDouble(bytes, offset)); + case 'F' -> putField.put(fieldName, ByteArray.getFloat(bytes, offset)); + case 'I' -> putField.put(fieldName, ByteArray.getInt(bytes, offset)); + case 'J' -> putField.put(fieldName, ByteArray.getLong(bytes, offset)); + case 'S' -> putField.put(fieldName, ByteArray.getShort(bytes, offset)); + case 'Z' -> putField.put(fieldName, ByteArray.getBoolean(bytes, offset)); + case '[', 'L' -> putField.put(fieldName, objs[offset]); + default -> throw new IllegalStateException(); + } + } + oos.writeFields(); + } + + static final class Access implements JavaObjectStreamReflectionAccess { + static { + SharedSecrets.setJavaObjectStreamReflectionAccess(new Access()); + } + + public MethodHandle defaultReadObject(Class clazz) { + return handleForClass(DRO_HANDLE, clazz, ObjectInputStream.class); + } + + public MethodHandle defaultWriteObject(Class clazz) { + return handleForClass(DWO_HANDLE, clazz, ObjectOutputStream.class); + } + + private static MethodHandle handleForClass(final MethodHandle handle, final Class clazz, final Class ioClass) { + ObjectStreamClass streamClass = ObjectStreamClass.lookup(clazz); + if (streamClass != null) { + try { + streamClass.checkDefaultSerialize(); + return handle.bindTo(streamClass) + .asType(MethodType.methodType(void.class, clazz, ioClass)); + } catch (InvalidClassException e) { + // ignore and return null + } + } + return null; + } + } +} diff --git a/src/java.base/share/classes/java/io/OutputStreamWriter.java b/src/java.base/share/classes/java/io/OutputStreamWriter.java index cda9fead18e..9a16aa140bc 100644 --- a/src/java.base/share/classes/java/io/OutputStreamWriter.java +++ b/src/java.base/share/classes/java/io/OutputStreamWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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,7 +28,6 @@ import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; -import jdk.internal.misc.InternalLock; import sun.nio.cs.StreamEncoder; /** @@ -75,20 +74,6 @@ public class OutputStreamWriter extends Writer { private final StreamEncoder se; - /** - * Return the lock object for the given writer's stream encoder. - * If the writer type is trusted then an internal lock can be used. If the - * writer type is not trusted then the writer object is the lock. - */ - private static Object lockFor(OutputStreamWriter writer) { - Class clazz = writer.getClass(); - if (clazz == OutputStreamWriter.class || clazz == FileWriter.class) { - return InternalLock.newLockOr(writer); - } else { - return writer; - } - } - /** * Creates an OutputStreamWriter that uses the named charset. * @@ -108,7 +93,7 @@ public OutputStreamWriter(OutputStream out, String charsetName) super(out); if (charsetName == null) throw new NullPointerException("charsetName"); - se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), charsetName); + se = StreamEncoder.forOutputStreamWriter(out, this, charsetName); } /** @@ -122,7 +107,7 @@ public OutputStreamWriter(OutputStream out, String charsetName) @SuppressWarnings("this-escape") public OutputStreamWriter(OutputStream out) { super(out); - se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), + se = StreamEncoder.forOutputStreamWriter(out, this, out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset()); } @@ -142,7 +127,7 @@ public OutputStreamWriter(OutputStream out, Charset cs) { super(out); if (cs == null) throw new NullPointerException("charset"); - se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), cs); + se = StreamEncoder.forOutputStreamWriter(out, this, cs); } /** @@ -161,7 +146,7 @@ public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { super(out); if (enc == null) throw new NullPointerException("charset encoder"); - se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), enc); + se = StreamEncoder.forOutputStreamWriter(out, this, enc); } /** diff --git a/src/java.base/share/classes/java/io/PrintStream.java b/src/java.base/share/classes/java/io/PrintStream.java index 3096f2356f5..0c1dd20e668 100644 --- a/src/java.base/share/classes/java/io/PrintStream.java +++ b/src/java.base/share/classes/java/io/PrintStream.java @@ -30,9 +30,6 @@ import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; -import jdk.internal.access.JavaIOPrintStreamAccess; -import jdk.internal.access.SharedSecrets; -import jdk.internal.misc.InternalLock; /** * A {@code PrintStream} adds functionality to another output stream, @@ -67,9 +64,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, Closeable { - // initialized to null when PrintStream is sub-classed - private final InternalLock lock; - private final boolean autoFlush; private boolean trouble = false; private Formatter formatter; @@ -117,13 +111,6 @@ private PrintStream(boolean autoFlush, OutputStream out) { this.charset = out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset(); this.charOut = new OutputStreamWriter(this, charset); this.textOut = new BufferedWriter(charOut); - - // use monitors when PrintStream is sub-classed - if (getClass() == PrintStream.class) { - lock = InternalLock.newLockOrNull(); - } else { - lock = null; - } } /* Variant of the private constructor so that the given charset name @@ -220,13 +207,6 @@ public PrintStream(OutputStream out, boolean autoFlush, Charset charset) { this.charOut = new OutputStreamWriter(this, charset); this.textOut = new BufferedWriter(charOut); this.charset = charset; - - // use monitors when PrintStream is sub-classed - if (getClass() == PrintStream.class) { - lock = InternalLock.newLockOrNull(); - } else { - lock = null; - } } /** @@ -420,30 +400,17 @@ private void ensureOpen() throws IOException { */ @Override public void flush() { - if (lock != null) { - lock.lock(); + synchronized (this) { try { - implFlush(); - } finally { - lock.unlock(); + ensureOpen(); + out.flush(); } - } else { - synchronized (this) { - implFlush(); + catch (IOException x) { + trouble = true; } } } - private void implFlush() { - try { - ensureOpen(); - out.flush(); - } - catch (IOException x) { - trouble = true; - } - } - private boolean closing = false; /* To avoid recursive closing */ /** @@ -454,33 +421,20 @@ private void implFlush() { */ @Override public void close() { - if (lock != null) { - lock.lock(); - try { - implClose(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implClose(); - } - } - } - - private void implClose() { - if (!closing) { - closing = true; - try { - textOut.close(); - out.close(); - } - catch (IOException x) { - trouble = true; + synchronized (this) { + if (!closing) { + closing = true; + try { + textOut.close(); + out.close(); + } + catch (IOException x) { + trouble = true; + } + textOut = null; + charOut = null; + out = null; } - textOut = null; - charOut = null; - out = null; } } @@ -547,17 +501,11 @@ protected void clearError() { @Override public void write(int b) { try { - if (lock != null) { - lock.lock(); - try { - implWrite(b); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(b); - } + synchronized (this) { + ensureOpen(); + out.write(b); + if ((b == '\n') && autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -568,13 +516,6 @@ public void write(int b) { } } - private void implWrite(int b) throws IOException { - ensureOpen(); - out.write(b); - if ((b == '\n') && autoFlush) - out.flush(); - } - /** * Writes {@code len} bytes from the specified byte array starting at * offset {@code off} to this stream. If automatic flushing is @@ -593,17 +534,11 @@ private void implWrite(int b) throws IOException { @Override public void write(byte[] buf, int off, int len) { try { - if (lock != null) { - lock.lock(); - try { - implWrite(buf, off, len); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(buf, off, len); - } + synchronized (this) { + ensureOpen(); + out.write(buf, off, len); + if (autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -614,14 +549,6 @@ public void write(byte[] buf, int off, int len) { } } - private void implWrite(byte[] buf, int off, int len) throws IOException { - ensureOpen(); - out.write(buf, off, len); - if (autoFlush) - out.flush(); - } - - /** * Writes all bytes from the specified byte array to this stream. If * automatic flushing is enabled then the {@code flush} method will be @@ -686,16 +613,17 @@ public void writeBytes(byte[] buf) { private void write(char[] buf) { try { - if (lock != null) { - lock.lock(); - try { - implWrite(buf); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(buf); + synchronized (this) { + ensureOpen(); + textOut.write(buf); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush) { + for (int i = 0; i < buf.length; i++) + if (buf[i] == '\n') { + out.flush(); + break; + } } } } catch (InterruptedIOException x) { @@ -705,37 +633,20 @@ private void write(char[] buf) { } } - private void implWrite(char[] buf) throws IOException { - ensureOpen(); - textOut.write(buf); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush) { - for (int i = 0; i < buf.length; i++) - if (buf[i] == '\n') { - out.flush(); - break; - } - } - } - // Used to optimize away back-to-back flushing and synchronization when // using println, but since subclasses could exist which depend on // observing a call to print followed by newLine() we only use this if // getClass() == PrintStream.class to avoid compatibility issues. private void writeln(char[] buf) { try { - if (lock != null) { - lock.lock(); - try { - implWriteln(buf); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWriteln(buf); - } + synchronized (this) { + ensureOpen(); + textOut.write(buf); + textOut.newLine(); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -746,29 +657,15 @@ private void writeln(char[] buf) { } } - private void implWriteln(char[] buf) throws IOException { - ensureOpen(); - textOut.write(buf); - textOut.newLine(); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush) - out.flush(); - } - private void write(String s) { try { - if (lock != null) { - lock.lock(); - try { - implWrite(s); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(s); - } + synchronized (this) { + ensureOpen(); + textOut.write(s); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush && (s.indexOf('\n') >= 0)) + out.flush(); } } catch (InterruptedIOException x) { @@ -779,32 +676,20 @@ private void write(String s) { } } - private void implWrite(String s) throws IOException { - ensureOpen(); - textOut.write(s); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush && (s.indexOf('\n') >= 0)) - out.flush(); - } - // Used to optimize away back-to-back flushing and synchronization when // using println, but since subclasses could exist which depend on // observing a call to print followed by newLine we only use this if // getClass() == PrintStream.class to avoid compatibility issues. private void writeln(String s) { try { - if (lock != null) { - lock.lock(); - try { - implWriteln(s); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWriteln(s); - } + synchronized (this) { + ensureOpen(); + textOut.write(s); + textOut.newLine(); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -815,29 +700,15 @@ private void writeln(String s) { } } - private void implWriteln(String s) throws IOException { - ensureOpen(); - textOut.write(s); - textOut.newLine(); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush) - out.flush(); - } - private void newLine() { try { - if (lock != null) { - lock.lock(); - try { - implNewLine(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implNewLine(); - } + synchronized (this) { + ensureOpen(); + textOut.newLine(); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -848,15 +719,6 @@ private void newLine() { } } - private void implNewLine() throws IOException { - ensureOpen(); - textOut.newLine(); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush) - out.flush(); - } - /* Methods that do not terminate lines */ /** @@ -1314,17 +1176,11 @@ public PrintStream printf(Locale l, String format, Object ... args) { */ public PrintStream format(String format, Object ... args) { try { - if (lock != null) { - lock.lock(); - try { - implFormat(format, args); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implFormat(format, args); - } + synchronized (this) { + ensureOpen(); + if ((formatter == null) || (formatter.locale() != Locale.getDefault(Locale.Category.FORMAT))) + formatter = new Formatter((Appendable) this); + formatter.format(Locale.getDefault(Locale.Category.FORMAT), format, args); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); @@ -1334,13 +1190,6 @@ public PrintStream format(String format, Object ... args) { return this; } - private void implFormat(String format, Object ... args) throws IOException { - ensureOpen(); - if ((formatter == null) || (formatter.locale() != Locale.getDefault(Locale.Category.FORMAT))) - formatter = new Formatter((Appendable) this); - formatter.format(Locale.getDefault(Locale.Category.FORMAT), format, args); - } - /** * Writes a formatted string to this output stream using the specified * format string and arguments. @@ -1383,17 +1232,11 @@ private void implFormat(String format, Object ... args) throws IOException { */ public PrintStream format(Locale l, String format, Object ... args) { try { - if (lock != null) { - lock.lock(); - try { - implFormat(l, format, args); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implFormat(l, format, args); - } + synchronized (this) { + ensureOpen(); + if ((formatter == null) || (formatter.locale() != l)) + formatter = new Formatter(this, l); + formatter.format(l, format, args); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); @@ -1403,13 +1246,6 @@ public PrintStream format(Locale l, String format, Object ... args) { return this; } - private void implFormat(Locale l, String format, Object ... args) throws IOException { - ensureOpen(); - if ((formatter == null) || (formatter.locale() != l)) - formatter = new Formatter(this, l); - formatter.format(l, format, args); - } - /** * Appends the specified character sequence to this output stream. * @@ -1511,13 +1347,4 @@ public PrintStream append(char c) { public Charset charset() { return charset; } - - static { - SharedSecrets.setJavaIOCPrintStreamAccess(new JavaIOPrintStreamAccess() { - public Object lock(PrintStream ps) { - Object lock = ps.lock; - return (lock != null) ? lock : ps; - } - }); - } } diff --git a/src/java.base/share/classes/java/io/PrintWriter.java b/src/java.base/share/classes/java/io/PrintWriter.java index 55baa2e0a57..dd6deb75ab7 100644 --- a/src/java.base/share/classes/java/io/PrintWriter.java +++ b/src/java.base/share/classes/java/io/PrintWriter.java @@ -31,9 +31,6 @@ import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; -import jdk.internal.access.JavaIOPrintWriterAccess; -import jdk.internal.access.SharedSecrets; -import jdk.internal.misc.InternalLock; /** * Prints formatted representations of objects to a text-output stream. This @@ -377,30 +374,16 @@ private void ensureOpen() throws IOException { * @see #checkError() */ public void flush() { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implFlush(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFlush(); + ensureOpen(); + out.flush(); + } catch (IOException x) { + trouble = true; } } } - private void implFlush() { - try { - ensureOpen(); - out.flush(); - } catch (IOException x) { - trouble = true; - } - } - /** * Closes the stream and releases any system resources associated * with it. Closing a previously closed stream has no effect. @@ -408,32 +391,18 @@ private void implFlush() { * @see #checkError() */ public void close() { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implClose(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implClose(); + if (out != null) { + out.close(); + out = null; + } + } catch (IOException x) { + trouble = true; } } } - private void implClose() { - try { - if (out != null) { - out.close(); - out = null; - } - } catch (IOException x) { - trouble = true; - } - } - /** * Flushes the stream if it's not closed and checks its error state. * @@ -487,32 +456,18 @@ protected void clearError() { * @param c int specifying a character to be written. */ public void write(int c) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implWrite(c); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(c); + ensureOpen(); + out.write(c); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } } } - private void implWrite(int c) { - try { - ensureOpen(); - out.write(c); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; - } - } - /** * Writes A Portion of an array of characters. * @param buf Array of characters @@ -525,29 +480,15 @@ private void implWrite(int c) { * to throw an {@code IndexOutOfBoundsException} */ public void write(char[] buf, int off, int len) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implWrite(buf, off, len); - } finally { - locker.unlock(); + ensureOpen(); + out.write(buf, off, len); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } - } else { - synchronized (lock) { - implWrite(buf, off, len); - } - } - } - - private void implWrite(char[] buf, int off, int len) { - try { - ensureOpen(); - out.write(buf, off, len); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; } } @@ -572,29 +513,15 @@ public void write(char[] buf) { * to throw an {@code IndexOutOfBoundsException} */ public void write(String s, int off, int len) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implWrite(s, off, len); - } finally { - locker.unlock(); + ensureOpen(); + out.write(s, off, len); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } - } else { - synchronized (lock) { - implWrite(s, off, len); - } - } - } - - private void implWrite(String s, int off, int len) { - try { - ensureOpen(); - out.write(s, off, len); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; } } @@ -608,34 +535,20 @@ public void write(String s) { } private void newLine() { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implNewLine(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implNewLine(); + ensureOpen(); + out.write(System.lineSeparator()); + if (autoFlush) + out.flush(); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } } } - private void implNewLine() { - try { - ensureOpen(); - out.write(System.lineSeparator()); - if (autoFlush) - out.flush(); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; - } - } - /* Methods that do not terminate lines */ /** @@ -788,20 +701,9 @@ public void println() { * @param x the {@code boolean} value to be printed */ public void println(boolean x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -813,20 +715,9 @@ public void println(boolean x) { * @param x the {@code char} value to be printed */ public void println(char x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -838,20 +729,9 @@ public void println(char x) { * @param x the {@code int} value to be printed */ public void println(int x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -863,20 +743,9 @@ public void println(int x) { * @param x the {@code long} value to be printed */ public void println(long x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -888,20 +757,9 @@ public void println(long x) { * @param x the {@code float} value to be printed */ public void println(float x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -913,20 +771,9 @@ public void println(float x) { * @param x the {@code double} value to be printed */ public void println(double x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -938,20 +785,9 @@ public void println(double x) { * @param x the array of {@code char} values to be printed */ public void println(char[] x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -963,20 +799,9 @@ public void println(char[] x) { * @param x the {@code String} value to be printed */ public void println(String x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -991,20 +816,9 @@ public void println(String x) { */ public void println(Object x) { String s = String.valueOf(x); - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(s); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(s); - println(); - } + synchronized (lock) { + print(s); + println(); } } @@ -1150,38 +964,24 @@ public PrintWriter printf(Locale l, String format, Object ... args) { * @since 1.5 */ public PrintWriter format(String format, Object ... args) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implFormat(format, args); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFormat(format, args); + ensureOpen(); + if ((formatter == null) + || (formatter.locale() != Locale.getDefault())) + formatter = new Formatter(this); + formatter.format(Locale.getDefault(), format, args); + if (autoFlush) + out.flush(); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } } return this; } - private void implFormat(String format, Object ... args) { - try { - ensureOpen(); - if ((formatter == null) - || (formatter.locale() != Locale.getDefault())) - formatter = new Formatter(this); - formatter.format(Locale.getDefault(), format, args); - if (autoFlush) - out.flush(); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; - } - } - /** * Writes a formatted string to this writer using the specified format * string and arguments. If automatic flushing is enabled, calls to this @@ -1224,37 +1024,23 @@ private void implFormat(String format, Object ... args) { * @since 1.5 */ public PrintWriter format(Locale l, String format, Object ... args) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implFormat(l, format, args); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFormat(l, format, args); + ensureOpen(); + if ((formatter == null) || (formatter.locale() != l)) + formatter = new Formatter(this, l); + formatter.format(l, format, args); + if (autoFlush) + out.flush(); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } } return this; } - private void implFormat(Locale l, String format, Object ... args) { - try { - ensureOpen(); - if ((formatter == null) || (formatter.locale() != l)) - formatter = new Formatter(this, l); - formatter.format(l, format, args); - if (autoFlush) - out.flush(); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; - } - } - /** * Appends the specified character sequence to this writer. * @@ -1346,12 +1132,4 @@ public PrintWriter append(char c) { write(c); return this; } - - static { - SharedSecrets.setJavaIOCPrintWriterAccess(new JavaIOPrintWriterAccess() { - public Object lock(PrintWriter pw) { - return pw.lock; - } - }); - } } diff --git a/src/java.base/share/classes/java/io/ProxyingConsole.java b/src/java.base/share/classes/java/io/ProxyingConsole.java index 1babceb665f..cc5cd926264 100644 --- a/src/java.base/share/classes/java/io/ProxyingConsole.java +++ b/src/java.base/share/classes/java/io/ProxyingConsole.java @@ -117,6 +117,18 @@ public String readln(String prompt) { } } + /** + * {@inheritDoc} + * + * @throws IOError {@inheritDoc} + */ + @Override + public String readln() { + synchronized (readLock) { + return delegate.readln(); + } + } + /** * {@inheritDoc} */ diff --git a/src/java.base/share/classes/java/io/PushbackInputStream.java b/src/java.base/share/classes/java/io/PushbackInputStream.java index 0c74205ba0e..5aa0e133df9 100644 --- a/src/java.base/share/classes/java/io/PushbackInputStream.java +++ b/src/java.base/share/classes/java/io/PushbackInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -27,7 +27,6 @@ import java.util.Arrays; import java.util.Objects; -import jdk.internal.misc.InternalLock; /** * A {@code PushbackInputStream} adds @@ -54,10 +53,6 @@ * @since 1.0 */ public class PushbackInputStream extends FilterInputStream { - - // initialized to null when PushbackInputStream is sub-classed - private final InternalLock closeLock; - /** * The pushback buffer. * @since 1.1 @@ -101,13 +96,6 @@ public PushbackInputStream(InputStream in, int size) { } this.buf = new byte[size]; this.pos = size; - - // use monitors when PushbackInputStream is sub-classed - if (getClass() == PushbackInputStream.class) { - closeLock = InternalLock.newLockOrNull(); - } else { - closeLock = null; - } } /** @@ -386,27 +374,12 @@ public void reset() throws IOException { * * @throws IOException if an I/O error occurs. */ - public void close() throws IOException { - if (closeLock != null) { - closeLock.lock(); - try { - implClose(); - } finally { - closeLock.unlock(); - } - } else { - synchronized (this) { - implClose(); - } - } - } - - private void implClose() throws IOException { - if (in != null) { - in.close(); - in = null; - buf = null; - } + public synchronized void close() throws IOException { + if (in == null) + return; + in.close(); + in = null; + buf = null; } @Override diff --git a/src/java.base/share/classes/java/io/RandomAccessFile.java b/src/java.base/share/classes/java/io/RandomAccessFile.java index 1487764ac44..c09f87afcdc 100644 --- a/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -245,14 +245,6 @@ else if (mode.startsWith("rw")) { + "\" must be one of " + "\"r\", \"rw\", \"rws\"," + " or \"rwd\""); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(name); - if (rw) { - security.checkWrite(name); - } - } if (name == null) { throw new NullPointerException(); } diff --git a/src/java.base/share/classes/java/io/Reader.java b/src/java.base/share/classes/java/io/Reader.java index 9fca28a3a96..1654156bee1 100644 --- a/src/java.base/share/classes/java/io/Reader.java +++ b/src/java.base/share/classes/java/io/Reader.java @@ -28,7 +28,6 @@ import java.nio.CharBuffer; import java.nio.ReadOnlyBufferException; import java.util.Objects; -import jdk.internal.misc.InternalLock; /** * Abstract class for reading character streams. The only methods that a @@ -283,21 +282,6 @@ protected Reader(Object lock) { this.lock = lock; } - /** - * For use by BufferedReader to create a character-stream reader that uses an - * internal lock when BufferedReader is not extended and the given reader is - * trusted, otherwise critical sections will synchronize on the given reader. - */ - Reader(Reader in) { - Class clazz = in.getClass(); - if (getClass() == BufferedReader.class && - (clazz == InputStreamReader.class || clazz == FileReader.class)) { - this.lock = InternalLock.newLockOr(in); - } else { - this.lock = in; - } - } - /** * Attempts to read characters into the specified character buffer. * The buffer is used as a repository of characters as-is: the only @@ -429,33 +413,19 @@ public int read(char[] cbuf) throws IOException { public long skip(long n) throws IOException { if (n < 0L) throw new IllegalArgumentException("skip value is negative"); - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implSkip(n); - } finally { - locker.unlock(); + synchronized (lock) { + int nn = (int) Math.min(n, maxSkipBufferSize); + if ((skipBuffer == null) || (skipBuffer.length < nn)) + skipBuffer = new char[nn]; + long r = n; + while (r > 0) { + int nc = read(skipBuffer, 0, (int)Math.min(r, nn)); + if (nc == -1) + break; + r -= nc; } - } else { - synchronized (lock) { - return implSkip(n); - } - } - } - - private long implSkip(long n) throws IOException { - int nn = (int) Math.min(n, maxSkipBufferSize); - if ((skipBuffer == null) || (skipBuffer.length < nn)) - skipBuffer = new char[nn]; - long r = n; - while (r > 0) { - int nc = read(skipBuffer, 0, (int)Math.min(r, nn)); - if (nc == -1) - break; - r -= nc; + return n - r; } - return n - r; } /** diff --git a/src/java.base/share/classes/java/io/SerializablePermission.java b/src/java.base/share/classes/java/io/SerializablePermission.java index 1e617e173a7..48be2eabf1f 100644 --- a/src/java.base/share/classes/java/io/SerializablePermission.java +++ b/src/java.base/share/classes/java/io/SerializablePermission.java @@ -25,7 +25,7 @@ package java.io; -import java.security.*; +import java.security.BasicPermission; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; @@ -44,7 +44,6 @@ * @see java.security.Permission * @see java.security.Permissions * @see java.security.PermissionCollection - * @see java.lang.SecurityManager * * @author Joe Fialli * @since 1.2 diff --git a/src/java.base/share/classes/java/io/SerializationMisdeclarationChecker.java b/src/java.base/share/classes/java/io/SerializationMisdeclarationChecker.java index 5eae83e80f7..5a9a6f02ab4 100644 --- a/src/java.base/share/classes/java/io/SerializationMisdeclarationChecker.java +++ b/src/java.base/share/classes/java/io/SerializationMisdeclarationChecker.java @@ -29,8 +29,6 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Arrays; import static jdk.internal.event.SerializationMisdeclarationEvent.*; @@ -75,7 +73,7 @@ static void checkMisdeclarations(Class cl) { } private static void checkSerialVersionUID(Class cl) { - Field f = privilegedDeclaredField(cl, SUID_NAME); + Field f = declaredField(cl, SUID_NAME); if (f == null) { if (isOrdinaryClass(cl)) { commitEvent(cl, SUID_NAME + " should be declared explicitly" + @@ -101,7 +99,7 @@ private static void checkSerialVersionUID(Class cl) { } private static void checkSerialPersistentFields(Class cl) { - Field f = privilegedDeclaredField(cl, SERIAL_PERSISTENT_FIELDS_NAME); + Field f = declaredField(cl, SERIAL_PERSISTENT_FIELDS_NAME); if (f == null) { return; } @@ -142,7 +140,7 @@ private static void checkSerialPersistentFields(Class cl) { private static void checkPrivateMethod(Class cl, String name, Class[] paramTypes, Class retType) { - for (Method m : privilegedDeclaredMethods(cl)) { + for (Method m : cl.getDeclaredMethods()) { if (m.getName().equals(name)) { checkPrivateMethod(cl, m, paramTypes, retType); } @@ -173,7 +171,7 @@ private static void checkPrivateMethod(Class cl, private static void checkAccessibleMethod(Class cl, String name, Class[] paramTypes, Class retType) { for (Class superCl = cl; superCl != null; superCl = superCl.getSuperclass()) { - for (Method m : privilegedDeclaredMethods(superCl)) { + for (Method m : superCl.getDeclaredMethods()) { if (m.getName().equals(name)) { checkAccessibleMethod(cl, superCl, m, paramTypes, retType); } @@ -236,14 +234,6 @@ private static boolean isStatic(Member m) { return (m.getModifiers() & STATIC) != 0; } - @SuppressWarnings("removal") - private static Field privilegedDeclaredField(Class cl, String name) { - if (System.getSecurityManager() == null) { - return declaredField(cl, name); - } - return AccessController.doPrivileged((PrivilegedAction) () -> - declaredField(cl, name)); - } private static Field declaredField(Class cl, String name) { try { @@ -253,14 +243,6 @@ private static Field declaredField(Class cl, String name) { return null; } - @SuppressWarnings("removal") - private static Method[] privilegedDeclaredMethods(Class cl) { - if (System.getSecurityManager() == null) { - return cl.getDeclaredMethods(); - } - return AccessController.doPrivileged( - (PrivilegedAction) cl::getDeclaredMethods); - } private static Object objectFromStatic(Field f) { try { diff --git a/src/java.base/share/classes/java/io/Writer.java b/src/java.base/share/classes/java/io/Writer.java index 62fe6b053e5..433a116a4bb 100644 --- a/src/java.base/share/classes/java/io/Writer.java +++ b/src/java.base/share/classes/java/io/Writer.java @@ -26,7 +26,6 @@ package java.io; import java.util.Objects; -import jdk.internal.misc.InternalLock; /** * Abstract class for writing to character streams. The only methods that a @@ -162,21 +161,6 @@ protected Writer() { this.lock = this; } - /** - * For use by BufferedWriter to create a character-stream writer that uses an - * internal lock when BufferedWriter is not extended and the given writer is - * trusted, otherwise critical sections will synchronize on the given writer. - */ - Writer(Writer writer) { - Class clazz = writer.getClass(); - if (getClass() == BufferedWriter.class && - (clazz == OutputStreamWriter.class || clazz == FileWriter.class)) { - this.lock = InternalLock.newLockOr(writer); - } else { - this.lock = writer; - } - } - /** * Creates a new character-stream writer whose critical sections will * synchronize on the given object. @@ -206,29 +190,15 @@ protected Writer(Object lock) { * If an I/O error occurs */ public void write(int c) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(c); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(c); + synchronized (lock) { + if (writeBuffer == null){ + writeBuffer = new char[WRITE_BUFFER_SIZE]; } + writeBuffer[0] = (char) c; + write(writeBuffer, 0, 1); } } - private void implWrite(int c) throws IOException { - if (writeBuffer == null){ - writeBuffer = new char[WRITE_BUFFER_SIZE]; - } - writeBuffer[0] = (char) c; - write(writeBuffer, 0, 1); - } - /** * Writes an array of characters. * @@ -305,33 +275,19 @@ public void write(String str) throws IOException { * If an I/O error occurs */ public void write(String str, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(str, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(str, off, len); - } - } - } - - private void implWrite(String str, int off, int len) throws IOException { - char cbuf[]; - if (len <= WRITE_BUFFER_SIZE) { - if (writeBuffer == null) { - writeBuffer = new char[WRITE_BUFFER_SIZE]; + synchronized (lock) { + char cbuf[]; + if (len <= WRITE_BUFFER_SIZE) { + if (writeBuffer == null) { + writeBuffer = new char[WRITE_BUFFER_SIZE]; + } + cbuf = writeBuffer; + } else { // Don't permanently allocate very large buffers. + cbuf = new char[len]; } - cbuf = writeBuffer; - } else { // Don't permanently allocate very large buffers. - cbuf = new char[len]; + str.getChars(off, (off + len), cbuf, 0); + write(cbuf, 0, len); } - str.getChars(off, (off + len), cbuf, 0); - write(cbuf, 0, len); } /** diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index bb091235646..771084384c8 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -30,7 +30,6 @@ import java.lang.constant.ConstantDescs; import java.lang.invoke.TypeDescriptor; import java.lang.invoke.MethodHandles; -import java.lang.module.ModuleReader; import java.lang.ref.SoftReference; import java.io.IOException; import java.io.InputStream; @@ -54,9 +53,7 @@ import java.lang.reflect.TypeVariable; import java.lang.constant.Constable; import java.net.URL; -import java.security.AccessController; import java.security.Permissions; -import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; @@ -73,10 +70,8 @@ import java.util.stream.Collectors; import jdk.internal.constant.ConstantUtils; -import jdk.internal.javac.PreviewFeature; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; -import jdk.internal.misc.PreviewFeatures; import jdk.internal.misc.Unsafe; import jdk.internal.module.Resources; import jdk.internal.reflect.CallerSensitive; @@ -84,7 +79,6 @@ import jdk.internal.reflect.ConstantPool; import jdk.internal.reflect.Reflection; import jdk.internal.reflect.ReflectionFactory; -import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.Stable; @@ -231,6 +225,11 @@ public final class Class implements java.io.Serializable, private static native void registerNatives(); static { + runtimeSetup(); + } + + // Called from JVM when loading an AOT cache + private static void runtimeSetup() { registerNatives(); } @@ -540,41 +539,10 @@ private static Class forName(String className, Class caller) * @jls 13.1 The Form of a Binary * @since 1.2 */ - @CallerSensitive - public static Class forName(String name, boolean initialize, - ClassLoader loader) + public static Class forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException { - Class caller = null; - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // Reflective call to get caller class is only needed if a security manager - // is present. Avoid the overhead of making this call otherwise. - caller = Reflection.getCallerClass(); - } - return forName(name, initialize, loader, caller); - } - - // Caller-sensitive adapter method for reflective invocation - @CallerSensitiveAdapter - private static Class forName(String name, boolean initialize, ClassLoader loader, Class caller) - throws ClassNotFoundException - { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // Reflective call to get caller class is only needed if a security manager - // is present. Avoid the overhead of making this call otherwise. - if (loader == null) { - ClassLoader ccl = ClassLoader.getClassLoader(caller); - if (ccl != null) { - sm.checkPermission( - SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - } - } - return forName0(name, initialize, loader, caller); + return forName0(name, initialize, loader, null); } /** Called after security check for system loader access checks have been made. */ @@ -620,38 +588,11 @@ private static native Class forName0(String name, boolean initialize, * @jls 12.3 Linking of Classes and Interfaces * @since 9 */ - @SuppressWarnings("removal") - @CallerSensitive public static Class forName(Module module, String name) { - Class caller = null; - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - caller = Reflection.getCallerClass(); - } - return forName(module, name, caller); - } - - // Caller-sensitive adapter method for reflective invocation - @SuppressWarnings("removal") - @CallerSensitiveAdapter - private static Class forName(Module module, String name, Class caller) { Objects.requireNonNull(module); Objects.requireNonNull(name); - ClassLoader cl; - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (caller != null && caller.getModule() != module) { - // if caller is null, Class.forName is the last java frame on the stack. - // java.base has all permissions - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - PrivilegedAction pa = module::getClassLoader; - cl = AccessController.doPrivileged(pa); - } else { - cl = module.getClassLoader(); - } - + ClassLoader cl = module.getClassLoader(); if (cl != null) { return cl.loadClass(module, name); } else { @@ -740,17 +681,11 @@ public static Class forPrimitiveName(String primitiveName) { * @throws ExceptionInInitializerError if the initialization * provoked by this method fails. */ - @SuppressWarnings("removal") @CallerSensitive @Deprecated(since="9") public T newInstance() throws InstantiationException, IllegalAccessException { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false); - } - // Constructor lookup Constructor tmpConstructor = cachedConstructor; if (tmpConstructor == null) { @@ -765,13 +700,7 @@ public T newInstance() getConstructor0(empty, Member.DECLARED)); // Disable accessibility checks on the constructor // access check is done with the true caller - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public Void run() { - c.setAccessible(true); - return null; - } - }); + c.setAccessible(true); cachedConstructor = tmpConstructor = c; } catch (NoSuchMethodException e) { throw (InstantiationException) @@ -1035,18 +964,8 @@ public String getName() { * represented by this {@code Class} object. * @see java.lang.ClassLoader */ - @CallerSensitive - @ForceInline // to ensure Reflection.getCallerClass optimization public ClassLoader getClassLoader() { - ClassLoader cl = classLoader; - if (cl == null) - return null; - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); - } - return cl; + return classLoader; } // Package-private to allow ClassLoader access @@ -1511,7 +1430,6 @@ void setSigners(Object[] signers) { * * @since 1.5 */ - @CallerSensitive public Method getEnclosingMethod() { EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); @@ -1533,14 +1451,7 @@ public Method getEnclosingMethod() { for(int i = 0; i < parameterClasses.length; i++) parameterClasses[i] = toClass(parameterTypes[i]); - // Perform access check final Class enclosingCandidate = enclosingInfo.getEnclosingClass(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - enclosingCandidate.checkMemberAccess(sm, Member.DECLARED, - Reflection.getCallerClass(), true); - } Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false); /* @@ -1648,7 +1559,6 @@ private static Class toClass(Type o) { * * @since 1.5 */ - @CallerSensitive public Constructor getEnclosingConstructor() { EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); @@ -1666,18 +1576,11 @@ public Constructor getEnclosingConstructor() { // Convert Types to Classes; returned types *should* // be class objects since the methodDescriptor's used // don't have generics information - for(int i = 0; i < parameterClasses.length; i++) + for (int i = 0; i < parameterClasses.length; i++) parameterClasses[i] = toClass(parameterTypes[i]); - // Perform access check - final Class enclosingCandidate = enclosingInfo.getEnclosingClass(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - enclosingCandidate.checkMemberAccess(sm, Member.DECLARED, - Reflection.getCallerClass(), true); - } + final Class enclosingCandidate = enclosingInfo.getEnclosingClass(); Constructor[] candidates = enclosingCandidate .privateGetDeclaredConstructors(false); /* @@ -1708,19 +1611,8 @@ public Constructor getEnclosingConstructor() { * @return the declaring class for this class * @since 1.1 */ - @CallerSensitive public Class getDeclaringClass() { - final Class candidate = getDeclaringClass0(); - - if (candidate != null) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - candidate.checkPackageAccess(sm, - ClassLoader.getClassLoader(Reflection.getCallerClass()), true); - } - } - return candidate; + return getDeclaringClass0(); } private native Class getDeclaringClass0(); @@ -1733,7 +1625,6 @@ public Class getDeclaringClass() { * @return the immediately enclosing class of the underlying class * @since 1.5 */ - @CallerSensitive public Class getEnclosingClass() { // There are five kinds of classes (or interfaces): // a) Top level classes @@ -1760,15 +1651,6 @@ public Class getEnclosingClass() { else enclosingCandidate = enclosingClass; } - - if (enclosingCandidate != null) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - enclosingCandidate.checkPackageAccess(sm, - ClassLoader.getClassLoader(Reflection.getCallerClass()), true); - } - } return enclosingCandidate; } @@ -1991,36 +1873,18 @@ private boolean hasEnclosingMethodInfo() { * members of this class * @since 1.1 */ - @SuppressWarnings("removal") - @CallerSensitive public Class[] getClasses() { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false); - } - - // Privileged so this implementation can look at DECLARED classes, - // something the caller might not have privilege to do. The code here - // is allowed to look at DECLARED classes because (1) it does not hand - // out anything other than public members and (2) public member access - // has already been ok'd by the SecurityManager. - - return java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public Class[] run() { - List> list = new ArrayList<>(); - Class currentClass = Class.this; - while (currentClass != null) { - for (Class m : currentClass.getDeclaredClasses()) { - if (Modifier.isPublic(m.getModifiers())) { - list.add(m); - } - } - currentClass = currentClass.getSuperclass(); - } - return list.toArray(new Class[0]); + List> list = new ArrayList<>(); + Class currentClass = Class.this; + while (currentClass != null) { + for (Class m : currentClass.getDeclaredClasses()) { + if (Modifier.isPublic(m.getModifiers())) { + list.add(m); } - }); + } + currentClass = currentClass.getSuperclass(); + } + return list.toArray(new Class[0]); } @@ -2054,13 +1918,7 @@ public Class[] run() { * @jls 8.2 Class Members * @jls 8.3 Field Declarations */ - @CallerSensitive public Field[] getFields() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); - } return copyFields(privateGetPublicFields()); } @@ -2138,13 +1996,7 @@ public Field[] getFields() { * @jls 8.4 Method Declarations * @since 1.1 */ - @CallerSensitive public Method[] getMethods() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); - } return copyMethods(privateGetPublicMethods()); } @@ -2173,13 +2025,7 @@ public Method[] getMethods() { * @see #getDeclaredConstructors() * @since 1.1 */ - @CallerSensitive public Constructor[] getConstructors() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); - } return copyConstructors(privateGetDeclaredConstructors(true)); } @@ -2219,14 +2065,8 @@ public Constructor[] getConstructors() { * @jls 8.2 Class Members * @jls 8.3 Field Declarations */ - @CallerSensitive public Field getField(String name) throws NoSuchFieldException { Objects.requireNonNull(name); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); - } Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); @@ -2322,15 +2162,9 @@ public Field getField(String name) throws NoSuchFieldException { * @jls 8.4 Method Declarations * @since 1.1 */ - @CallerSensitive public Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException { Objects.requireNonNull(name); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); - } Method method = getMethod0(name, parameterTypes); if (method == null) { throw new NoSuchMethodException(methodToString(name, parameterTypes)); @@ -2363,14 +2197,8 @@ public Method getMethod(String name, Class... parameterTypes) * @see #getDeclaredConstructor(Class[]) * @since 1.1 */ - @CallerSensitive public Constructor getConstructor(Class... parameterTypes) throws NoSuchMethodException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); - } return getReflectionFactory().copyConstructor( getConstructor0(parameterTypes, Member.PUBLIC)); } @@ -2392,13 +2220,7 @@ public Constructor getConstructor(Class... parameterTypes) * @since 1.1 * @jls 8.5 Member Class and Interface Declarations */ - @CallerSensitive public Class[] getDeclaredClasses() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), false); - } return getDeclaredClasses0(); } @@ -2425,13 +2247,7 @@ public Class[] getDeclaredClasses() { * @jls 8.2 Class Members * @jls 8.3 Field Declarations */ - @CallerSensitive public Field[] getDeclaredFields() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); - } return copyFields(privateGetDeclaredFields(false)); } @@ -2467,13 +2283,7 @@ public Field[] getDeclaredFields() { * @jls 8.10 Record Classes * @since 16 */ - @CallerSensitive public RecordComponent[] getRecordComponents() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); - } if (!isRecord()) { return null; } @@ -2519,13 +2329,7 @@ public RecordComponent[] getRecordComponents() { * programming language and JVM modeling in core reflection * @since 1.1 */ - @CallerSensitive public Method[] getDeclaredMethods() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); - } return copyMethods(privateGetDeclaredMethods(false)); } @@ -2550,13 +2354,7 @@ public Method[] getDeclaredMethods() { * @see #getConstructors() * @jls 8.8 Constructor Declarations */ - @CallerSensitive public Constructor[] getDeclaredConstructors() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); - } return copyConstructors(privateGetDeclaredConstructors(false)); } @@ -2581,14 +2379,8 @@ public Constructor[] getDeclaredConstructors() { * @jls 8.2 Class Members * @jls 8.3 Field Declarations */ - @CallerSensitive public Field getDeclaredField(String name) throws NoSuchFieldException { Objects.requireNonNull(name); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); - } Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); @@ -2626,15 +2418,9 @@ public Field getDeclaredField(String name) throws NoSuchFieldException { * @jls 8.4 Method Declarations * @since 1.1 */ - @CallerSensitive public Method getDeclaredMethod(String name, Class... parameterTypes) throws NoSuchMethodException { Objects.requireNonNull(name); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); - } Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(methodToString(name, parameterTypes)); @@ -2703,15 +2489,8 @@ Method findMethod(boolean publicOnly, String name, Class... parameterTypes) { * @see #getConstructor(Class[]) * @since 1.1 */ - @CallerSensitive public Constructor getDeclaredConstructor(Class... parameterTypes) throws NoSuchMethodException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); - } - return getReflectionFactory().copyConstructor( getConstructor0(parameterTypes, Member.DECLARED)); } @@ -2933,11 +2712,6 @@ private boolean isOpenToCaller(String name, Class caller) { * @since 1.2 */ public ProtectionDomain getProtectionDomain() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.GET_PD_PERMISSION); - } return protectionDomain(); } @@ -2972,91 +2746,6 @@ ProtectionDomain protectionDomain() { */ static native Class getPrimitiveClass(String name); - /* - * Check if client is allowed to access members. If access is denied, - * throw a SecurityException. - * - * This method also enforces package access. - * - *

Default policy: allow all clients access with normal Java access - * control. - * - *

NOTE: should only be called if a SecurityManager is installed - */ - private void checkMemberAccess(@SuppressWarnings("removal") SecurityManager sm, int which, - Class caller, boolean checkProxyInterfaces) { - /* Default policy allows access to all {@link Member#PUBLIC} members, - * as well as access to classes that have the same class loader as the caller. - * In all other cases, it requires RuntimePermission("accessDeclaredMembers") - * permission. - */ - final ClassLoader ccl = ClassLoader.getClassLoader(caller); - if (which != Member.PUBLIC) { - final ClassLoader cl = classLoader; - if (ccl != cl) { - sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); - } - } - this.checkPackageAccess(sm, ccl, checkProxyInterfaces); - } - - /* - * Checks if a client loaded in ClassLoader ccl is allowed to access this - * class under the current package access policy. If access is denied, - * throw a SecurityException. - * - * NOTE: this method should only be called if a SecurityManager is active - */ - private void checkPackageAccess(@SuppressWarnings("removal") SecurityManager sm, final ClassLoader ccl, - boolean checkProxyInterfaces) { - final ClassLoader cl = classLoader; - - if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { - String pkg = this.getPackageName(); - if (!pkg.isEmpty()) { - // skip the package access check on a proxy class in default proxy package - if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) { - sm.checkPackageAccess(pkg); - } - } - } - // check package access on the proxy interfaces - if (checkProxyInterfaces && Proxy.isProxyClass(this)) { - ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces(/* cloneArray */ false)); - } - } - - /* - * Checks if a client loaded in ClassLoader ccl is allowed to access the provided - * classes under the current package access policy. If access is denied, - * throw a SecurityException. - * - * NOTE: this method should only be called if a SecurityManager is active - * classes must be non-empty - * all classes provided must be loaded by the same ClassLoader - * NOTE: this method does not support Proxy classes - */ - private static void checkPackageAccessForPermittedSubclasses(@SuppressWarnings("removal") SecurityManager sm, - final ClassLoader ccl, Class[] subClasses) { - final ClassLoader cl = subClasses[0].classLoader; - - if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { - Set packages = new HashSet<>(); - - for (Class c : subClasses) { - if (Proxy.isProxyClass(c)) - throw new InternalError("a permitted subclass should not be a proxy class: " + c); - String pkg = c.getPackageName(); - if (!pkg.isEmpty()) { - packages.add(pkg); - } - } - for (String pkg : packages) { - sm.checkPackageAccess(pkg); - } - } - } - /** * Add a package name prefix if the name is not absolute. Remove leading "/" * if name is absolute @@ -3732,18 +3421,24 @@ public boolean isRecord() { } // Fetches the factory for reflective objects - @SuppressWarnings("removal") private static ReflectionFactory getReflectionFactory() { var factory = reflectionFactory; if (factory != null) { return factory; } - return reflectionFactory = - java.security.AccessController.doPrivileged - (new ReflectionFactory.GetReflectionFactoryAction()); + return reflectionFactory = ReflectionFactory.getReflectionFactory(); } private static ReflectionFactory reflectionFactory; + /** + * When CDS is enabled, the Class class may be aot-initialized. However, + * we can't archive reflectionFactory, so we reset it to null, so it + * will be allocated again at runtime. + */ + private static void resetArchivedStates() { + reflectionFactory = null; + } + /** * Returns the elements of this enum class or null if this * Class object does not represent an enum class. @@ -3766,20 +3461,13 @@ public T[] getEnumConstants() { * identical to getEnumConstants except that the result is * uncloned, cached, and shared by all callers. */ - @SuppressWarnings("removal") T[] getEnumConstantsShared() { T[] constants = enumConstants; if (constants == null) { if (!isEnum()) return null; try { final Method values = getMethod("values"); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public Void run() { - values.setAccessible(true); - return null; - } - }); + values.setAccessible(true); @SuppressWarnings("unchecked") T[] temporaryConstants = (T[])values.invoke(null); enumConstants = constants = temporaryConstants; @@ -4160,24 +3848,11 @@ public AnnotatedType[] getAnnotatedInterfaces() { * @jvms 4.7.29 The {@code NestMembers} Attribute * @jvms 5.4.4 Access Control */ - @CallerSensitive public Class getNestHost() { if (isPrimitive() || isArray()) { return this; } - - Class host = getNestHost0(); - if (host == this) { - return this; - } - // returning a different class requires a security check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkPackageAccess(sm, - ClassLoader.getClassLoader(Reflection.getCallerClass()), true); - } - return host; + return getNestHost0(); } /** @@ -4244,7 +3919,6 @@ public boolean isNestmateOf(Class c) { * @jvms 4.7.28 The {@code NestHost} Attribute * @jvms 4.7.29 The {@code NestMembers} Attribute */ - @CallerSensitive public Class[] getNestMembers() { if (isPrimitive() || isArray()) { return new Class[] { this }; @@ -4252,17 +3926,6 @@ public Class[] getNestMembers() { Class[] members = getNestMembers0(); // Can't actually enable this due to bootstrapping issues // assert(members.length != 1 || members[0] == this); // expected invariant from VM - - if (members.length > 1) { - // If we return anything other than the current class we need - // a security check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkPackageAccess(sm, - ClassLoader.getClassLoader(Reflection.getCallerClass()), true); - } - } return members; } @@ -4432,7 +4095,6 @@ public Optional describeConstable() { * @jls 9.1 Interface Declarations * @since 17 */ - @CallerSensitive public Class[] getPermittedSubclasses() { Class[] subClasses; if (isArray() || isPrimitive() || (subClasses = getPermittedSubclasses0()) == null) { @@ -4445,16 +4107,6 @@ public Class[] getPermittedSubclasses() { .toArray(s -> new Class[s]); } } - if (subClasses.length > 0) { - // If we return some classes we need a security check: - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkPackageAccessForPermittedSubclasses(sm, - ClassLoader.getClassLoader(Reflection.getCallerClass()), - subClasses); - } - } return subClasses; } diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java index 85fc315c767..55341635d8a 100644 --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -64,7 +64,6 @@ import jdk.internal.reflect.CallerSensitiveAdapter; import jdk.internal.reflect.Reflection; import jdk.internal.util.StaticProperty; -import sun.security.util.SecurityConstants; /** * A class loader is an object that is responsible for loading classes. The @@ -357,12 +356,6 @@ private static Void checkCreateClassLoader(String name) { if (name != null && name.isEmpty()) { throw new IllegalArgumentException("name must be non-empty or null"); } - - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkCreateClassLoader(); - } return null; } @@ -1735,18 +1728,7 @@ public static InputStream getSystemResourceAsStream(String name) { * * @since 1.2 */ - @CallerSensitive public final ClassLoader getParent() { - if (parent == null) - return null; - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // Check access to the parent class loader - // If the caller's class loader is same as this class loader, - // permission check is performed. - checkClassLoaderPermission(parent, Reflection.getCallerClass()); - } return parent; } @@ -1774,15 +1756,8 @@ public final Module getUnnamedModule() { * * @since 9 */ - @CallerSensitive public static ClassLoader getPlatformClassLoader() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - ClassLoader loader = getBuiltinPlatformClassLoader(); - if (sm != null) { - checkClassLoaderPermission(loader, Reflection.getCallerClass()); - } - return loader; + return getBuiltinPlatformClassLoader(); } /** @@ -1853,7 +1828,6 @@ public static ClassLoader getPlatformClassLoader() { * underlying cause of the error can be retrieved via the * {@link Throwable#getCause()} method. */ - @CallerSensitive public static ClassLoader getSystemClassLoader() { switch (VM.initLevel()) { case 0: @@ -1867,11 +1841,6 @@ public static ClassLoader getSystemClassLoader() { default: // system fully initialized assert VM.isBooted() && scl != null; - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkClassLoaderPermission(scl, Reflection.getCallerClass()); - } return scl; } } @@ -1902,8 +1871,6 @@ static synchronized ClassLoader initSystemClassLoader() { } ClassLoader builtinLoader = getBuiltinAppClassLoader(); - - // All are privileged frames. No need to call doPrivileged. String cn = System.getProperty("java.system.class.loader"); if (cn != null) { try { @@ -1930,36 +1897,6 @@ static synchronized ClassLoader initSystemClassLoader() { return scl; } - // Returns true if the specified class loader can be found in this class - // loader's delegation chain. - boolean isAncestor(ClassLoader cl) { - ClassLoader acl = this; - do { - acl = acl.parent; - if (cl == acl) { - return true; - } - } while (acl != null); - return false; - } - - // Tests if class loader access requires "getClassLoader" permission - // check. A class loader 'from' can access class loader 'to' if - // class loader 'from' is same as class loader 'to' or an ancestor - // of 'to'. The class loader in a system domain can access - // any class loader. - private static boolean needsClassLoaderPermissionCheck(ClassLoader from, - ClassLoader to) - { - if (from == to) - return false; - - if (from == null) - return false; - - return !to.isAncestor(from); - } - // Returns the class's class loader, or null if none. static ClassLoader getClassLoader(Class caller) { // This can be null if the VM is requesting it @@ -1970,23 +1907,6 @@ static ClassLoader getClassLoader(Class caller) { return caller.getClassLoader0(); } - /* - * Checks RuntimePermission("getClassLoader") permission - * if caller's class loader is not null and caller's class loader - * is not the same as or an ancestor of the given cl argument. - */ - static void checkClassLoaderPermission(ClassLoader cl, Class caller) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // caller can be null if the VM is requesting it - ClassLoader ccl = getClassLoader(caller); - if (needsClassLoaderPermissionCheck(ccl, cl)) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - } - } - // The system class loader // @GuardedBy("ClassLoader.class") private static volatile ClassLoader scl; diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index a90fbc99260..4f9c09bace4 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -39,8 +39,6 @@ import java.lang.reflect.AnnotatedElement; import java.net.URI; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -64,14 +62,12 @@ import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; import jdk.internal.module.ModuleBootstrap; -import jdk.internal.module.ModuleBootstrap.IllegalNativeAccess; import jdk.internal.module.ModuleLoaderMap; import jdk.internal.module.ServicesCatalog; import jdk.internal.module.Resources; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.vm.annotation.Stable; -import sun.security.util.SecurityConstants; /** * Represents a run-time module, either {@link #isNamed() named} or unnamed. @@ -198,11 +194,6 @@ public String getName() { * @return The class loader for this module */ public ClassLoader getClassLoader() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } return loader; } @@ -1556,7 +1547,6 @@ public Annotation[] getDeclaredAnnotations() { // cached class file with annotations private volatile Class moduleInfoClass; - @SuppressWarnings("removal") private Class moduleInfoClass() { Class clazz = this.moduleInfoClass; if (clazz != null) @@ -1566,8 +1556,7 @@ private Class moduleInfoClass() { clazz = this.moduleInfoClass; if (clazz == null) { if (isNamed()) { - PrivilegedAction> pa = this::loadModuleInfoClass; - clazz = AccessController.doPrivileged(pa); + clazz = loadModuleInfoClass(); } if (clazz == null) { class DummyModuleInfo { } diff --git a/src/java.base/share/classes/java/lang/ModuleLayer.java b/src/java.base/share/classes/java/lang/ModuleLayer.java index 4ee2b02414d..5dfd93796d2 100644 --- a/src/java.base/share/classes/java/lang/ModuleLayer.java +++ b/src/java.base/share/classes/java/lang/ModuleLayer.java @@ -44,7 +44,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.Restricted; import jdk.internal.loader.ClassLoaderValue; import jdk.internal.loader.Loader; @@ -54,7 +53,6 @@ import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.vm.annotation.Stable; -import sun.security.util.SecurityConstants; /** * A layer of modules in the Java virtual machine. @@ -505,9 +503,6 @@ public static Controller defineModulesWithOneLoader(Configuration cf, List parents = List.copyOf(parentLayers); checkConfiguration(cf, parents); - checkCreateClassLoaderPermission(); - checkGetClassLoaderPermission(); - try { Loader loader = new Loader(cf.modules(), parentLoader); loader.initRemotePackageMap(cf, parents); @@ -572,9 +567,6 @@ public static Controller defineModulesWithManyLoaders(Configuration cf, List parents = List.copyOf(parentLayers); checkConfiguration(cf, parents); - checkCreateClassLoaderPermission(); - checkGetClassLoaderPermission(); - LoaderPool pool = new LoaderPool(cf, parents, parentLoader); try { ModuleLayer layer = new ModuleLayer(cf, parents, pool::loaderFor); @@ -654,8 +646,6 @@ public static Controller defineModules(Configuration cf, checkConfiguration(cf, parents); Objects.requireNonNull(clf); - checkGetClassLoaderPermission(); - // The boot layer is checked during module system initialization if (boot() != null) { checkForDuplicatePkgs(cf, clf); @@ -693,20 +683,6 @@ private static void checkConfiguration(Configuration cf, } } - private static void checkCreateClassLoaderPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION); - } - - private static void checkGetClassLoaderPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - /** * Checks a configuration and the module-to-loader mapping to ensure that * no two modules mapped to the same class loader have the same package. diff --git a/src/java.base/share/classes/java/lang/Package.java b/src/java.base/share/classes/java/lang/Package.java index d48320a66cf..424c390c8ef 100644 --- a/src/java.base/share/classes/java/lang/Package.java +++ b/src/java.base/share/classes/java/lang/Package.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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,8 +30,6 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Objects; import jdk.internal.loader.BootLoader; @@ -417,9 +415,7 @@ private Class getPackageInfo() { // find package-info.class defined by loader String cn = packageName() + ".package-info"; Module module = module(); - PrivilegedAction pa = module::getClassLoader; - @SuppressWarnings("removal") - ClassLoader loader = AccessController.doPrivileged(pa); + ClassLoader loader = module.getClassLoader(); Class c; if (loader != null) { c = loader.loadClass(module, cn); diff --git a/src/java.base/share/classes/java/lang/PublicMethods.java b/src/java.base/share/classes/java/lang/PublicMethods.java index b9851e2f049..03b3ad86a7a 100644 --- a/src/java.base/share/classes/java/lang/PublicMethods.java +++ b/src/java.base/share/classes/java/lang/PublicMethods.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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,7 +28,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.security.AccessController; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; @@ -88,10 +87,7 @@ Method[] toArray() { * Method (name, parameter types) tuple. */ private static final class Key { - @SuppressWarnings("removal") - private static final ReflectionFactory reflectionFactory = - AccessController.doPrivileged( - new ReflectionFactory.GetReflectionFactoryAction()); + private static final ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory(); private final String name; // must be interned (as from Method.getName()) private final Class[] ptypes; diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 275961a9a9f..8c0ce29dbee 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -27,9 +27,7 @@ import java.io.*; import java.util.*; -import jdk.internal.access.SharedSecrets; import jdk.internal.event.ThrowableTracer; -import jdk.internal.misc.InternalLock; /** * The {@code Throwable} class is the superclass of all errors and @@ -689,39 +687,27 @@ public void printStackTrace(PrintStream s) { } private void printStackTrace(PrintStreamOrWriter s) { - Object lock = s.lock(); - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedPrintStackTrace(s); - } finally { - locker.unlock(); - } - } else synchronized (lock) { - lockedPrintStackTrace(s); - } - } - - private void lockedPrintStackTrace(PrintStreamOrWriter s) { // Guard against malicious overrides of Throwable.equals by // using a Set with identity equality semantics. Set dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); dejaVu.add(this); - // Print our stack trace - s.println(this); - StackTraceElement[] trace = getOurStackTrace(); - for (StackTraceElement traceElement : trace) - s.println("\tat " + traceElement); + synchronized(s.lock()) { + // Print our stack trace + s.println(this); + StackTraceElement[] trace = getOurStackTrace(); + for (StackTraceElement traceElement : trace) + s.println("\tat " + traceElement); - // Print suppressed exceptions, if any - for (Throwable se : getSuppressed()) - se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); + // Print suppressed exceptions, if any + for (Throwable se : getSuppressed()) + se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); - // Print cause, if any - Throwable ourCause = getCause(); - if (ourCause != null) - ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); + // Print cause, if any + Throwable ourCause = getCause(); + if (ourCause != null) + ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); + } } /** @@ -733,7 +719,7 @@ private void printEnclosedStackTrace(PrintStreamOrWriter s, String caption, String prefix, Set dejaVu) { - assert s.isLockedByCurrentThread(); + assert Thread.holdsLock(s.lock()); if (dejaVu.contains(this)) { s.println(prefix + caption + "[CIRCULAR REFERENCE: " + this + "]"); } else { @@ -785,15 +771,6 @@ private abstract static class PrintStreamOrWriter { /** Returns the object to be locked when using this StreamOrWriter */ abstract Object lock(); - boolean isLockedByCurrentThread() { - Object lock = lock(); - if (lock instanceof InternalLock locker) { - return locker.isHeldByCurrentThread(); - } else { - return Thread.holdsLock(lock); - } - } - /** Prints the specified string as a line on this StreamOrWriter */ abstract void println(Object o); } @@ -806,7 +783,7 @@ private static class WrappedPrintStream extends PrintStreamOrWriter { } Object lock() { - return SharedSecrets.getJavaIOPrintStreamAccess().lock(printStream); + return printStream; } void println(Object o) { @@ -822,7 +799,7 @@ private static class WrappedPrintWriter extends PrintStreamOrWriter { } Object lock() { - return SharedSecrets.getJavaIOPrintWriterAccess().lock(printWriter); + return printWriter; } void println(Object o) { diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java index 1bf4367bed4..1f8e1941c1d 100644 --- a/src/java.base/share/classes/java/lang/VirtualThread.java +++ b/src/java.base/share/classes/java/lang/VirtualThread.java @@ -108,14 +108,14 @@ final class VirtualThread extends BaseVirtualThread { * UNBLOCKED -> RUNNING // continue execution after blocked on monitor enter * * RUNNING -> WAITING // transitional state during wait on monitor - * WAITING -> WAITED // waiting on monitor - * WAITED -> BLOCKED // notified, waiting to be unblocked by monitor owner - * WAITED -> UNBLOCKED // timed-out/interrupted + * WAITING -> WAIT // waiting on monitor + * WAIT -> BLOCKED // notified, waiting to be unblocked by monitor owner + * WAIT -> UNBLOCKED // timed-out/interrupted * * RUNNING -> TIMED_WAITING // transition state during timed-waiting on monitor - * TIMED_WAITING -> TIMED_WAITED // timed-waiting on monitor - * TIMED_WAITED -> BLOCKED // notified, waiting to be unblocked by monitor owner - * TIMED_WAITED -> UNBLOCKED // timed-out/interrupted + * TIMED_WAITING -> TIMED_WAIT // timed-waiting on monitor + * TIMED_WAIT -> BLOCKED // notified, waiting to be unblocked by monitor owner + * TIMED_WAIT -> UNBLOCKED // timed-out/interrupted * * RUNNING -> YIELDING // Thread.yield * YIELDING -> YIELDED // cont.yield successful, may be scheduled to continue diff --git a/src/java.base/share/classes/java/lang/classfile/AccessFlags.java b/src/java.base/share/classes/java/lang/classfile/AccessFlags.java index 4abe17c1cf5..b1d026f52e4 100644 --- a/src/java.base/share/classes/java/lang/classfile/AccessFlags.java +++ b/src/java.base/share/classes/java/lang/classfile/AccessFlags.java @@ -28,16 +28,14 @@ import java.util.Set; import jdk.internal.classfile.impl.AccessFlagsImpl; -import jdk.internal.javac.PreviewFeature; /** * Models the access flags for a class, method, or field. Delivered as a * {@link ClassElement}, {@link FieldElement}, or {@link MethodElement} * when traversing the corresponding model type. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface AccessFlags extends ClassElement, MethodElement, FieldElement permits AccessFlagsImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/Annotation.java b/src/java.base/share/classes/java/lang/classfile/Annotation.java index 4f222084cb7..98b6ea783d5 100644 --- a/src/java.base/share/classes/java/lang/classfile/Annotation.java +++ b/src/java.base/share/classes/java/lang/classfile/Annotation.java @@ -35,7 +35,6 @@ import jdk.internal.classfile.impl.AnnotationImpl; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models an {@code annotation} structure (JVMS {@jvms 4.7.16}) or part of a {@code @@ -63,9 +62,8 @@ * @see RuntimeVisibleParameterAnnotationsAttribute * @see RuntimeInvisibleParameterAnnotationsAttribute * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Annotation permits AnnotationImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java b/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java index 7c4283c49bf..4381bb9733a 100644 --- a/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java @@ -29,7 +29,6 @@ import jdk.internal.classfile.impl.AnnotationImpl; import jdk.internal.classfile.impl.TemporaryConstantPool; -import jdk.internal.javac.PreviewFeature; /** * Models an element-value pair in the {@code element_value_pairs} @@ -43,9 +42,8 @@ * @see Annotation * @see AnnotationValue * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface AnnotationElement permits AnnotationImpl.AnnotationElementImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java index e1e91f2c9ed..8e92ef59a50 100644 --- a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.AnnotationImpl; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -48,18 +47,16 @@ * @see AnnotationElement * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface AnnotationValue { /** * Models an annotation value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_ANNOTATION}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfAnnotation extends AnnotationValue permits AnnotationImpl.OfAnnotationImpl { /** {@return the annotation value} */ @@ -70,9 +67,8 @@ sealed interface OfAnnotation extends AnnotationValue * Models an array value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_ARRAY}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfArray extends AnnotationValue permits AnnotationImpl.OfArrayImpl { /** @@ -91,9 +87,8 @@ sealed interface OfArray extends AnnotationValue * Models a constant value of an element-value pair. * * @sealedGraph - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfConstant extends AnnotationValue { /** * {@return the constant pool entry backing this constant element} @@ -128,9 +123,8 @@ sealed interface OfConstant extends AnnotationValue { * Models a string value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_STRING}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfString extends OfConstant permits AnnotationImpl.OfStringImpl { /** {@return the backing UTF8 entry} */ @@ -156,9 +150,8 @@ default String resolvedValue() { * Models a double value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_DOUBLE}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfDouble extends OfConstant permits AnnotationImpl.OfDoubleImpl { /** {@return the backing double entry} */ @@ -184,9 +177,8 @@ default Double resolvedValue() { * Models a float value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_FLOAT}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfFloat extends OfConstant permits AnnotationImpl.OfFloatImpl { /** {@return the backing float entry} */ @@ -212,9 +204,8 @@ default Float resolvedValue() { * Models a long value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_LONG}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfLong extends OfConstant permits AnnotationImpl.OfLongImpl { /** {@return the backing long entry} */ @@ -240,9 +231,8 @@ default Long resolvedValue() { * Models an int value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_INT}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfInt extends OfConstant permits AnnotationImpl.OfIntImpl { /** {@return the backing integer entry} */ @@ -268,9 +258,8 @@ default Integer resolvedValue() { * Models a short value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_SHORT}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfShort extends OfConstant permits AnnotationImpl.OfShortImpl { /** {@return the backing integer entry} */ @@ -299,9 +288,8 @@ default Short resolvedValue() { * Models a char value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_CHAR}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfChar extends OfConstant permits AnnotationImpl.OfCharImpl { /** {@return the backing integer entry} */ @@ -330,9 +318,8 @@ default Character resolvedValue() { * Models a byte value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_BYTE}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfByte extends OfConstant permits AnnotationImpl.OfByteImpl { /** {@return the backing integer entry} */ @@ -361,9 +348,8 @@ default Byte resolvedValue() { * Models a boolean value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_BOOLEAN}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfBoolean extends OfConstant permits AnnotationImpl.OfBooleanImpl { /** {@return the backing integer entry} */ @@ -392,9 +378,8 @@ default Boolean resolvedValue() { * Models a class value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_CLASS}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfClass extends AnnotationValue permits AnnotationImpl.OfClassImpl { /** {@return the class descriptor string} */ @@ -410,9 +395,8 @@ default ClassDesc classSymbol() { * Models an enum value of an element-value pair. * The {@linkplain #tag tag} of this value is {@value TAG_ENUM}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfEnum extends AnnotationValue permits AnnotationImpl.OfEnumImpl { /** {@return the enum class descriptor string} */ diff --git a/src/java.base/share/classes/java/lang/classfile/Attribute.java b/src/java.base/share/classes/java/lang/classfile/Attribute.java index e2f0072d396..bb5c7bdf8ea 100644 --- a/src/java.base/share/classes/java/lang/classfile/Attribute.java +++ b/src/java.base/share/classes/java/lang/classfile/Attribute.java @@ -25,10 +25,10 @@ package java.lang.classfile; import java.lang.classfile.attribute.*; +import java.lang.classfile.constantpool.Utf8Entry; import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models a classfile attribute (JVMS {@jvms 4.7}). Many, though not all, subtypes of @@ -41,9 +41,8 @@ * @param the attribute type * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Attribute> extends ClassFileElement permits AnnotationDefaultAttribute, BootstrapMethodsAttribute, @@ -65,7 +64,7 @@ public sealed interface Attribute> /** * {@return the name of the attribute} */ - String attributeName(); + Utf8Entry attributeName(); /** * {@return the {@link AttributeMapper} associated with this attribute} diff --git a/src/java.base/share/classes/java/lang/classfile/AttributeMapper.java b/src/java.base/share/classes/java/lang/classfile/AttributeMapper.java index 0b46055423a..993da9aa4a8 100644 --- a/src/java.base/share/classes/java/lang/classfile/AttributeMapper.java +++ b/src/java.base/share/classes/java/lang/classfile/AttributeMapper.java @@ -24,8 +24,6 @@ */ package java.lang.classfile; -import jdk.internal.javac.PreviewFeature; - /** * Bidirectional mapper between the classfile representation of an attribute and * how that attribute is modeled in the API. The attribute mapper is used @@ -37,17 +35,15 @@ * CustomAttribute}. * @param the attribute type * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public interface AttributeMapper> { /** * Attribute stability indicator * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum AttributeStability { /** diff --git a/src/java.base/share/classes/java/lang/classfile/AttributedElement.java b/src/java.base/share/classes/java/lang/classfile/AttributedElement.java index fb1bf817480..478ad1e3f0a 100644 --- a/src/java.base/share/classes/java/lang/classfile/AttributedElement.java +++ b/src/java.base/share/classes/java/lang/classfile/AttributedElement.java @@ -31,7 +31,6 @@ import java.util.Optional; import jdk.internal.classfile.impl.AbstractUnboundModel; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -40,9 +39,8 @@ * as a class, field, method, code attribute, or record component. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface AttributedElement extends ClassFileElement permits ClassModel, CodeModel, FieldModel, MethodModel, RecordComponentInfo, AbstractUnboundModel { diff --git a/src/java.base/share/classes/java/lang/classfile/Attributes.java b/src/java.base/share/classes/java/lang/classfile/Attributes.java index ad63eec75de..24684a36b02 100644 --- a/src/java.base/share/classes/java/lang/classfile/Attributes.java +++ b/src/java.base/share/classes/java/lang/classfile/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +28,6 @@ import java.lang.classfile.attribute.*; import jdk.internal.classfile.impl.AbstractAttributeMapper.*; -import jdk.internal.javac.PreviewFeature; /** * Attribute mappers for standard classfile attributes. @@ -89,9 +88,8 @@ * * @see AttributeMapper * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public final class Attributes { /** AnnotationDefault */ @@ -207,7 +205,6 @@ private Attributes() { /** * {@return Attribute mapper for the {@code AnnotationDefault} attribute} - * @since 23 */ public static AttributeMapper annotationDefault() { return AnnotationDefaultMapper.INSTANCE; @@ -215,7 +212,6 @@ public static AttributeMapper annotationDefault() { /** * {@return Attribute mapper for the {@code BootstrapMethods} attribute} - * @since 23 */ public static AttributeMapper bootstrapMethods() { return BootstrapMethodsMapper.INSTANCE; @@ -224,7 +220,6 @@ public static AttributeMapper bootstrapMethods() { /** * {@return Attribute mapper for the {@code CharacterRangeTable} attribute} * The mapper permits multiple instances in a given location. - * @since 23 */ public static AttributeMapper characterRangeTable() { return CharacterRangeTableMapper.INSTANCE; @@ -232,7 +227,6 @@ public static AttributeMapper characterRangeTable( /** * {@return Attribute mapper for the {@code Code} attribute} - * @since 23 */ public static AttributeMapper code() { return CodeMapper.INSTANCE; @@ -240,7 +234,6 @@ public static AttributeMapper code() { /** * {@return Attribute mapper for the {@code CompilationID} attribute} - * @since 23 */ public static AttributeMapper compilationId() { return CompilationIDMapper.INSTANCE; @@ -248,7 +241,6 @@ public static AttributeMapper compilationId() { /** * {@return Attribute mapper for the {@code ConstantValue} attribute} - * @since 23 */ public static AttributeMapper constantValue() { return ConstantValueMapper.INSTANCE; @@ -257,7 +249,6 @@ public static AttributeMapper constantValue() { /** * {@return Attribute mapper for the {@code Deprecated} attribute} * The mapper permits multiple instances in a given location. - * @since 23 */ public static AttributeMapper deprecated() { return DeprecatedMapper.INSTANCE; @@ -265,7 +256,6 @@ public static AttributeMapper deprecated() { /** * {@return Attribute mapper for the {@code EnclosingMethod} attribute} - * @since 23 */ public static AttributeMapper enclosingMethod() { return EnclosingMethodMapper.INSTANCE; @@ -273,7 +263,6 @@ public static AttributeMapper enclosingMethod() { /** * {@return Attribute mapper for the {@code Exceptions} attribute} - * @since 23 */ public static AttributeMapper exceptions() { return ExceptionsMapper.INSTANCE; @@ -281,7 +270,6 @@ public static AttributeMapper exceptions() { /** * {@return Attribute mapper for the {@code InnerClasses} attribute} - * @since 23 */ public static AttributeMapper innerClasses() { return InnerClassesMapper.INSTANCE; @@ -290,7 +278,6 @@ public static AttributeMapper innerClasses() { /** * {@return Attribute mapper for the {@code LineNumberTable} attribute} * The mapper permits multiple instances in a given location. - * @since 23 */ public static AttributeMapper lineNumberTable() { return LineNumberTableMapper.INSTANCE; @@ -299,7 +286,6 @@ public static AttributeMapper lineNumberTable() { /** * {@return Attribute mapper for the {@code LocalVariableTable} attribute} * The mapper permits multiple instances in a given location. - * @since 23 */ public static AttributeMapper localVariableTable() { return LocalVariableTableMapper.INSTANCE; @@ -308,7 +294,6 @@ public static AttributeMapper localVariableTable() /** * {@return Attribute mapper for the {@code LocalVariableTypeTable} attribute} * The mapper permits multiple instances in a given location. - * @since 23 */ public static AttributeMapper localVariableTypeTable() { return LocalVariableTypeTableMapper.INSTANCE; @@ -316,7 +301,6 @@ public static AttributeMapper localVariableType /** * {@return Attribute mapper for the {@code MethodParameters} attribute} - * @since 23 */ public static AttributeMapper methodParameters() { return MethodParametersMapper.INSTANCE; @@ -324,7 +308,6 @@ public static AttributeMapper methodParameters() { /** * {@return Attribute mapper for the {@code Module} attribute} - * @since 23 */ public static AttributeMapper module() { return ModuleMapper.INSTANCE; @@ -332,7 +315,6 @@ public static AttributeMapper module() { /** * {@return Attribute mapper for the {@code ModuleHashes} attribute} - * @since 23 */ public static AttributeMapper moduleHashes() { return ModuleHashesMapper.INSTANCE; @@ -340,7 +322,6 @@ public static AttributeMapper moduleHashes() { /** * {@return Attribute mapper for the {@code ModuleMainClass} attribute} - * @since 23 */ public static AttributeMapper moduleMainClass() { return ModuleMainClassMapper.INSTANCE; @@ -348,7 +329,6 @@ public static AttributeMapper moduleMainClass() { /** * {@return Attribute mapper for the {@code ModulePackages} attribute} - * @since 23 */ public static AttributeMapper modulePackages() { return ModulePackagesMapper.INSTANCE; @@ -356,7 +336,6 @@ public static AttributeMapper modulePackages() { /** * {@return Attribute mapper for the {@code ModuleResolution} attribute} - * @since 23 */ public static AttributeMapper moduleResolution() { return ModuleResolutionMapper.INSTANCE; @@ -364,7 +343,6 @@ public static AttributeMapper moduleResolution() { /** * {@return Attribute mapper for the {@code ModuleTarget} attribute} - * @since 23 */ public static AttributeMapper moduleTarget() { return ModuleTargetMapper.INSTANCE; @@ -372,7 +350,6 @@ public static AttributeMapper moduleTarget() { /** * {@return Attribute mapper for the {@code NestHost} attribute} - * @since 23 */ public static AttributeMapper nestHost() { return NestHostMapper.INSTANCE; @@ -380,7 +357,6 @@ public static AttributeMapper nestHost() { /** * {@return Attribute mapper for the {@code NestMembers} attribute} - * @since 23 */ public static AttributeMapper nestMembers() { return NestMembersMapper.INSTANCE; @@ -388,7 +364,6 @@ public static AttributeMapper nestMembers() { /** * {@return Attribute mapper for the {@code PermittedSubclasses} attribute} - * @since 23 */ public static AttributeMapper permittedSubclasses() { return PermittedSubclassesMapper.INSTANCE; @@ -396,7 +371,6 @@ public static AttributeMapper permittedSubclasses( /** * {@return Attribute mapper for the {@code Record} attribute} - * @since 23 */ public static AttributeMapper record() { return RecordMapper.INSTANCE; @@ -404,7 +378,6 @@ public static AttributeMapper record() { /** * {@return Attribute mapper for the {@code RuntimeInvisibleAnnotations} attribute} - * @since 23 */ public static AttributeMapper runtimeInvisibleAnnotations() { return RuntimeInvisibleAnnotationsMapper.INSTANCE; @@ -412,7 +385,6 @@ public static AttributeMapper runtimeInvis /** * {@return Attribute mapper for the {@code RuntimeInvisibleParameterAnnotations} attribute} - * @since 23 */ public static AttributeMapper runtimeInvisibleParameterAnnotations() { return RuntimeInvisibleParameterAnnotationsMapper.INSTANCE; @@ -420,7 +392,6 @@ public static AttributeMapper run /** * {@return Attribute mapper for the {@code RuntimeInvisibleTypeAnnotations} attribute} - * @since 23 */ public static AttributeMapper runtimeInvisibleTypeAnnotations() { return RuntimeInvisibleTypeAnnotationsMapper.INSTANCE; @@ -428,7 +399,6 @@ public static AttributeMapper runtimeI /** * {@return Attribute mapper for the {@code RuntimeVisibleAnnotations} attribute} - * @since 23 */ public static AttributeMapper runtimeVisibleAnnotations() { return RuntimeVisibleAnnotationsMapper.INSTANCE; @@ -436,7 +406,6 @@ public static AttributeMapper runtimeVisible /** * {@return Attribute mapper for the {@code RuntimeVisibleParameterAnnotations} attribute} - * @since 23 */ public static AttributeMapper runtimeVisibleParameterAnnotations() { return RuntimeVisibleParameterAnnotationsMapper.INSTANCE; @@ -444,7 +413,6 @@ public static AttributeMapper runti /** * {@return Attribute mapper for the {@code RuntimeVisibleTypeAnnotations} attribute} - * @since 23 */ public static AttributeMapper runtimeVisibleTypeAnnotations() { return RuntimeVisibleTypeAnnotationsMapper.INSTANCE; @@ -452,7 +420,6 @@ public static AttributeMapper runtimeVis /** * {@return Attribute mapper for the {@code Signature} attribute} - * @since 23 */ public static AttributeMapper signature() { return SignatureMapper.INSTANCE; @@ -460,7 +427,6 @@ public static AttributeMapper signature() { /** * {@return Attribute mapper for the {@code SourceDebugExtension} attribute} - * @since 23 */ public static AttributeMapper sourceDebugExtension() { return SourceDebugExtensionMapper.INSTANCE; @@ -468,7 +434,6 @@ public static AttributeMapper sourceDebugExtensio /** * {@return Attribute mapper for the {@code SourceFile} attribute} - * @since 23 */ public static AttributeMapper sourceFile() { return SourceFileMapper.INSTANCE; @@ -476,7 +441,6 @@ public static AttributeMapper sourceFile() { /** * {@return Attribute mapper for the {@code SourceID} attribute} - * @since 23 */ public static AttributeMapper sourceId() { return SourceIDMapper.INSTANCE; @@ -484,7 +448,6 @@ public static AttributeMapper sourceId() { /** * {@return Attribute mapper for the {@code StackMapTable} attribute} - * @since 23 */ public static AttributeMapper stackMapTable() { return StackMapTableMapper.INSTANCE; @@ -493,7 +456,6 @@ public static AttributeMapper stackMapTable() { /** * {@return Attribute mapper for the {@code Synthetic} attribute} * The mapper permits multiple instances in a given location. - * @since 23 */ public static AttributeMapper synthetic() { return SyntheticMapper.INSTANCE; diff --git a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java index 964976e0fd5..1608e77bee6 100644 --- a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java @@ -31,7 +31,6 @@ import java.util.List; import jdk.internal.classfile.impl.BootstrapMethodEntryImpl; -import jdk.internal.javac.PreviewFeature; /** * Models an entry in the bootstrap method table. The bootstrap method table @@ -39,9 +38,8 @@ * the {@link ConstantPool}, since the bootstrap method table is logically * part of the constant pool. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface BootstrapMethodEntry permits BootstrapMethodEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/BufWriter.java b/src/java.base/share/classes/java/lang/classfile/BufWriter.java index d60447c1388..c6779583eb1 100644 --- a/src/java.base/share/classes/java/lang/classfile/BufWriter.java +++ b/src/java.base/share/classes/java/lang/classfile/BufWriter.java @@ -29,16 +29,14 @@ import java.lang.classfile.constantpool.PoolEntry; import jdk.internal.classfile.impl.BufWriterImpl; -import jdk.internal.javac.PreviewFeature; /** * Supports writing portions of a classfile to a growable buffer. Methods * are provided to write various standard entities (e.g., {@code u2}, {@code u4}) * to the end of the buffer, as well as to create constant pool entries. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface BufWriter permits BufWriterImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java b/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java index 71f1cc53194..996c63ddd01 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java @@ -39,7 +39,6 @@ import jdk.internal.classfile.impl.ChainedClassBuilder; import jdk.internal.classfile.impl.DirectClassBuilder; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * A builder for classfiles. Builders are not created directly; they are passed @@ -50,9 +49,8 @@ * * @see ClassTransform * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassBuilder extends ClassFileBuilder permits ChainedClassBuilder, DirectClassBuilder { diff --git a/src/java.base/share/classes/java/lang/classfile/ClassElement.java b/src/java.base/share/classes/java/lang/classfile/ClassElement.java index 6c918b7de4a..c39ab3c4a64 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassElement.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +26,13 @@ import java.lang.classfile.attribute.*; -import jdk.internal.javac.PreviewFeature; - /** * A marker interface for elements that can appear when traversing * a {@link ClassModel} or be presented to a {@link ClassBuilder}. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassElement extends ClassFileElement permits AccessFlags, Superclass, Interfaces, ClassFileVersion, FieldModel, MethodModel, diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFile.java b/src/java.base/share/classes/java/lang/classfile/ClassFile.java index 7051228c827..db293f41588 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFile.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFile.java @@ -43,7 +43,6 @@ import jdk.internal.classfile.impl.ClassFileImpl; import jdk.internal.classfile.impl.TemporaryConstantPool; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; import static jdk.internal.constant.ConstantUtils.CD_module_info; @@ -53,9 +52,8 @@ * A {@code ClassFile} has a set of options that condition how parsing and * generation is done. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassFile permits ClassFileImpl { @@ -84,9 +82,8 @@ static ClassFile of(Option... options) { * An option that affects the parsing and writing of classfiles. * * @sealedGraph - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface Option { } @@ -94,9 +91,8 @@ sealed interface Option { * Option describing attribute mappers for custom attributes. * Default is only to process standard attributes. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface AttributeMapperOption extends Option permits ClassFileImpl.AttributeMapperOptionImpl { @@ -119,9 +115,8 @@ static AttributeMapperOption of(Function> attribut * Option describing the class hierarchy resolver to use when generating * stack maps. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface ClassHierarchyResolverOption extends Option permits ClassFileImpl.ClassHierarchyResolverOptionImpl { @@ -150,9 +145,8 @@ static ClassHierarchyResolverOption of(ClassHierarchyResolver classHierarchyReso * Default is {@code SHARED_POOL} to preserve the original constant * pool. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum ConstantPoolSharingOption implements Option { /** Preserves the original constant pool when transforming classfile */ @@ -167,9 +161,8 @@ enum ConstantPoolSharingOption implements Option { * Default is {@code PATCH_DEAD_CODE} to automatically patch out unreachable * code with NOPs. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum DeadCodeOption implements Option { /** Patch unreachable code */ @@ -188,9 +181,8 @@ enum DeadCodeOption implements Option { * Setting this option to {@code DROP_DEAD_LABELS} filters the above * elements instead. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum DeadLabelsOption implements Option { /** Fail on unresolved labels */ @@ -207,9 +199,8 @@ enum DeadLabelsOption implements Option { * reduce the overhead of parsing or transforming classfiles. * Default is {@code PASS_DEBUG} to process debug elements. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum DebugElementsOption implements Option { /** Process debug elements */ @@ -225,9 +216,8 @@ enum DebugElementsOption implements Option { * classfiles. * Default is {@code PASS_LINE_NUMBERS} to process line numbers. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum LineNumbersOption implements Option { /** Process line numbers */ @@ -243,9 +233,8 @@ enum LineNumbersOption implements Option { * Default is {@code FIX_SHORT_JUMPS} to automatically rewrite jump * instructions. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum ShortJumpsOption implements Option { /** Automatically convert short jumps to long when necessary */ @@ -262,9 +251,8 @@ enum ShortJumpsOption implements Option { * {@link #JAVA_6_VERSION} the stack maps may not be generated. * @jvms 4.10.1 Verification by Type Checking * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum StackMapsOption implements Option { /** Generate stack maps when required */ @@ -284,9 +272,8 @@ enum StackMapsOption implements Option { * Default is {@code PASS_ALL_ATTRIBUTES} to process all original attributes. * @see AttributeMapper.AttributeStability * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) enum AttributesProcessingOption implements Option { /** Process all original attributes during transformation */ @@ -648,16 +635,10 @@ default List verify(Path path) throws IOException { /** The class major version of JAVA_22. */ int JAVA_22_VERSION = 66; - /** - * The class major version of JAVA_23. - * @since 23 - */ + /** The class major version of JAVA_23. */ int JAVA_23_VERSION = 67; - /** - * The class major version of JAVA_24. - * @since 24 - */ + /** The class major version of JAVA_24. */ int JAVA_24_VERSION = 68; /** diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFileBuilder.java b/src/java.base/share/classes/java/lang/classfile/ClassFileBuilder.java index 8b3f6544fff..01eeefd0b9b 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFileBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFileBuilder.java @@ -29,7 +29,6 @@ import java.util.function.Consumer; import jdk.internal.classfile.impl.TransformImpl; -import jdk.internal.javac.PreviewFeature; /** * A builder for a classfile or portion of a classfile. Builders are rarely @@ -44,9 +43,8 @@ * @see ClassFileTransform * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassFileBuilder> extends Consumer permits ClassBuilder, FieldBuilder, MethodBuilder, CodeBuilder { diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFileElement.java b/src/java.base/share/classes/java/lang/classfile/ClassFileElement.java index a4a8203038f..ed84eb39d53 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFileElement.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFileElement.java @@ -24,8 +24,6 @@ */ package java.lang.classfile; -import jdk.internal.javac.PreviewFeature; - /** * Immutable model for a portion of (or the entirety of) a classfile. Elements * that model parts of the classfile that have attributes will implement {@link @@ -35,9 +33,8 @@ * will implement {@link ClassElement}, {@link MethodElement}, etc. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassFileElement permits AttributedElement, CompoundElement, Attribute, ClassElement, CodeElement, FieldElement, MethodElement { diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFileTransform.java b/src/java.base/share/classes/java/lang/classfile/ClassFileTransform.java index b9c5210881c..9fdafdf4331 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFileTransform.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFileTransform.java @@ -27,8 +27,6 @@ import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; import java.util.function.Supplier; -import jdk.internal.javac.PreviewFeature; - /** * A transformation on streams of elements. Transforms are used during * transformation of classfile entities; a transform is provided to a method like @@ -73,9 +71,8 @@ * @param the builder type * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassFileTransform< C extends ClassFileTransform, E extends ClassFileElement, diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFileVersion.java b/src/java.base/share/classes/java/lang/classfile/ClassFileVersion.java index b6ef3e57f61..1916a185cc8 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFileVersion.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFileVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,16 +25,14 @@ package java.lang.classfile; import jdk.internal.classfile.impl.ClassFileVersionImpl; -import jdk.internal.javac.PreviewFeature; /** * Models the classfile version information for a class. Delivered as a {@link * java.lang.classfile.ClassElement} when traversing the elements of a {@link * ClassModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassFileVersion extends ClassElement permits ClassFileVersionImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/ClassHierarchyResolver.java b/src/java.base/share/classes/java/lang/classfile/ClassHierarchyResolver.java index c2719e7aae0..2c612854a64 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassHierarchyResolver.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassHierarchyResolver.java @@ -37,7 +37,6 @@ import jdk.internal.classfile.impl.ClassHierarchyImpl.ClassLoadingClassHierarchyResolver; import jdk.internal.classfile.impl.ClassHierarchyImpl.StaticClassHierarchyResolver; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; import static java.lang.constant.ConstantDescs.CD_Object; import static java.util.Objects.requireNonNull; @@ -46,9 +45,8 @@ * Provides class hierarchy information for generating correct stack maps * during code building. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) @FunctionalInterface public interface ClassHierarchyResolver { @@ -71,9 +69,8 @@ static ClassHierarchyResolver defaultResolver() { /** * Information about a resolved class. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface ClassHierarchyInfo permits ClassHierarchyImpl.ClassHierarchyInfoImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/ClassModel.java b/src/java.base/share/classes/java/lang/classfile/ClassModel.java index 915b662b488..db804348cfe 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassModel.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassModel.java @@ -31,16 +31,14 @@ import java.util.Optional; import jdk.internal.classfile.impl.ClassImpl; -import jdk.internal.javac.PreviewFeature; /** * Models a classfile. The contents of the classfile can be traversed via * a streaming view, or via random access (e.g., * {@link #flags()}), or by freely mixing the two. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassModel extends CompoundElement, AttributedElement permits ClassImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/ClassReader.java b/src/java.base/share/classes/java/lang/classfile/ClassReader.java index 58ee2aae5e5..93f2ac5c810 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassReader.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassReader.java @@ -33,7 +33,6 @@ import java.util.function.Function; import jdk.internal.classfile.impl.ClassReaderImpl; -import jdk.internal.javac.PreviewFeature; /** * Supports reading from a classfile. Methods are provided to read data of @@ -42,9 +41,8 @@ * Encapsulates additional reading context such as mappers for custom attributes * and processing options. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassReader extends ConstantPool permits ClassReaderImpl { @@ -122,7 +120,6 @@ public sealed interface ClassReader extends ConstantPool * @param cls the entry type * @throws ConstantPoolException if the index is out of range of the * constant pool size, or zero, or the entry is not of the given type - * @since 23 */ T readEntryOrNull(int offset, Class cls); diff --git a/src/java.base/share/classes/java/lang/classfile/ClassSignature.java b/src/java.base/share/classes/java/lang/classfile/ClassSignature.java index 5a57144c4ab..0e1329fd167 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassSignature.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassSignature.java @@ -27,27 +27,21 @@ import java.util.List; import jdk.internal.classfile.impl.SignaturesImpl; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; /** * Models the generic signature of a class file, as defined by JVMS {@jvms 4.7.9}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassSignature permits SignaturesImpl.ClassSignatureImpl { /** {@return the type parameters of this class} */ List typeParameters(); - /** - * {@return the instantiation of the superclass in this signature} - * - * @since 23 - */ + /** {@return the instantiation of the superclass in this signature} */ Signature.ClassTypeSig superclassSignature(); /** {@return the instantiation of the interfaces in this signature} */ @@ -60,7 +54,6 @@ public sealed interface ClassSignature * {@return a class signature} * @param superclassSignature the superclass * @param superinterfaceSignatures the interfaces - * @since 23 */ public static ClassSignature of(Signature.ClassTypeSig superclassSignature, Signature.ClassTypeSig... superinterfaceSignatures) { @@ -72,7 +65,6 @@ public static ClassSignature of(Signature.ClassTypeSig superclassSignature, * @param typeParameters the type parameters * @param superclassSignature the superclass * @param superinterfaceSignatures the interfaces - * @since 23 */ public static ClassSignature of(List typeParameters, Signature.ClassTypeSig superclassSignature, diff --git a/src/java.base/share/classes/java/lang/classfile/ClassTransform.java b/src/java.base/share/classes/java/lang/classfile/ClassTransform.java index f512683a9b6..82b61a15089 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassTransform.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassTransform.java @@ -30,7 +30,6 @@ import java.util.function.Supplier; import jdk.internal.classfile.impl.TransformImpl; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -39,9 +38,8 @@ * * @see ClassFileTransform * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) @FunctionalInterface public non-sealed interface ClassTransform extends ClassFileTransform { diff --git a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java index 11e83550d23..1a074c1554a 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java @@ -39,7 +39,6 @@ import java.util.function.Consumer; import jdk.internal.classfile.impl.*; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; import static jdk.internal.classfile.impl.BytecodeHelpers.handleDescToHandleInfo; @@ -75,9 +74,8 @@ * * @see CodeTransform * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CodeBuilder extends ClassFileBuilder permits CodeBuilder.BlockCodeBuilder, ChainedCodeBuilder, TerminalCodeBuilder, NonterminalCodeBuilder { @@ -149,9 +147,8 @@ default CodeBuilder transforming(CodeTransform transform, Consumer /** * A builder for blocks of code. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface BlockCodeBuilder extends CodeBuilder permits BlockCodeBuilderImpl { /** @@ -290,9 +287,8 @@ default CodeBuilder ifThenElse(Opcode opcode, * * @see #trying * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface CatchBuilder permits CatchBuilderImpl { /** * Adds a catch block that catches an exception of the given type. @@ -385,7 +381,6 @@ default CodeBuilder trying(Consumer tryHandler, * @return this builder * @throws IllegalArgumentException if {@code tk} is {@link TypeKind#VOID void} * or {@code slot} is out of range - * @since 23 */ default CodeBuilder loadLocal(TypeKind tk, int slot) { return with(LoadInstruction.of(tk, slot)); @@ -398,7 +393,6 @@ default CodeBuilder loadLocal(TypeKind tk, int slot) { * @return this builder * @throws IllegalArgumentException if {@code tk} is {@link TypeKind#VOID void} * or {@code slot} is out of range - * @since 23 */ default CodeBuilder storeLocal(TypeKind tk, int slot) { return with(StoreInstruction.of(tk, slot)); @@ -410,7 +404,6 @@ default CodeBuilder storeLocal(TypeKind tk, int slot) { * @param op the branch opcode * @param target the branch target * @return this builder - * @since 23 */ default CodeBuilder branch(Opcode op, Label target) { return with(BranchInstruction.of(op, target)); @@ -420,7 +413,6 @@ default CodeBuilder branch(Opcode op, Label target) { * Generate return instruction * @param tk the return type * @return this builder - * @since 23 */ default CodeBuilder return_(TypeKind tk) { return with(ReturnInstruction.of(tk)); @@ -432,7 +424,6 @@ default CodeBuilder return_(TypeKind tk) { * @param opcode the field access opcode * @param ref the field reference * @return this builder - * @since 23 */ default CodeBuilder fieldAccess(Opcode opcode, FieldRefEntry ref) { return with(FieldInstruction.of(opcode, ref)); @@ -446,7 +437,6 @@ default CodeBuilder fieldAccess(Opcode opcode, FieldRefEntry ref) { * @param name the field name * @param type the field type * @return this builder - * @since 23 */ default CodeBuilder fieldAccess(Opcode opcode, ClassDesc owner, String name, ClassDesc type) { return fieldAccess(opcode, constantPool().fieldRefEntry(owner, name, type)); @@ -458,7 +448,6 @@ default CodeBuilder fieldAccess(Opcode opcode, ClassDesc owner, String name, Cla * @param opcode the invoke opcode * @param ref the interface method or method reference * @return this builder - * @since 23 */ default CodeBuilder invoke(Opcode opcode, MemberRefEntry ref) { return with(InvokeInstruction.of(opcode, ref)); @@ -473,7 +462,6 @@ default CodeBuilder invoke(Opcode opcode, MemberRefEntry ref) { * @param desc the method type * @param isInterface the interface method invocation indication * @return this builder - * @since 23 */ default CodeBuilder invoke(Opcode opcode, ClassDesc owner, String name, MethodTypeDesc desc, boolean isInterface) { return invoke(opcode, @@ -485,7 +473,6 @@ default CodeBuilder invoke(Opcode opcode, ClassDesc owner, String name, MethodTy * Generate an instruction to load from an array * @param tk the array element type * @return this builder - * @since 23 */ default CodeBuilder arrayLoad(TypeKind tk) { Opcode opcode = BytecodeHelpers.arrayLoadOpcode(tk); @@ -496,7 +483,6 @@ default CodeBuilder arrayLoad(TypeKind tk) { * Generate an instruction to store into an array * @param tk the array element type * @return this builder - * @since 23 */ default CodeBuilder arrayStore(TypeKind tk) { Opcode opcode = BytecodeHelpers.arrayStoreOpcode(tk); @@ -510,7 +496,6 @@ default CodeBuilder arrayStore(TypeKind tk) { * @return this builder * @throws IllegalArgumentException for conversions of {@link TypeKind#VOID void} or * {@link TypeKind#REFERENCE reference} - * @since 23 */ default CodeBuilder conversion(TypeKind fromType, TypeKind toType) { var computationalFrom = fromType.asLoadable(); @@ -566,7 +551,6 @@ default CodeBuilder conversion(TypeKind fromType, TypeKind toType) { * Generate an instruction pushing a constant onto the operand stack * @param value the constant value * @return this builder - * @since 23 */ default CodeBuilder loadConstant(ConstantDesc value) { //avoid switch expressions here @@ -1740,7 +1724,6 @@ default CodeBuilder ineg() { * * @param target the target type * @return this builder - * @since 23 */ default CodeBuilder instanceOf(ClassEntry target) { return with(TypeCheckInstruction.of(Opcode.INSTANCEOF, target)); @@ -1756,7 +1739,6 @@ default CodeBuilder instanceOf(ClassEntry target) { * @param target the target type * @return this builder * @throws IllegalArgumentException if {@code target} represents a primitive type - * @since 23 */ default CodeBuilder instanceOf(ClassDesc target) { return instanceOf(constantPool().classEntry(target)); diff --git a/src/java.base/share/classes/java/lang/classfile/CodeElement.java b/src/java.base/share/classes/java/lang/classfile/CodeElement.java index 1cec4b8e604..63669d41014 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeElement.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,8 +28,6 @@ import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute; import java.lang.classfile.attribute.StackMapTableAttribute; -import jdk.internal.javac.PreviewFeature; - /** * A marker interface for elements that can appear when traversing * a {@link CodeModel} or be presented to a {@link CodeBuilder}. Code elements @@ -39,9 +37,8 @@ * exception metadata, label target metadata, etc. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CodeElement extends ClassFileElement permits Instruction, PseudoInstruction, CustomAttribute, RuntimeVisibleTypeAnnotationsAttribute, RuntimeInvisibleTypeAnnotationsAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/CodeModel.java b/src/java.base/share/classes/java/lang/classfile/CodeModel.java index 759aacc18c9..644f7660564 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeModel.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeModel.java @@ -31,15 +31,13 @@ import java.util.Optional; import jdk.internal.classfile.impl.BufferedCodeBuilder; -import jdk.internal.javac.PreviewFeature; /** * Models the body of a method (the {@code Code} attribute). The instructions * of the method body are accessed via a streaming view. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CodeModel extends CompoundElement, AttributedElement, MethodElement permits CodeAttribute, BufferedCodeBuilder.Model { diff --git a/src/java.base/share/classes/java/lang/classfile/CodeTransform.java b/src/java.base/share/classes/java/lang/classfile/CodeTransform.java index 0474e0c9c67..b76c02bf5fb 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeTransform.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeTransform.java @@ -28,7 +28,6 @@ import java.util.function.Supplier; import jdk.internal.classfile.impl.TransformImpl; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -37,9 +36,8 @@ * * @see ClassFileTransform * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) @FunctionalInterface public non-sealed interface CodeTransform extends ClassFileTransform { diff --git a/src/java.base/share/classes/java/lang/classfile/CompoundElement.java b/src/java.base/share/classes/java/lang/classfile/CompoundElement.java index 5dfeac6f00d..38d149623e1 100644 --- a/src/java.base/share/classes/java/lang/classfile/CompoundElement.java +++ b/src/java.base/share/classes/java/lang/classfile/CompoundElement.java @@ -34,8 +34,6 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -import jdk.internal.javac.PreviewFeature; - /** * A {@link ClassFileElement} that has complex structure defined in terms of * other classfile elements, such as a method, field, method body, or entire @@ -46,9 +44,8 @@ * @param the element type * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CompoundElement extends ClassFileElement, Iterable permits ClassModel, CodeModel, FieldModel, MethodModel, jdk.internal.classfile.impl.AbstractUnboundModel { diff --git a/src/java.base/share/classes/java/lang/classfile/CustomAttribute.java b/src/java.base/share/classes/java/lang/classfile/CustomAttribute.java index 9fe492dc22c..f47ce9f055b 100644 --- a/src/java.base/share/classes/java/lang/classfile/CustomAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/CustomAttribute.java @@ -24,7 +24,8 @@ */ package java.lang.classfile; -import jdk.internal.javac.PreviewFeature; +import java.lang.classfile.constantpool.Utf8Entry; +import jdk.internal.classfile.impl.TemporaryConstantPool; /** * Models a non-standard attribute of a classfile. Clients should extend @@ -33,9 +34,8 @@ * format and the {@linkplain CustomAttribute} representation. * @param the custom attribute type * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public abstract non-sealed class CustomAttribute> implements Attribute, CodeElement, ClassElement, MethodElement, FieldElement { @@ -55,8 +55,8 @@ public final AttributeMapper attributeMapper() { } @Override - public final String attributeName() { - return mapper.name(); + public Utf8Entry attributeName() { + return TemporaryConstantPool.INSTANCE.utf8Entry(mapper.name()); } @Override diff --git a/src/java.base/share/classes/java/lang/classfile/FieldBuilder.java b/src/java.base/share/classes/java/lang/classfile/FieldBuilder.java index d3183644657..c473e09cab7 100644 --- a/src/java.base/share/classes/java/lang/classfile/FieldBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/FieldBuilder.java @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.AccessFlagsImpl; import jdk.internal.classfile.impl.ChainedFieldBuilder; import jdk.internal.classfile.impl.TerminalFieldBuilder; -import jdk.internal.javac.PreviewFeature; /** * A builder for fields. Builders are not created directly; they are passed @@ -43,9 +42,8 @@ * * @see FieldTransform * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface FieldBuilder extends ClassFileBuilder permits TerminalFieldBuilder, ChainedFieldBuilder { diff --git a/src/java.base/share/classes/java/lang/classfile/FieldElement.java b/src/java.base/share/classes/java/lang/classfile/FieldElement.java index b4af9971981..a2c1b22751e 100644 --- a/src/java.base/share/classes/java/lang/classfile/FieldElement.java +++ b/src/java.base/share/classes/java/lang/classfile/FieldElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +26,13 @@ import java.lang.classfile.attribute.*; -import jdk.internal.javac.PreviewFeature; - /** * A marker interface for elements that can appear when traversing * a {@link FieldModel} or be presented to a {@link FieldBuilder}. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface FieldElement extends ClassFileElement permits AccessFlags, CustomAttribute, ConstantValueAttribute, DeprecatedAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/FieldModel.java b/src/java.base/share/classes/java/lang/classfile/FieldModel.java index c45f3e88d5d..89fa1e192b0 100644 --- a/src/java.base/share/classes/java/lang/classfile/FieldModel.java +++ b/src/java.base/share/classes/java/lang/classfile/FieldModel.java @@ -32,16 +32,14 @@ import jdk.internal.classfile.impl.BufferedFieldBuilder; import jdk.internal.classfile.impl.FieldImpl; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a field. The contents of the field can be traversed via * a streaming view, or via random access (e.g., * {@link #flags()}), or by freely mixing the two. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface FieldModel extends CompoundElement, AttributedElement, ClassElement permits BufferedFieldBuilder.Model, FieldImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/FieldTransform.java b/src/java.base/share/classes/java/lang/classfile/FieldTransform.java index 78a6f5ead2f..90313ae48f0 100644 --- a/src/java.base/share/classes/java/lang/classfile/FieldTransform.java +++ b/src/java.base/share/classes/java/lang/classfile/FieldTransform.java @@ -29,7 +29,6 @@ import java.util.function.Supplier; import jdk.internal.classfile.impl.TransformImpl; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -38,9 +37,8 @@ * * @see ClassFileTransform * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) @FunctionalInterface public non-sealed interface FieldTransform extends ClassFileTransform { diff --git a/src/java.base/share/classes/java/lang/classfile/Instruction.java b/src/java.base/share/classes/java/lang/classfile/Instruction.java index 210c1e1b0da..2fe0ec5a588 100644 --- a/src/java.base/share/classes/java/lang/classfile/Instruction.java +++ b/src/java.base/share/classes/java/lang/classfile/Instruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,14 +28,12 @@ import java.lang.classfile.instruction.*; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models an executable instruction in a method body. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Instruction extends CodeElement permits ArrayLoadInstruction, ArrayStoreInstruction, BranchInstruction, ConstantInstruction, ConvertInstruction, DiscontinuedInstruction, diff --git a/src/java.base/share/classes/java/lang/classfile/Interfaces.java b/src/java.base/share/classes/java/lang/classfile/Interfaces.java index ff1dda17de8..2c0e5b2e54b 100644 --- a/src/java.base/share/classes/java/lang/classfile/Interfaces.java +++ b/src/java.base/share/classes/java/lang/classfile/Interfaces.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,15 +31,13 @@ import jdk.internal.classfile.impl.InterfacesImpl; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models the interfaces of a class. Delivered as a {@link * java.lang.classfile.ClassElement} when traversing a {@link ClassModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Interfaces extends ClassElement permits InterfacesImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/Label.java b/src/java.base/share/classes/java/lang/classfile/Label.java index 5069b935935..e958e116084 100644 --- a/src/java.base/share/classes/java/lang/classfile/Label.java +++ b/src/java.base/share/classes/java/lang/classfile/Label.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.lang.classfile; import jdk.internal.classfile.impl.LabelImpl; -import jdk.internal.javac.PreviewFeature; /** * A marker for a position within the instructions of a method body. The @@ -40,9 +39,8 @@ * can be bound to the current position within a {@linkplain CodeBuilder} via * {@link CodeBuilder#labelBinding(Label)} or {@link CodeBuilder#with(ClassFileElement)}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Label permits LabelImpl { } diff --git a/src/java.base/share/classes/java/lang/classfile/MethodBuilder.java b/src/java.base/share/classes/java/lang/classfile/MethodBuilder.java index 6607d19b0ac..747cbe2e107 100644 --- a/src/java.base/share/classes/java/lang/classfile/MethodBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/MethodBuilder.java @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.AccessFlagsImpl; import jdk.internal.classfile.impl.ChainedMethodBuilder; import jdk.internal.classfile.impl.TerminalMethodBuilder; -import jdk.internal.javac.PreviewFeature; /** * A builder for methods. Builders are not created directly; they are passed @@ -43,9 +42,8 @@ * * @see MethodTransform * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodBuilder extends ClassFileBuilder permits ChainedMethodBuilder, TerminalMethodBuilder { diff --git a/src/java.base/share/classes/java/lang/classfile/MethodElement.java b/src/java.base/share/classes/java/lang/classfile/MethodElement.java index dd23548c360..77254a6a82c 100644 --- a/src/java.base/share/classes/java/lang/classfile/MethodElement.java +++ b/src/java.base/share/classes/java/lang/classfile/MethodElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +26,13 @@ import java.lang.classfile.attribute.*; -import jdk.internal.javac.PreviewFeature; - /** * A marker interface for elements that can appear when traversing * a {@link MethodModel} or be presented to a {@link MethodBuilder}. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodElement extends ClassFileElement permits AccessFlags, CodeModel, CustomAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/MethodModel.java b/src/java.base/share/classes/java/lang/classfile/MethodModel.java index 568036e464d..d88051a5eb3 100644 --- a/src/java.base/share/classes/java/lang/classfile/MethodModel.java +++ b/src/java.base/share/classes/java/lang/classfile/MethodModel.java @@ -32,16 +32,14 @@ import jdk.internal.classfile.impl.BufferedMethodBuilder; import jdk.internal.classfile.impl.MethodImpl; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a method. The contents of the method can be traversed via * a streaming view, or via random access (e.g., * {@link #flags()}), or by freely mixing the two. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodModel extends CompoundElement, AttributedElement, ClassElement permits BufferedMethodBuilder.Model, MethodImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/MethodSignature.java b/src/java.base/share/classes/java/lang/classfile/MethodSignature.java index 7235c368a45..e3889395e32 100644 --- a/src/java.base/share/classes/java/lang/classfile/MethodSignature.java +++ b/src/java.base/share/classes/java/lang/classfile/MethodSignature.java @@ -29,16 +29,14 @@ import jdk.internal.classfile.impl.SignaturesImpl; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; /** * Models the generic signature of a method, as defined by JVMS {@jvms 4.7.9}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodSignature permits SignaturesImpl.MethodSignatureImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/MethodTransform.java b/src/java.base/share/classes/java/lang/classfile/MethodTransform.java index bf5786f3dc7..865fadbae87 100644 --- a/src/java.base/share/classes/java/lang/classfile/MethodTransform.java +++ b/src/java.base/share/classes/java/lang/classfile/MethodTransform.java @@ -29,7 +29,6 @@ import java.util.function.Supplier; import jdk.internal.classfile.impl.TransformImpl; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -38,9 +37,8 @@ * * @see ClassFileTransform * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) @FunctionalInterface public non-sealed interface MethodTransform extends ClassFileTransform { diff --git a/src/java.base/share/classes/java/lang/classfile/Opcode.java b/src/java.base/share/classes/java/lang/classfile/Opcode.java index 735510dbcea..4d333400001 100644 --- a/src/java.base/share/classes/java/lang/classfile/Opcode.java +++ b/src/java.base/share/classes/java/lang/classfile/Opcode.java @@ -25,7 +25,6 @@ package java.lang.classfile; import jdk.internal.classfile.impl.RawBytecodeHelper; -import jdk.internal.javac.PreviewFeature; /** * Describes the opcodes of the JVM instruction set, as described in JVMS {@jvms 6.5}. @@ -35,9 +34,8 @@ * @see Instruction * @see PseudoInstruction * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public enum Opcode { /** Do nothing */ @@ -697,9 +695,8 @@ public enum Opcode { /** * Kinds of opcodes. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public static enum Kind { /** diff --git a/src/java.base/share/classes/java/lang/classfile/PseudoInstruction.java b/src/java.base/share/classes/java/lang/classfile/PseudoInstruction.java index b152756acfd..456bce04c80 100644 --- a/src/java.base/share/classes/java/lang/classfile/PseudoInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/PseudoInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,7 +33,6 @@ import java.lang.classfile.instruction.LocalVariableType; import jdk.internal.classfile.impl.AbstractPseudoInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models metadata about a {@link CodeAttribute}, such as entries in the @@ -43,9 +42,8 @@ * pseudo-instructions can be disabled by modifying the value of classfile * options (e.g., {@link ClassFile.DebugElementsOption}). * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface PseudoInstruction extends CodeElement permits CharacterRange, ExceptionCatch, LabelTarget, LineNumber, LocalVariable, LocalVariableType, AbstractPseudoInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/Signature.java b/src/java.base/share/classes/java/lang/classfile/Signature.java index 7255a41528c..ad2dca0ad46 100644 --- a/src/java.base/share/classes/java/lang/classfile/Signature.java +++ b/src/java.base/share/classes/java/lang/classfile/Signature.java @@ -30,7 +30,6 @@ import jdk.internal.classfile.impl.SignaturesImpl; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -38,9 +37,8 @@ * Models generic Java type signatures, as defined in JVMS {@jvms 4.7.9.1}. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Signature { /** {@return the raw signature string} */ @@ -71,9 +69,8 @@ public static Signature of(ClassDesc classDesc) { /** * Models the signature of a primitive type or void * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface BaseTypeSig extends Signature permits SignaturesImpl.BaseTypeSigImpl { @@ -108,9 +105,8 @@ public static BaseTypeSig of(char baseType) { * type variable, or array type. * * @sealedGraph - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RefTypeSig extends Signature permits ArrayTypeSig, ClassTypeSig, TypeVarSig { @@ -119,9 +115,8 @@ public sealed interface RefTypeSig /** * Models the signature of a possibly-parameterized class or interface type. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassTypeSig extends RefTypeSig, ThrowableSig permits SignaturesImpl.ClassTypeSigImpl { @@ -187,31 +182,27 @@ public static ClassTypeSig of(ClassTypeSig outerType, String className, TypeArg. * Models the type argument. * * @sealedGraph - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface TypeArg { /** * Models an unbounded type argument {@code *}. - * @since 23 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Unbounded extends TypeArg permits SignaturesImpl.UnboundedTypeArgImpl { } /** * Models a type argument with an explicit bound type. - * @since 23 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Bounded extends TypeArg permits SignaturesImpl.TypeArgImpl { /** * Models a type argument's wildcard indicator. - * @since 23 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public enum WildcardIndicator { /** @@ -243,7 +234,6 @@ public enum WildcardIndicator { /** * {@return a bounded type arg} * @param boundType the bound - * @since 23 */ public static TypeArg.Bounded of(RefTypeSig boundType) { requireNonNull(boundType); @@ -252,7 +242,6 @@ public static TypeArg.Bounded of(RefTypeSig boundType) { /** * {@return an unbounded type arg} - * @since 23 */ public static TypeArg.Unbounded unbounded() { return SignaturesImpl.UnboundedTypeArgImpl.INSTANCE; @@ -261,7 +250,6 @@ public static TypeArg.Unbounded unbounded() { /** * {@return an upper-bounded type arg} * @param boundType the upper bound - * @since 23 */ public static TypeArg.Bounded extendsOf(RefTypeSig boundType) { requireNonNull(boundType); @@ -271,7 +259,6 @@ public static TypeArg.Bounded extendsOf(RefTypeSig boundType) { /** * {@return a lower-bounded type arg} * @param boundType the lower bound - * @since 23 */ public static TypeArg.Bounded superOf(RefTypeSig boundType) { requireNonNull(boundType); @@ -282,7 +269,6 @@ public static TypeArg.Bounded superOf(RefTypeSig boundType) { * {@return a bounded type arg} * @param wildcard the wild card * @param boundType optional bound type - * @since 23 */ public static TypeArg.Bounded bounded(Bounded.WildcardIndicator wildcard, RefTypeSig boundType) { requireNonNull(wildcard); @@ -294,9 +280,8 @@ public static TypeArg.Bounded bounded(Bounded.WildcardIndicator wildcard, RefTyp /** * Models the signature of a type variable. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface TypeVarSig extends RefTypeSig, ThrowableSig permits SignaturesImpl.TypeVarSigImpl { @@ -316,9 +301,8 @@ public static TypeVarSig of(String identifier) { /** * Models the signature of an array type. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ArrayTypeSig extends RefTypeSig permits SignaturesImpl.ArrayTypeSigImpl { @@ -352,9 +336,8 @@ public static ArrayTypeSig of(int dims, Signature componentSignature) { /** * Models a signature for a type parameter of a generic class or method. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface TypeParam permits SignaturesImpl.TypeParamImpl { @@ -398,9 +381,8 @@ public static TypeParam of(String identifier, Optional classBound, R * Models a signature for a throwable type. * * @sealedGraph - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ThrowableSig extends Signature { } } diff --git a/src/java.base/share/classes/java/lang/classfile/Superclass.java b/src/java.base/share/classes/java/lang/classfile/Superclass.java index a69fac6341a..fe30fe8a8e3 100644 --- a/src/java.base/share/classes/java/lang/classfile/Superclass.java +++ b/src/java.base/share/classes/java/lang/classfile/Superclass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -27,15 +27,13 @@ import java.lang.classfile.constantpool.ClassEntry; import jdk.internal.classfile.impl.SuperclassImpl; -import jdk.internal.javac.PreviewFeature; /** * Models the superclass of a class. Delivered as a {@link * java.lang.classfile.ClassElement} when traversing a {@link ClassModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Superclass extends ClassElement permits SuperclassImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java b/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java index 38e5ea09a93..9353b30a643 100644 --- a/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java +++ b/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java @@ -31,7 +31,6 @@ import jdk.internal.classfile.impl.TargetInfoImpl; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; import static java.lang.classfile.TypeAnnotation.TargetInfo.*; @@ -52,18 +51,16 @@ * @see RuntimeVisibleTypeAnnotationsAttribute * @see RuntimeInvisibleTypeAnnotationsAttribute * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface TypeAnnotation permits UnboundAttribute.UnboundTypeAnnotation { /** * The kind of target on which the annotation appears, as defined in JVMS {@jvms 4.7.20.1}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public enum TargetType { /** For annotations on a class type parameter declaration. */ CLASS_TYPE_PARAMETER(TARGET_CLASS_TYPE_PARAMETER, 1), @@ -193,9 +190,8 @@ static TypeAnnotation of(TargetInfo targetInfo, List targetPa * Specifies which type in a declaration or expression is being annotated. * * @sealedGraph - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface TargetInfo { /** @@ -611,9 +607,8 @@ static TypeArgumentTarget ofMethodReferenceTypeArgument(Label target, int typeAr * parameter of a generic class, generic interface, generic method, or * generic constructor. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface TypeParameterTarget extends TargetInfo permits TargetInfoImpl.TypeParameterTargetImpl { @@ -630,9 +625,8 @@ sealed interface TypeParameterTarget extends TargetInfo * Indicates that an annotation appears on a type in the extends or implements * clause of a class or interface declaration. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface SupertypeTarget extends TargetInfo permits TargetInfoImpl.SupertypeTargetImpl { @@ -654,9 +648,8 @@ sealed interface SupertypeTarget extends TargetInfo * type parameter declaration of a generic class, interface, method, or * constructor. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface TypeParameterBoundTarget extends TargetInfo permits TargetInfoImpl.TypeParameterBoundTargetImpl { @@ -680,9 +673,8 @@ sealed interface TypeParameterBoundTarget extends TargetInfo * declaration, the return type of a method, the type of a newly constructed * object, or the receiver type of a method or constructor. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface EmptyTarget extends TargetInfo permits TargetInfoImpl.EmptyTargetImpl { } @@ -691,9 +683,8 @@ sealed interface EmptyTarget extends TargetInfo * Indicates that an annotation appears on the type in a formal parameter * declaration of a method, constructor, or lambda expression. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface FormalParameterTarget extends TargetInfo permits TargetInfoImpl.FormalParameterTargetImpl { @@ -710,9 +701,8 @@ sealed interface FormalParameterTarget extends TargetInfo * Indicates that an annotation appears on the i'th type in the throws * clause of a method or constructor declaration. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface ThrowsTarget extends TargetInfo permits TargetInfoImpl.ThrowsTargetImpl { @@ -730,9 +720,8 @@ sealed interface ThrowsTarget extends TargetInfo * Indicates that an annotation appears on the type in a local variable declaration, * including a variable declared as a resource in a try-with-resources statement. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface LocalVarTarget extends TargetInfo permits TargetInfoImpl.LocalVarTargetImpl { @@ -747,9 +736,8 @@ sealed interface LocalVarTarget extends TargetInfo * has a value, and the index into the local variable array of the current * frame at which that local variable can be found. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface LocalVarTargetInfo permits TargetInfoImpl.LocalVarTargetInfoImpl { @@ -794,9 +782,8 @@ static LocalVarTargetInfo of(Label startLabel, Label endLabel, int index) { * Indicates that an annotation appears on the i'th type in an exception parameter * declaration. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface CatchTarget extends TargetInfo permits TargetInfoImpl.CatchTargetImpl { @@ -813,9 +800,8 @@ sealed interface CatchTarget extends TargetInfo * Indicates that an annotation appears on either the type in an instanceof expression * or a new expression, or the type before the :: in a method reference expression. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OffsetTarget extends TargetInfo permits TargetInfoImpl.OffsetTargetImpl { @@ -835,9 +821,8 @@ sealed interface OffsetTarget extends TargetInfo * expression, an explicit constructor invocation statement, a method invocation expression, or a method reference * expression. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface TypeArgumentTarget extends TargetInfo permits TargetInfoImpl.TypeArgumentTargetImpl { @@ -871,18 +856,16 @@ sealed interface TypeArgumentTarget extends TargetInfo * JVMS: Type_path structure identifies which part of the type is annotated, * as defined in JVMS {@jvms 4.7.20.2} * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface TypePathComponent permits UnboundAttribute.TypePathComponentImpl { /** * Type path kind, as defined in JVMS {@jvms 4.7.20.2} * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public enum Kind { /** Annotation is deeper in an array type */ diff --git a/src/java.base/share/classes/java/lang/classfile/TypeKind.java b/src/java.base/share/classes/java/lang/classfile/TypeKind.java index bdbea7c8c54..5a6475aa801 100644 --- a/src/java.base/share/classes/java/lang/classfile/TypeKind.java +++ b/src/java.base/share/classes/java/lang/classfile/TypeKind.java @@ -30,7 +30,6 @@ import java.lang.constant.ConstantDescs; import java.lang.invoke.TypeDescriptor; -import jdk.internal.javac.PreviewFeature; import jdk.internal.vm.annotation.Stable; /** @@ -54,9 +53,8 @@ * * @jvms 2.2 Data Types * @jvms 2.11.1 Types and the Java Virtual Machine - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public enum TypeKind { // Elements are grouped so frequently used switch ranges such as // primitives (boolean - double) and computational (int - void) are together. @@ -166,7 +164,6 @@ private ClassDesc fetchUpperBound() { /** * {@return the code used by the {@link Opcode#NEWARRAY newarray} instruction to create an array * of this component type, or {@code -1} if this type is not supported by {@code newarray}} - * @since 23 * @jvms 6.5.newarray newarray */ public int newarrayCode() { @@ -198,7 +195,6 @@ public TypeKind asLoadable() { * newarray}} * @param newarrayCode the operand of the {@code newarray} instruction * @throws IllegalArgumentException if the code is invalid - * @since 23 * @jvms 6.5.newarray newarray */ public static TypeKind fromNewarrayCode(int newarrayCode) { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/AnnotationDefaultAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/AnnotationDefaultAttribute.java index 4f147b0d63a..206c0a84087 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/AnnotationDefaultAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/AnnotationDefaultAttribute.java @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code AnnotationDefault} attribute (JVMS {@jvms 4.7.22}), which can @@ -46,9 +45,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface AnnotationDefaultAttribute extends Attribute, MethodElement permits BoundAttribute.BoundAnnotationDefaultAttr, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/BootstrapMethodsAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/BootstrapMethodsAttribute.java index 26ef1d3ddaf..bbea96dc162 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/BootstrapMethodsAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/BootstrapMethodsAttribute.java @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code BootstrapMethods} attribute (JVMS {@jvms 4.7.23}), which serves as @@ -45,9 +44,8 @@ *

* The attribute was introduced in the Java SE Platform version 7. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface BootstrapMethodsAttribute extends Attribute permits BoundAttribute.BoundBootstrapMethodsAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeInfo.java index 126ba1037ce..ab37c372c29 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeInfo.java @@ -27,14 +27,12 @@ import java.lang.classfile.instruction.CharacterRange; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models a single character range in the {@link CharacterRangeTableAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CharacterRangeInfo permits UnboundAttribute.UnboundCharacterRangeInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeTableAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeTableAttribute.java index a4b79be62f0..42a8443f2f6 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeTableAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeTableAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +30,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * The CharacterRangeTable attribute is an optional variable-length attribute in @@ -58,9 +57,8 @@ *

* The attribute permits multiple instances in a given location. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CharacterRangeTableAttribute extends Attribute permits BoundAttribute.BoundCharacterRangeTableAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/CodeAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/CodeAttribute.java index 3342c2648ed..9bc9e975d12 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/CodeAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/CodeAttribute.java @@ -30,7 +30,6 @@ import java.lang.classfile.Label; import jdk.internal.classfile.impl.BoundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code Code} attribute (JVMS {@jvms 4.7.3}), appears on non-native, @@ -42,9 +41,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CodeAttribute extends Attribute, CodeModel permits BoundAttribute.BoundCodeAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/CompilationIDAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/CompilationIDAttribute.java index 292b449c628..8311a8e045c 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/CompilationIDAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/CompilationIDAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code CompilationID} attribute (@@@ need reference), which can @@ -44,9 +43,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CompilationIDAttribute extends Attribute, ClassElement permits BoundAttribute.BoundCompilationIDAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ConstantValueAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/ConstantValueAttribute.java index cd874648551..54f4742ab0c 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ConstantValueAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ConstantValueAttribute.java @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code ConstantValue} attribute (JVMS {@jvms 4.7.2}), which can appear on @@ -44,9 +43,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ConstantValueAttribute extends Attribute, FieldElement permits BoundAttribute.BoundConstantValueAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/DeprecatedAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/DeprecatedAttribute.java index 47c85c4b6c1..9e470711e1f 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/DeprecatedAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/DeprecatedAttribute.java @@ -31,7 +31,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code Deprecated} attribute (JVMS {@jvms 4.7.15}), which can appear on @@ -41,9 +40,8 @@ *

* The attribute permits multiple instances in a given location. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface DeprecatedAttribute extends Attribute, ClassElement, MethodElement, FieldElement diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/EnclosingMethodAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/EnclosingMethodAttribute.java index c760fdee04b..06ded8c82a5 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/EnclosingMethodAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/EnclosingMethodAttribute.java @@ -37,7 +37,6 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code EnclosingMethod} attribute (JVMS {@jvms 4.7.7}), which can appear @@ -51,9 +50,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface EnclosingMethodAttribute extends Attribute, ClassElement permits BoundAttribute.BoundEnclosingMethodAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ExceptionsAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/ExceptionsAttribute.java index 91f07d94de9..67732e10e81 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ExceptionsAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ExceptionsAttribute.java @@ -34,7 +34,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code Exceptions} attribute (JVMS {@jvms 4.7.5}), which can appear on @@ -46,9 +45,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ExceptionsAttribute extends Attribute, MethodElement permits BoundAttribute.BoundExceptionsAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/InnerClassInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/InnerClassInfo.java index fca8cce7faa..6965d5fdfd2 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/InnerClassInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/InnerClassInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,14 +34,12 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a single inner class in the {@link InnerClassesAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface InnerClassInfo permits UnboundAttribute.UnboundInnerClassInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/InnerClassesAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/InnerClassesAttribute.java index 3b5d63822c4..463a29f9398 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/InnerClassesAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/InnerClassesAttribute.java @@ -31,7 +31,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code InnerClasses} attribute (JVMS {@jvms 4.7.6}), which can @@ -43,9 +42,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface InnerClassesAttribute extends Attribute, ClassElement permits BoundAttribute.BoundInnerClassesAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/LineNumberInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/LineNumberInfo.java index 6e83284f6b1..7e148cec9c1 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/LineNumberInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/LineNumberInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,12 @@ package java.lang.classfile.attribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models a single line number in the {@link LineNumberTableAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LineNumberInfo permits UnboundAttribute.UnboundLineNumberInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/LineNumberTableAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/LineNumberTableAttribute.java index bb636a8113f..1c00745218a 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/LineNumberTableAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/LineNumberTableAttribute.java @@ -29,7 +29,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code LineNumberTable} attribute (JVMS {@jvms 4.7.12}), which can appear @@ -41,9 +40,8 @@ *

* The attribute permits multiple instances in a given location. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LineNumberTableAttribute extends Attribute permits BoundAttribute.BoundLineNumberTableAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableInfo.java index 177fc842483..2b4030b46a6 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,14 +30,12 @@ import jdk.internal.classfile.impl.BoundLocalVariable; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a single local variable in the {@link LocalVariableTableAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LocalVariableInfo permits UnboundAttribute.UnboundLocalVariableInfo, BoundLocalVariable { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTableAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTableAttribute.java index ad4e732073e..8f44ab2905f 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTableAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTableAttribute.java @@ -29,7 +29,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code LocalVariableTable} attribute (JVMS {@jvms 4.7.13}), which can appear @@ -41,9 +40,8 @@ *

* The attribute permits multiple instances in a given location. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LocalVariableTableAttribute extends Attribute permits BoundAttribute.BoundLocalVariableTableAttribute, UnboundAttribute.UnboundLocalVariableTableAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTypeInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTypeInfo.java index 6ba5b409b5b..e7a137102ae 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTypeInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTypeInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,14 +28,12 @@ import jdk.internal.classfile.impl.BoundLocalVariableType; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models a single local variable in the {@link LocalVariableTypeTableAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LocalVariableTypeInfo permits UnboundAttribute.UnboundLocalVariableTypeInfo, BoundLocalVariableType { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTypeTableAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTypeTableAttribute.java index 084b72d6838..2bf7b7a87b3 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTypeTableAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/LocalVariableTypeTableAttribute.java @@ -30,7 +30,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code LocalVariableTypeTable} attribute (JVMS {@jvms 4.7.14}), which can appear @@ -44,9 +43,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LocalVariableTypeTableAttribute extends Attribute permits BoundAttribute.BoundLocalVariableTypeTableAttribute, UnboundAttribute.UnboundLocalVariableTypeTableAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/MethodParameterInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/MethodParameterInfo.java index b0961bf1476..35301a30284 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/MethodParameterInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/MethodParameterInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,14 +33,12 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a single method parameter in the {@link MethodParametersAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodParameterInfo permits UnboundAttribute.UnboundMethodParameterInfo { /** diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/MethodParametersAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/MethodParametersAttribute.java index 43a43d25bb7..3b3bacbbca5 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/MethodParametersAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/MethodParametersAttribute.java @@ -31,7 +31,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code MethodParameters} attribute (JVMS {@jvms 4.7.24}), which can @@ -45,9 +44,8 @@ *

* The attribute was introduced in the Java SE Platform version 8. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodParametersAttribute extends Attribute, MethodElement permits BoundAttribute.BoundMethodParametersAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleAttribute.java index 7091bbd5c42..07e0f2baa12 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleAttribute.java @@ -43,7 +43,6 @@ import jdk.internal.classfile.impl.ModuleAttributeBuilderImpl; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code Module} attribute (JVMS {@jvms 4.7.25}), which can @@ -57,9 +56,8 @@ *

* The attribute was introduced in the Java SE Platform version 9. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleAttribute extends Attribute, ClassElement permits BoundAttribute.BoundModuleAttribute, UnboundAttribute.UnboundModuleAttribute { @@ -172,9 +170,8 @@ static ModuleAttribute of(ModuleEntry moduleName, /** * A builder for module attributes. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleAttributeBuilder permits ModuleAttributeBuilderImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleExportInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleExportInfo.java index 4a534894e9e..69290c55994 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleExportInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleExportInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,14 +37,12 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a single "exports" declaration in the {@link ModuleAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleExportInfo permits UnboundAttribute.UnboundModuleExportInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleHashInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleHashInfo.java index 0c85dd14125..07616757daa 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleHashInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleHashInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,14 +29,12 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models hash information for a single module in the {@link ModuleHashesAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleHashInfo permits UnboundAttribute.UnboundModuleHashInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleHashesAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleHashesAttribute.java index 0d2eb701484..918d18bda1e 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleHashesAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleHashesAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code ModuleHashes} attribute, which can @@ -68,9 +67,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleHashesAttribute extends Attribute, ClassElement permits BoundAttribute.BoundModuleHashesAttribute, UnboundAttribute.UnboundModuleHashesAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleMainClassAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleMainClassAttribute.java index 67d6e5cc15c..7f06eb0f95b 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleMainClassAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleMainClassAttribute.java @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code ModuleMainClass} attribute (JVMS {@jvms 4.7.27}), which can @@ -47,9 +46,8 @@ *

* The attribute was introduced in the Java SE Platform version 9. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleMainClassAttribute extends Attribute, ClassElement permits BoundAttribute.BoundModuleMainClassAttribute, UnboundAttribute.UnboundModuleMainClassAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleOpenInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleOpenInfo.java index 7c5fe948d78..a16c9973627 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleOpenInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleOpenInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -36,14 +36,12 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a single "opens" declaration in the {@link ModuleAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleOpenInfo permits UnboundAttribute.UnboundModuleOpenInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModulePackagesAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModulePackagesAttribute.java index f2b34ad107d..ec0a65742b4 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModulePackagesAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModulePackagesAttribute.java @@ -34,7 +34,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code ModulePackages} attribute (JVMS {@jvms 4.7.26}), which can @@ -48,9 +47,8 @@ *

* The attribute was introduced in the Java SE Platform version 9. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModulePackagesAttribute extends Attribute, ClassElement permits BoundAttribute.BoundModulePackagesAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleProvideInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleProvideInfo.java index 266c73de04f..ce68848d4dc 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleProvideInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleProvideInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,14 +32,12 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a single "provides" declaration in the {@link ModuleAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleProvideInfo permits UnboundAttribute.UnboundModuleProvideInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleRequireInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleRequireInfo.java index d072d0fead8..578a783f277 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleRequireInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleRequireInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -35,14 +35,12 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a single "requires" declaration in the {@link ModuleAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleRequireInfo permits UnboundAttribute.UnboundModuleRequiresInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleResolutionAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleResolutionAttribute.java index a6b17fa4041..3457cb8073e 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleResolutionAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleResolutionAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +30,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code ModuleResolution} attribute, which can @@ -63,9 +62,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleResolutionAttribute extends Attribute, ClassElement permits BoundAttribute.BoundModuleResolutionAttribute, UnboundAttribute.UnboundModuleResolutionAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleTargetAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleTargetAttribute.java index 226412eccf3..ac390c3d391 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/ModuleTargetAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/ModuleTargetAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code ModuleTarget} attribute, which can @@ -58,9 +57,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleTargetAttribute extends Attribute, ClassElement permits BoundAttribute.BoundModuleTargetAttribute, UnboundAttribute.UnboundModuleTargetAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/NestHostAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/NestHostAttribute.java index 6b69f9cbe08..ccfb61242cd 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/NestHostAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/NestHostAttribute.java @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code NestHost} attribute (JVMS {@jvms 4.7.28}), which can @@ -47,9 +46,8 @@ *

* The attribute was introduced in the Java SE Platform version 11. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface NestHostAttribute extends Attribute, ClassElement permits BoundAttribute.BoundNestHostAttribute, UnboundAttribute.UnboundNestHostAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/NestMembersAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/NestMembersAttribute.java index 8826b4953a5..b01c05542de 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/NestMembersAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/NestMembersAttribute.java @@ -34,7 +34,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code NestMembers} attribute (JVMS {@jvms 4.7.29}), which can @@ -48,9 +47,8 @@ *

* The attribute was introduced in the Java SE Platform version 11. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface NestMembersAttribute extends Attribute, ClassElement permits BoundAttribute.BoundNestMembersAttribute, UnboundAttribute.UnboundNestMembersAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/PermittedSubclassesAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/PermittedSubclassesAttribute.java index 1242bc6e045..dac63c73435 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/PermittedSubclassesAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/PermittedSubclassesAttribute.java @@ -34,7 +34,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code PermittedSubclasses} attribute (JVMS {@jvms 4.7.31}), which can @@ -48,9 +47,8 @@ *

* The attribute was introduced in the Java SE Platform version 17. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface PermittedSubclassesAttribute extends Attribute, ClassElement permits BoundAttribute.BoundPermittedSubclassesAttribute, UnboundAttribute.UnboundPermittedSubclassesAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/RecordAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/RecordAttribute.java index 7ef3b6f41b6..b0c4fa7c61c 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/RecordAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/RecordAttribute.java @@ -31,7 +31,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code Record} attribute (JVMS {@jvms 4.7.30}), which can @@ -45,9 +44,8 @@ *

* The attribute was introduced in the Java SE Platform version 16. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RecordAttribute extends Attribute, ClassElement permits BoundAttribute.BoundRecordAttribute, UnboundAttribute.UnboundRecordAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/RecordComponentInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/RecordComponentInfo.java index ef6385653ed..73e4497915e 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/RecordComponentInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/RecordComponentInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,14 +34,12 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a single record component in the {@link java.lang.classfile.attribute.RecordAttribute}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RecordComponentInfo extends AttributedElement permits BoundRecordComponentInfo, UnboundAttribute.UnboundRecordComponentInfo { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleAnnotationsAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleAnnotationsAttribute.java index 05635af4beb..58903859464 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleAnnotationsAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleAnnotationsAttribute.java @@ -34,7 +34,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code RuntimeInvisibleAnnotations} attribute (JVMS {@jvms 4.7.17}), which @@ -48,9 +47,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RuntimeInvisibleAnnotationsAttribute extends Attribute, ClassElement, MethodElement, FieldElement diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleParameterAnnotationsAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleParameterAnnotationsAttribute.java index edb82c49900..f1c02b77e1e 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleParameterAnnotationsAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleParameterAnnotationsAttribute.java @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code RuntimeInvisibleParameterAnnotations} attribute @@ -46,9 +45,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RuntimeInvisibleParameterAnnotationsAttribute extends Attribute, MethodElement permits BoundAttribute.BoundRuntimeInvisibleParameterAnnotationsAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleTypeAnnotationsAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleTypeAnnotationsAttribute.java index df3a035d620..7500d39fc19 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleTypeAnnotationsAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeInvisibleTypeAnnotationsAttribute.java @@ -35,7 +35,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code RuntimeInvisibleTypeAnnotations} attribute (JVMS {@jvms 4.7.21}), which @@ -50,9 +49,8 @@ *

* The attribute was introduced in the Java SE Platform version 8. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RuntimeInvisibleTypeAnnotationsAttribute extends Attribute, ClassElement, MethodElement, FieldElement, CodeElement diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleAnnotationsAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleAnnotationsAttribute.java index 69095188818..d41fcf3794b 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleAnnotationsAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleAnnotationsAttribute.java @@ -34,7 +34,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code RuntimeVisibleAnnotations} attribute (JVMS {@jvms 4.7.16}), which @@ -48,9 +47,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RuntimeVisibleAnnotationsAttribute extends Attribute, ClassElement, MethodElement, FieldElement diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleParameterAnnotationsAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleParameterAnnotationsAttribute.java index ef58d21f14a..5ed9817eeb9 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleParameterAnnotationsAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleParameterAnnotationsAttribute.java @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code RuntimeVisibleParameterAnnotations} attribute (JVMS {@jvms 4.7.18}), which @@ -46,9 +45,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RuntimeVisibleParameterAnnotationsAttribute extends Attribute, MethodElement permits BoundAttribute.BoundRuntimeVisibleParameterAnnotationsAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleTypeAnnotationsAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleTypeAnnotationsAttribute.java index 20dc89d700c..a4e780c4536 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleTypeAnnotationsAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/RuntimeVisibleTypeAnnotationsAttribute.java @@ -35,7 +35,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code RuntimeVisibleTypeAnnotations} attribute (JVMS {@jvms 4.7.20}), which @@ -50,9 +49,8 @@ *

* The attribute was introduced in the Java SE Platform version 8. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface RuntimeVisibleTypeAnnotationsAttribute extends Attribute, ClassElement, MethodElement, FieldElement, CodeElement diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/SignatureAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/SignatureAttribute.java index ca4cc62852a..8f06e16a1b1 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/SignatureAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/SignatureAttribute.java @@ -31,7 +31,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code Signature} attribute (JVMS {@jvms 4.7.9}), which @@ -46,9 +45,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface SignatureAttribute extends Attribute, ClassElement, MethodElement, FieldElement diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/SourceDebugExtensionAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/SourceDebugExtensionAttribute.java index e181b7fb14a..0e6b7267263 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/SourceDebugExtensionAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/SourceDebugExtensionAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +30,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code SourceDebugExtension} attribute. @@ -43,9 +42,8 @@ *

* The attribute was introduced in the Java SE Platform version 5.0. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface SourceDebugExtensionAttribute extends Attribute, ClassElement permits BoundAttribute.BoundSourceDebugExtensionAttribute, UnboundAttribute.UnboundSourceDebugExtensionAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/SourceFileAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/SourceFileAttribute.java index d6c40058e7b..70f3d1e72ce 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/SourceFileAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/SourceFileAttribute.java @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code SourceFile} attribute (JVMS {@jvms 4.7.10}), which @@ -44,9 +43,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface SourceFileAttribute extends Attribute, ClassElement permits BoundAttribute.BoundSourceFileAttribute, UnboundAttribute.UnboundSourceFileAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/SourceIDAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/SourceIDAttribute.java index 69ff3bf57fd..71fd9d5b059 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/SourceIDAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/SourceIDAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code SourceID} attribute, which can @@ -44,9 +43,8 @@ * Subsequent occurrence of the attribute takes precedence during the attributed * element build or transformation. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface SourceIDAttribute extends Attribute, ClassElement permits BoundAttribute.BoundSourceIDAttribute, UnboundAttribute.UnboundSourceIDAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java index d041a73c58a..920db8ac9d7 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java @@ -32,14 +32,12 @@ import jdk.internal.classfile.impl.StackMapDecoder; import jdk.internal.classfile.impl.TemporaryConstantPool; -import jdk.internal.javac.PreviewFeature; /** * Models stack map frame of {@code StackMapTable} attribute (JVMS {@jvms 4.7.4}). * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface StackMapFrameInfo permits StackMapDecoder.StackMapFrameImpl { @@ -79,9 +77,8 @@ public static StackMapFrameInfo of(Label target, /** * The type of a stack value. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface VerificationTypeInfo { /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#TOP TOP}. */ @@ -124,9 +121,8 @@ sealed interface VerificationTypeInfo { /** * A simple stack value. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public enum SimpleVerificationTypeInfo implements VerificationTypeInfo { /** verification type top */ @@ -166,9 +162,8 @@ public int tag() { /** * A stack value for an object type. Its {@link #tag() tag} is {@value #ITEM_OBJECT}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface ObjectVerificationTypeInfo extends VerificationTypeInfo permits StackMapDecoder.ObjectVerificationTypeInfoImpl { @@ -205,9 +200,8 @@ default ClassDesc classSymbol() { /** * An uninitialized stack value. Its {@link #tag() tag} is {@value #ITEM_UNINITIALIZED}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface UninitializedVerificationTypeInfo extends VerificationTypeInfo permits StackMapDecoder.UninitializedVerificationTypeInfoImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapTableAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapTableAttribute.java index a8aef4795d7..0d577fb6cd5 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapTableAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapTableAttribute.java @@ -31,7 +31,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code StackMapTable} attribute (JVMS {@jvms 4.7.4}), which can appear @@ -43,9 +42,8 @@ *

* The attribute was introduced in the Java SE Platform version 6. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface StackMapTableAttribute extends Attribute, CodeElement permits BoundAttribute.BoundStackMapTableAttribute, UnboundAttribute.UnboundStackMapTableAttribute { diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/SyntheticAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/SyntheticAttribute.java index e5b5da7fbfe..1e6b706ec08 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/SyntheticAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/SyntheticAttribute.java @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.BoundAttribute; import jdk.internal.classfile.impl.UnboundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models the {@code Synthetic} attribute (JVMS {@jvms 4.7.8}), which can appear on @@ -42,9 +41,8 @@ *

* The attribute permits multiple instances in a given location. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface SyntheticAttribute extends Attribute, ClassElement, MethodElement, FieldElement diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/UnknownAttribute.java b/src/java.base/share/classes/java/lang/classfile/attribute/UnknownAttribute.java index 5c1369e1308..ad47f35a856 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/UnknownAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/UnknownAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,14 +31,12 @@ import java.lang.classfile.MethodElement; import jdk.internal.classfile.impl.BoundAttribute; -import jdk.internal.javac.PreviewFeature; /** * Models an unknown attribute on a class, method, or field. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface UnknownAttribute extends Attribute, ClassElement, MethodElement, FieldElement diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/package-info.java b/src/java.base/share/classes/java/lang/classfile/attribute/package-info.java index 3047ef659e5..08bd28cbc58 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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,9 +28,7 @@ * * The {@code java.lang.classfile.attribute} package contains interfaces describing classfile attributes. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) package java.lang.classfile.attribute; -import jdk.internal.javac.PreviewFeature; diff --git a/src/java.base/share/classes/java/lang/classfile/components/ClassPrinter.java b/src/java.base/share/classes/java/lang/classfile/components/ClassPrinter.java index 85768cbe6a4..7237dc54580 100644 --- a/src/java.base/share/classes/java/lang/classfile/components/ClassPrinter.java +++ b/src/java.base/share/classes/java/lang/classfile/components/ClassPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -36,7 +36,6 @@ import java.util.stream.Stream; import jdk.internal.classfile.impl.ClassPrinterImpl; -import jdk.internal.javac.PreviewFeature; /** * A printer of classfiles and its elements. @@ -60,9 +59,8 @@ * Another use case for {@link ClassPrinter} is to simplify writing of automated tests: * {@snippet lang="java" class="PackageSnippets" region="printNodesInTest"} * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public final class ClassPrinter { private ClassPrinter() { @@ -71,9 +69,8 @@ private ClassPrinter() { /** * Level of detail to print or export. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public enum Verbosity { /** @@ -106,9 +103,8 @@ public enum Verbosity { /** * Named, traversable, and printable node parent. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Node { /** @@ -151,9 +147,8 @@ default void toYaml(Consumer out) { /** * A leaf node holding single printable value. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LeafNode extends Node permits ClassPrinterImpl.LeafNodeImpl { @@ -167,9 +162,8 @@ public sealed interface LeafNode extends Node /** * A tree node holding {@link List} of nested nodes. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ListNode extends Node, List permits ClassPrinterImpl.ListNodeImpl { } @@ -179,9 +173,8 @@ public sealed interface ListNode extends Node, List *

* Each {@link Map.Entry#getKey()} == {@link Map.Entry#getValue()}.{@link #name()}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MapNode extends Node, Map permits ClassPrinterImpl.MapNodeImpl { } diff --git a/src/java.base/share/classes/java/lang/classfile/components/ClassRemapper.java b/src/java.base/share/classes/java/lang/classfile/components/ClassRemapper.java index 4f7bd3199d5..4a2808ad4f0 100644 --- a/src/java.base/share/classes/java/lang/classfile/components/ClassRemapper.java +++ b/src/java.base/share/classes/java/lang/classfile/components/ClassRemapper.java @@ -35,7 +35,6 @@ import java.util.function.Function; import jdk.internal.classfile.impl.ClassRemapperImpl; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -55,9 +54,8 @@ * Arrays of reference types are always decomposed, mapped as the base reference * types and composed back to arrays. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassRemapper extends ClassTransform permits ClassRemapperImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/components/CodeLocalsShifter.java b/src/java.base/share/classes/java/lang/classfile/components/CodeLocalsShifter.java index 49838722461..9db85f54a45 100644 --- a/src/java.base/share/classes/java/lang/classfile/components/CodeLocalsShifter.java +++ b/src/java.base/share/classes/java/lang/classfile/components/CodeLocalsShifter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +31,6 @@ import java.lang.reflect.AccessFlag; import jdk.internal.classfile.impl.CodeLocalsShifterImpl; -import jdk.internal.javac.PreviewFeature; /** * {@link CodeLocalsShifter} is a {@link CodeTransform} shifting locals to @@ -39,9 +38,8 @@ * Locals pointing to the receiver or to method arguments slots are never shifted. * All locals pointing beyond the method arguments are re-indexed in order of appearance. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CodeLocalsShifter extends CodeTransform permits CodeLocalsShifterImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/components/CodeRelabeler.java b/src/java.base/share/classes/java/lang/classfile/components/CodeRelabeler.java index 247d712e4f3..4ef82adfdb9 100644 --- a/src/java.base/share/classes/java/lang/classfile/components/CodeRelabeler.java +++ b/src/java.base/share/classes/java/lang/classfile/components/CodeRelabeler.java @@ -32,7 +32,6 @@ import java.util.function.BiFunction; import jdk.internal.classfile.impl.CodeRelabelerImpl; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -46,9 +45,8 @@ * Repeated injection of the same code block must be relabeled, so each instance of * {@link java.lang.classfile.Label} is bound in the target bytecode exactly once. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CodeRelabeler extends CodeTransform permits CodeRelabelerImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/components/CodeStackTracker.java b/src/java.base/share/classes/java/lang/classfile/components/CodeStackTracker.java index 1ee0b0948e1..3761e53ff19 100644 --- a/src/java.base/share/classes/java/lang/classfile/components/CodeStackTracker.java +++ b/src/java.base/share/classes/java/lang/classfile/components/CodeStackTracker.java @@ -31,7 +31,6 @@ import java.util.Optional; import jdk.internal.classfile.impl.CodeStackTrackerImpl; -import jdk.internal.javac.PreviewFeature; /** * {@link CodeStackTracker} is a {@link CodeTransform} tracking stack content @@ -51,9 +50,8 @@ * }); * } * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CodeStackTracker extends CodeTransform permits CodeStackTrackerImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/components/package-info.java b/src/java.base/share/classes/java/lang/classfile/components/package-info.java index 98a0095587d..be650f4c77c 100644 --- a/src/java.base/share/classes/java/lang/classfile/components/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/components/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -111,9 +111,7 @@ * instrumenting transformation: * {@snippet lang="java" class="PackageSnippets" region="classInstrumentation"} * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) package java.lang.classfile.components; -import jdk.internal.javac.PreviewFeature; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java index 6365fc3636a..5255ceb1ef7 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java @@ -27,8 +27,6 @@ import java.lang.classfile.AnnotationValue; import java.lang.constant.ConstantDesc; -import jdk.internal.javac.PreviewFeature; - /** * A constant pool entry that may be used by annotation constant values, * which includes the four kinds of primitive constants and UTF8 constants. @@ -43,9 +41,8 @@ * * @see AnnotationValue.OfConstant * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface AnnotationConstantValueEntry extends PoolEntry permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, Utf8Entry { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java index 9e5f1f52049..2a3bd95da22 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +28,14 @@ import java.lang.constant.ConstantDesc; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Class_info} constant in the constant pool of a * classfile. * @jvms 4.4.1 The CONSTANT_Class_info Structure * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassEntry extends LoadableConstantEntry permits AbstractPoolEntry.ClassEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java index 7c55a09f3f4..72050cd9b8f 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +31,14 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Dynamic_info} constant in the constant pool of a * classfile. * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ConstantDynamicEntry extends DynamicConstantPoolEntry, LoadableConstantEntry permits AbstractPoolEntry.ConstantDynamicEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java index 0225f6ec77d..91dc8906b7b 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java @@ -30,17 +30,14 @@ import java.util.Iterator; import java.util.NoSuchElementException; -import jdk.internal.javac.PreviewFeature; - /** * Provides read access to the constant pool and bootstrap method table of a * classfile. * @jvms 4.4 The Constant Pool * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ConstantPool extends Iterable permits ClassReader, ConstantPoolBuilder { @@ -70,7 +67,6 @@ public sealed interface ConstantPool extends Iterable * @param cls the entry type * @throws ConstantPoolException if the index is out of range of the * constant pool, or the entry is not of the given type - * @since 23 */ T entryByIndex(int index, Class cls); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java index 0ce4a6868c8..2dc2a390bd1 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java @@ -35,7 +35,6 @@ import jdk.internal.classfile.impl.SplitConstantPool; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; import static java.util.Objects.requireNonNull; @@ -48,9 +47,8 @@ * The {@linkplain ConstantPoolBuilder} also provides access to some of the * state of the {@linkplain ClassBuilder}, such as classfile processing options. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ConstantPoolBuilder extends ConstantPool permits SplitConstantPool, TemporaryConstantPool { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java index 260c9af64d4..ce5ed26c4c9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,15 +24,13 @@ */ package java.lang.classfile.constantpool; -import jdk.internal.javac.PreviewFeature; /** * Thrown to indicate that requested entry cannot be obtained from the constant * pool. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public class ConstantPoolException extends IllegalArgumentException { @java.io.Serial diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java index 924d0aca710..ae746042aa4 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java @@ -27,17 +27,14 @@ import java.lang.classfile.Attributes; import java.lang.constant.ConstantDesc; -import jdk.internal.javac.PreviewFeature; - /** * Models a constant pool entry that can be used as the constant in a * {@link Attributes#constantValue() ConstantValue} attribute; this includes the four * primitive constant types and {@linkplain String} constants. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ConstantValueEntry extends LoadableConstantEntry permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, StringEntry { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java index 8dd4ba1ffd9..ebc3a837bb0 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java @@ -27,16 +27,14 @@ import java.lang.classfile.TypeKind; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Double_info} constant in the constant pool of a * classfile. * @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface DoubleEntry extends AnnotationConstantValueEntry, ConstantValueEntry permits AbstractPoolEntry.DoubleEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java index ac763049410..3ec4fbbdbee 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,17 +26,14 @@ import java.lang.classfile.BootstrapMethodEntry; -import jdk.internal.javac.PreviewFeature; - /** * Models a dynamic constant pool entry, which is either {@link ConstantDynamicEntry} * or {@link InvokeDynamicEntry}. * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface DynamicConstantPoolEntry extends PoolEntry permits ConstantDynamicEntry, InvokeDynamicEntry { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java index ab122f410b6..47f5b6710d8 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +28,14 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Fieldref_info} constant in the constant pool of a * classfile. * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface FieldRefEntry extends MemberRefEntry permits AbstractPoolEntry.FieldRefEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java index 7a91dd11153..eeb44e92b7c 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java @@ -27,16 +27,14 @@ import java.lang.classfile.TypeKind; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Float_info} constant in the constant pool of a * classfile. * @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface FloatEntry extends AnnotationConstantValueEntry, ConstantValueEntry permits AbstractPoolEntry.FloatEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java index 7cd21e37db8..908f17d1cb7 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java @@ -27,16 +27,14 @@ import java.lang.classfile.TypeKind; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Integer_info} constant in the constant pool of a * classfile. * @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface IntegerEntry extends AnnotationConstantValueEntry, ConstantValueEntry permits AbstractPoolEntry.IntegerEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java index 8f15053e5b7..7b1a94f123a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +28,14 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_InterfaceMethodRef_info} constant in the constant pool of a * classfile. * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface InterfaceMethodRefEntry extends MemberRefEntry permits AbstractPoolEntry.InterfaceMethodRefEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java index f06c3d4c782..0cc8b6823df 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,15 +30,13 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a constant pool entry for a dynamic call site. * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface InvokeDynamicEntry extends DynamicConstantPoolEntry permits AbstractPoolEntry.InvokeDynamicEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java index c963e2425ea..32f85f64c7e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java @@ -27,16 +27,13 @@ import java.lang.classfile.TypeKind; import java.lang.constant.ConstantDesc; -import jdk.internal.javac.PreviewFeature; - /** * Marker interface for constant pool entries suitable for loading via the * {@code LDC} instructions. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LoadableConstantEntry extends PoolEntry permits ClassEntry, ConstantDynamicEntry, ConstantValueEntry, MethodHandleEntry, MethodTypeEntry { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java index 75e02b19441..cd38dcfe014 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java @@ -27,16 +27,14 @@ import java.lang.classfile.TypeKind; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Long_info} constant in the constant pool of a * classfile. * @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LongEntry extends AnnotationConstantValueEntry, ConstantValueEntry permits AbstractPoolEntry.LongEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java index 7c9292c8f04..12d68796dd7 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,16 +25,14 @@ package java.lang.classfile.constantpool; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a member reference constant in the constant pool of a classfile, * which includes references to fields, methods, and interface methods. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MemberRefEntry extends PoolEntry permits FieldRefEntry, InterfaceMethodRefEntry, MethodRefEntry, AbstractPoolEntry.AbstractMemberRefEntry { /** diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java index 37ec30648ab..d2e08ef178c 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java @@ -28,16 +28,14 @@ import java.lang.constant.DirectMethodHandleDesc; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_MethodHandle_info} constant in the constant pool of a * classfile. * @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodHandleEntry extends LoadableConstantEntry permits AbstractPoolEntry.MethodHandleEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java index ff3f5e5220c..5be9e88fa2f 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +28,14 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_MethodRef_info} constant in the constant pool of a * classfile. * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodRefEntry extends MemberRefEntry permits AbstractPoolEntry.MethodRefEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java index d626aeb4900..b6fad856358 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +28,14 @@ import java.lang.constant.MethodTypeDesc; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_MethodType_info} constant in the constant pool of a * classfile. * @jvms 4.4.9 The CONSTANT_MethodType_info Structure * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodTypeEntry extends LoadableConstantEntry permits AbstractPoolEntry.MethodTypeEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java index db7aa1f76fe..d0cdae5678f 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -27,16 +27,14 @@ import java.lang.constant.ModuleDesc; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Module_info} constant in the constant pool of a * classfile. * @jvms 4.4.11 The CONSTANT_Module_info Structure * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ModuleEntry extends PoolEntry permits AbstractPoolEntry.ModuleEntryImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java index d4beff2aff7..eff7e3456d1 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,16 +25,14 @@ package java.lang.classfile.constantpool; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_NameAndType_info} constant in the constant pool of a * classfile. * @jvms 4.4.6 The CONSTANT_NameAndType_info Structure * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface NameAndTypeEntry extends PoolEntry permits AbstractPoolEntry.NameAndTypeEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java index 5725d411028..54ea2fc38e5 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -27,16 +27,14 @@ import java.lang.constant.PackageDesc; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_Package_info} constant in the constant pool of a * classfile. * @jvms 4.4.12 The CONSTANT_Package_info Structure * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface PackageEntry extends PoolEntry permits AbstractPoolEntry.PackageEntryImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java index d2af4c7c11a..fdb8b497ff9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java @@ -24,15 +24,12 @@ */ package java.lang.classfile.constantpool; -import jdk.internal.javac.PreviewFeature; - /** * Models an entry in the constant pool of a classfile. * * @sealedGraph - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface PoolEntry permits AnnotationConstantValueEntry, DynamicConstantPoolEntry, LoadableConstantEntry, MemberRefEntry, ModuleEntry, NameAndTypeEntry, diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java index 65f75a6a062..03ff7652f67 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,16 +25,14 @@ package java.lang.classfile.constantpool; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_String_info} constant in the constant pool of a * classfile. * @jvms 4.4.3 The CONSTANT_String_info Structure * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface StringEntry extends ConstantValueEntry permits AbstractPoolEntry.StringEntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java index b379854cfcb..db03bf6a403 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,16 +25,14 @@ package java.lang.classfile.constantpool; import jdk.internal.classfile.impl.AbstractPoolEntry; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code CONSTANT_UTF8_info} constant in the constant pool of a * classfile. * @jvms 4.4.7 The CONSTANT_Utf8_info Structure * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Utf8Entry extends CharSequence, AnnotationConstantValueEntry permits AbstractPoolEntry.Utf8EntryImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java b/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java index 1ba2b63b6a1..83039c6565c 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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,9 +28,7 @@ * * The {@code java.lang.classfile.constantpool} package contains interfaces describing classfile constant pool entries. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) package java.lang.classfile.constantpool; -import jdk.internal.javac.PreviewFeature; diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java index b66627ef212..cc0e0b89f80 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models an array load instruction in the {@code code} array of a {@code Code} @@ -40,9 +39,8 @@ * Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ArrayLoadInstruction extends Instruction permits AbstractInstruction.UnboundArrayLoadInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java index f009cfca361..c350b3a5928 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models an array store instruction in the {@code code} array of a {@code Code} @@ -40,9 +39,8 @@ * Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ArrayStoreInstruction extends Instruction permits AbstractInstruction.UnboundArrayStoreInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java index 6b2142fa0e1..2fdc00fced1 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a branching instruction (conditional or unconditional) in the {@code @@ -40,9 +39,8 @@ * {@code kind} of {@link Opcode.Kind#BRANCH}. Delivered as a {@link * CodeElement} when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface BranchInstruction extends Instruction permits AbstractInstruction.BoundBranchInstruction, AbstractInstruction.UnboundBranchInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java b/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java index 3d04473ab37..d47639d7dd7 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java @@ -34,7 +34,6 @@ import jdk.internal.classfile.impl.AbstractPseudoInstruction; import jdk.internal.classfile.impl.BoundCharacterRange; -import jdk.internal.javac.PreviewFeature; /** * A pseudo-instruction which models a single entry in the @@ -42,9 +41,8 @@ * during traversal of the elements of a {@link CodeModel}, according to * the setting of the {@link ClassFile.DebugElementsOption} option. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface CharacterRange extends PseudoInstruction permits AbstractPseudoInstruction.UnboundCharacterRange, BoundCharacterRange { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java index c41793c614e..312c1868f19 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java @@ -35,7 +35,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a constant-load instruction in the {@code code} array of a {@code @@ -45,9 +44,8 @@ * a {@code kind} of {@link Opcode.Kind#CONSTANT}. Delivered as a {@link * CodeElement} when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ConstantInstruction extends Instruction { /** @@ -64,9 +62,8 @@ public sealed interface ConstantInstruction extends Instruction { * Models an "intrinsic constant" instruction (e.g., {@code * iconst_0}). * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface IntrinsicConstantInstruction extends ConstantInstruction permits AbstractInstruction.UnboundIntrinsicConstantInstruction { @@ -83,9 +80,8 @@ default TypeKind typeKind() { * Models an "argument constant" instruction (e.g., {@code * bipush}). * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface ArgumentConstantInstruction extends ConstantInstruction permits AbstractInstruction.BoundArgumentConstantInstruction, AbstractInstruction.UnboundArgumentConstantInstruction { @@ -106,9 +102,8 @@ default TypeKind typeKind() { * Models a "load constant" instruction (e.g., {@code * ldc}). * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface LoadConstantInstruction extends ConstantInstruction permits AbstractInstruction.BoundLoadConstantInstruction, AbstractInstruction.UnboundLoadConstantInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java index ec48c2f4663..468685779b9 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a primitive conversion instruction in the {@code code} array of a @@ -41,9 +40,8 @@ * a {@code kind} of {@link Opcode.Kind#CONVERT}. Delivered as a {@link * CodeElement} when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ConvertInstruction extends Instruction permits AbstractInstruction.UnboundConvertInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/DiscontinuedInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/DiscontinuedInstruction.java index 0e4718a1c77..4e8ddcef385 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/DiscontinuedInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/DiscontinuedInstruction.java @@ -33,16 +33,14 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models instruction discontinued from the {@code code} array of a {@code Code} * attribute. Delivered as a {@link CodeElement} when traversing the elements of * a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface DiscontinuedInstruction extends Instruction { /** @@ -52,9 +50,8 @@ public sealed interface DiscontinuedInstruction extends Instruction { * {@link Opcode.Kind#DISCONTINUED_JSR}. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface JsrInstruction extends DiscontinuedInstruction permits AbstractInstruction.BoundJsrInstruction, AbstractInstruction.UnboundJsrInstruction { @@ -95,9 +92,8 @@ static JsrInstruction of(Label target) { * {@link Opcode.Kind#DISCONTINUED_RET}. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ - @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface RetInstruction extends DiscontinuedInstruction permits AbstractInstruction.BoundRetInstruction, AbstractInstruction.UnboundRetInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java b/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java index 22b6f632abc..885f029d108 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import java.util.Optional; import jdk.internal.classfile.impl.AbstractPseudoInstruction; -import jdk.internal.javac.PreviewFeature; /** * A pseudo-instruction modeling an entry in the exception table of a code @@ -42,9 +41,8 @@ * * @see PseudoInstruction * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ExceptionCatch extends PseudoInstruction permits AbstractPseudoInstruction.ExceptionCatchImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/FieldInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/FieldInstruction.java index c8a82fe7dfa..b547abd18ab 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/FieldInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/FieldInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a field access instruction in the {@code code} array of a {@code Code} @@ -45,9 +44,8 @@ * Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface FieldInstruction extends Instruction permits AbstractInstruction.BoundFieldInstruction, AbstractInstruction.UnboundFieldInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java index 74fd6a4465a..7ea516c7cc5 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +30,6 @@ import java.lang.classfile.Opcode; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models a local variable increment instruction in the {@code code} array of a @@ -38,9 +37,8 @@ * {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface IncrementInstruction extends Instruction permits AbstractInstruction.BoundIncrementInstruction, AbstractInstruction.UnboundIncrementInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java index 6df960b88fa..43907b2a518 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,16 +38,14 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models an {@code invokedynamic} instruction in the {@code code} array of a * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing * the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface InvokeDynamicInstruction extends Instruction permits AbstractInstruction.BoundInvokeDynamicInstruction, AbstractInstruction.UnboundInvokeDynamicInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java index 41ca5fd1519..904a17375ac 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java @@ -39,7 +39,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a method invocation instruction in the {@code code} array of a {@code @@ -47,9 +46,8 @@ * will have a {@code kind} of {@link Opcode.Kind#INVOKE}. Delivered as a * {@link CodeElement} when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface InvokeInstruction extends Instruction permits AbstractInstruction.BoundInvokeInterfaceInstruction, AbstractInstruction.BoundInvokeInstruction, AbstractInstruction.UnboundInvokeInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java b/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java index 8682d0ee508..bc1deffc98b 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +30,6 @@ import java.lang.classfile.PseudoInstruction; import jdk.internal.classfile.impl.LabelImpl; -import jdk.internal.javac.PreviewFeature; /** * A pseudo-instruction which indicates that the specified label corresponds to @@ -39,9 +38,8 @@ * * @see PseudoInstruction * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LabelTarget extends PseudoInstruction permits LabelImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java b/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java index a06e7cfceba..a9a497708c0 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +31,6 @@ import java.lang.classfile.attribute.LineNumberTableAttribute; import jdk.internal.classfile.impl.LineNumberImpl; -import jdk.internal.javac.PreviewFeature; /** * A pseudo-instruction which models a single entry in the @@ -41,9 +40,8 @@ * * @see PseudoInstruction * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LineNumber extends PseudoInstruction permits LineNumberImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java index ce6463ef924..c499dcc9944 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a local variable load instruction in the {@code code} array of a @@ -41,9 +40,8 @@ * {@link Opcode.Kind#LOAD}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LoadInstruction extends Instruction permits AbstractInstruction.BoundLoadInstruction, AbstractInstruction.UnboundLoadInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java index 390034bd666..0f8cb672e51 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java @@ -37,7 +37,6 @@ import jdk.internal.classfile.impl.BoundLocalVariable; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * A pseudo-instruction which models a single entry in the @@ -47,9 +46,8 @@ * * @see PseudoInstruction * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LocalVariable extends PseudoInstruction permits AbstractPseudoInstruction.UnboundLocalVariable, BoundLocalVariable { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java index d0d2cd1581f..c9427491733 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java @@ -36,7 +36,6 @@ import jdk.internal.classfile.impl.AbstractPseudoInstruction; import jdk.internal.classfile.impl.BoundLocalVariableType; import jdk.internal.classfile.impl.TemporaryConstantPool; -import jdk.internal.javac.PreviewFeature; /** * A pseudo-instruction which models a single entry in the {@link @@ -44,9 +43,8 @@ * traversal of the elements of a {@link CodeModel}, according to the setting of * the {@link ClassFile.DebugElementsOption} option. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LocalVariableType extends PseudoInstruction permits AbstractPseudoInstruction.UnboundLocalVariableType, BoundLocalVariableType { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java index ce6c0cce109..7b286e9cfd2 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +31,14 @@ import java.util.List; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code lookupswitch} instruction in the {@code code} array of a * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing * the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface LookupSwitchInstruction extends Instruction permits AbstractInstruction.BoundLookupSwitchInstruction, AbstractInstruction.UnboundLookupSwitchInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/MonitorInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/MonitorInstruction.java index 9bec7805339..1c8268cddd6 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/MonitorInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/MonitorInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +31,14 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code monitorenter} or {@code monitorexit} instruction in the * {@code code} array of a {@code Code} attribute. Delivered as a {@link * CodeElement} when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MonitorInstruction extends Instruction permits AbstractInstruction.UnboundMonitorInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java index f5e0129205c..4a1f6cfd170 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +31,14 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code multianewarray} invocation instruction in the {@code code} * array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface NewMultiArrayInstruction extends Instruction permits AbstractInstruction.BoundNewMultidimensionalArrayInstruction, AbstractInstruction.UnboundNewMultidimensionalArrayInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java index e6e8fc64d17..f063733b64f 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +30,14 @@ import java.lang.classfile.constantpool.ClassEntry; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code new} instruction in the {@code code} array of a {@code Code} * attribute. Delivered as a {@link CodeElement} when traversing the elements * of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface NewObjectInstruction extends Instruction permits AbstractInstruction.BoundNewObjectInstruction, AbstractInstruction.UnboundNewObjectInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java index 4adc7536c2c..411bf7f6b55 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java @@ -30,16 +30,14 @@ import java.lang.classfile.TypeKind; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code newarray} invocation instruction in the {@code code} * array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface NewPrimitiveArrayInstruction extends Instruction permits AbstractInstruction.BoundNewPrimitiveArrayInstruction, AbstractInstruction.UnboundNewPrimitiveArrayInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java index b622f915c46..c85ed9dd3d9 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +30,14 @@ import java.lang.classfile.constantpool.ClassEntry; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code anewarray} invocation instruction in the {@code code} * array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface NewReferenceArrayInstruction extends Instruction permits AbstractInstruction.BoundNewReferenceArrayInstruction, AbstractInstruction.UnboundNewReferenceArrayInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java index 3183ad88816..3c11803109a 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,16 +29,14 @@ import java.lang.classfile.Instruction; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code nop} invocation instruction in the {@code code} * array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface NopInstruction extends Instruction permits AbstractInstruction.UnboundNopInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java index 602f34ec03e..d1eb8aa1a3d 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models an arithmetic operator instruction in the {@code code} array of a @@ -40,9 +39,8 @@ * {@link Opcode.Kind#OPERATOR}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface OperatorInstruction extends Instruction permits AbstractInstruction.UnboundOperatorInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java index 6596404a582..3bbb96b1cbe 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a return-from-method instruction in the {@code code} array of a @@ -41,9 +40,8 @@ * {@link Opcode.Kind#RETURN}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ReturnInstruction extends Instruction permits AbstractInstruction.UnboundReturnInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java index 17e9496652b..b01b206e368 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,7 +31,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a stack manipulation instruction in the {@code code} array of a @@ -39,9 +38,8 @@ * {@link Opcode.Kind#STACK}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface StackInstruction extends Instruction permits AbstractInstruction.UnboundStackInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java index 68bf54e61c2..1d7bdce1fdf 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,7 +33,6 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models a local variable store instruction in the {@code code} array of a @@ -41,9 +40,8 @@ * {@link Opcode.Kind#STORE}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface StoreInstruction extends Instruction permits AbstractInstruction.BoundStoreInstruction, AbstractInstruction.UnboundStoreInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java b/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java index 6149945532b..3f5f91031b6 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -27,7 +27,6 @@ import java.lang.classfile.Label; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models a single case in a {@code lookupswitch} or {@code tableswitch} @@ -36,9 +35,8 @@ * @see LookupSwitchInstruction * @see TableSwitchInstruction * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface SwitchCase permits AbstractInstruction.SwitchCaseImpl { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java index a8bce119db2..bbe7a4d6c0c 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +31,14 @@ import java.util.List; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models a {@code tableswitch} instruction in the {@code code} array of a * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing * the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface TableSwitchInstruction extends Instruction permits AbstractInstruction.BoundTableSwitchInstruction, AbstractInstruction.UnboundTableSwitchInstruction { /** diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ThrowInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ThrowInstruction.java index 68d861ba06d..ec6fdc38626 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ThrowInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ThrowInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,16 +29,14 @@ import java.lang.classfile.Instruction; import jdk.internal.classfile.impl.AbstractInstruction; -import jdk.internal.javac.PreviewFeature; /** * Models an {@code athrow} instruction in the {@code code} array of a * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing * the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ThrowInstruction extends Instruction permits AbstractInstruction.UnboundThrowInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java index a4b9818a4be..032e7a8462b 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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,16 +34,14 @@ import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.TemporaryConstantPool; import jdk.internal.classfile.impl.Util; -import jdk.internal.javac.PreviewFeature; /** * Models an {@code instanceof} or {@code checkcast} instruction in the {@code * code} array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface TypeCheckInstruction extends Instruction permits AbstractInstruction.BoundTypeCheckInstruction, AbstractInstruction.UnboundTypeCheckInstruction { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java b/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java index 2bb35494da0..d2a36e16615 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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,9 +28,7 @@ * * The {@code java.lang.classfile.attribute} package contains interfaces describing code instructions. * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) package java.lang.classfile.instruction; -import jdk.internal.javac.PreviewFeature; diff --git a/src/java.base/share/classes/java/lang/classfile/package-info.java b/src/java.base/share/classes/java/lang/classfile/package-info.java index 6e9ecfe4819..2d6a8959a2d 100644 --- a/src/java.base/share/classes/java/lang/classfile/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/package-info.java @@ -546,9 +546,6 @@ * | CharacterRange(int rangeStart, int rangeEnd, int flags, Label startScope, Label endScope) * } * - * @since 22 + * @since 24 */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) package java.lang.classfile; - -import jdk.internal.javac.PreviewFeature; diff --git a/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java index a9bfff152e6..b42a8d39353 100644 --- a/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java +++ b/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java @@ -107,9 +107,6 @@ * implemented by invoking the implementation method * @throws LambdaConversionException If any of the meta-factory protocol * invariants are violated - * @throws SecurityException If a security manager is present, and it - * denies access - * from {@code caller} to the package of {@code implementation}. */ AbstractValidatingLambdaMetafactory(MethodHandles.Lookup caller, MethodType factoryType, @@ -138,7 +135,7 @@ this.implementation = implementation; this.implMethodType = implementation.type(); try { - this.implInfo = caller.revealDirect(implementation); // may throw SecurityException + this.implInfo = caller.revealDirect(implementation); } catch (IllegalArgumentException e) { throw new LambdaConversionException(implementation + " is not direct or cannot be cracked"); } diff --git a/src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java b/src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java index f01fc004986..0e73a02077a 100644 --- a/src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java +++ b/src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.lang.invoke; -import java.security.*; import java.lang.reflect.*; import java.lang.invoke.MethodHandles.Lookup; @@ -85,16 +84,13 @@ public T reflectAs(Class expected, Lookup lookup) { // For more information see comments on {@link MethodHandleNatives#linkMethod}. throw new IllegalArgumentException("cannot reflect signature polymorphic method"); } - @SuppressWarnings("removal") - Member mem = AccessController.doPrivileged(new PrivilegedAction<>() { - public Member run() { - try { - return reflectUnchecked(); - } catch (ReflectiveOperationException ex) { - throw new IllegalArgumentException(ex); - } - } - }); + + Member mem; + try { + mem = reflectUnchecked(); + } catch (ReflectiveOperationException ex) { + throw new IllegalArgumentException(ex); + } try { Class defc = getDeclaringClass(); byte refKind = (byte) getReferenceKind(); 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 93784004994..4dac59771e8 100644 --- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -29,7 +29,6 @@ import jdk.internal.misc.CDS; import jdk.internal.util.ClassFileDumper; import sun.invoke.util.VerifyAccess; -import sun.security.action.GetBooleanAction; import java.io.Serializable; import java.lang.classfile.ClassBuilder; @@ -83,7 +82,7 @@ lambdaProxyClassFileDumper = ClassFileDumper.getInstance(dumpProxyClassesKey, "DUMP_LAMBDA_PROXY_CLASS_FILES"); final String disableEagerInitializationKey = "jdk.internal.lambda.disableEagerInitialization"; - disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey); + disableEagerInitialization = Boolean.getBoolean(disableEagerInitializationKey); } // See context values in AbstractValidatingLambdaMetafactory @@ -134,9 +133,6 @@ * implemented by invoking the implementation method * @throws LambdaConversionException If any of the meta-factory protocol * invariants are violated - * @throws SecurityException If a security manager is present, and it - * denies access - * from {@code caller} to the package of {@code implementation}. */ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, MethodType factoryType, @@ -189,13 +185,17 @@ private static String argName(int i) { return i < ARG_NAME_CACHE.length ? ARG_NAME_CACHE[i] : "arg$" + (i + 1); } - private static String lambdaClassName(Class targetClass) { + private static String sanitizedTargetClassName(Class targetClass) { String name = targetClass.getName(); if (targetClass.isHidden()) { // use the original class name name = name.replace('/', '_'); } - return name.replace('.', '/').concat("$$Lambda"); + return name.replace('.', '/'); + } + + private static String lambdaClassName(Class targetClass) { + return sanitizedTargetClassName(targetClass).concat("$$Lambda"); } /** @@ -434,7 +434,7 @@ private void generateSerializationFriendlyMethods(ClassBuilder clb) { public void accept(CodeBuilder cob) { cob.new_(SerializationSupport.CD_SerializedLambda) .dup() - .ldc(classDesc(targetClass)) + .ldc(ClassDesc.ofInternalName(sanitizedTargetClassName(targetClass))) .ldc(factoryType.returnType().getName().replace('.', '/')) .ldc(interfaceMethodName) .ldc(interfaceMethodType.toMethodDescriptorString()) diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java b/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java index 4de0d9c95cb..8d84c5f8096 100644 --- a/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java +++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import static java.lang.invoke.MethodHandleImpl.Intrinsic; import static java.lang.invoke.MethodHandleImpl.NF_loop; import static java.lang.invoke.MethodHandleImpl.makeIntrinsic; +import static java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE; /** Transforms on LFs. * A lambda-form editor can derive new LFs from its base LF. @@ -89,12 +90,17 @@ static LambdaFormEditor lambdaFormEditor(LambdaForm lambdaForm) { * Tightly coupled with the TransformKey class, which is used to lookup existing * Transforms. */ - private static final class Transform extends SoftReference { + private static final class Transform { + final Object cache; final long packedBytes; final byte[] fullBytes; private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) { - super(result); + if (USE_SOFT_CACHE) { + cache = new SoftReference(result); + } else { + cache = result; + } this.packedBytes = packedBytes; this.fullBytes = fullBytes; } @@ -135,6 +141,15 @@ public String toString() { } return buf.toString(); } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public LambdaForm get() { + if (cache instanceof LambdaForm lf) { + return lf; + } else { + return ((SoftReference)cache).get(); + } + } } /** diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java index 0cc6f627543..d6099861cee 100644 --- a/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java +++ b/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java @@ -229,6 +229,22 @@ * used, but this is not compatible with some implementation techniques and * would complicate the work implementations must do. * + *

Uses besides evaluation of lambda expressions and method references are + * unintended. These linkage methods may change their unspecified behaviors at + * any time to better suit the Java language features they were designed to + * support, and such changes may impact unintended uses. Unintended uses of + * these linkage methods may lead to resource leaks, or other unspecified + * negative effects. + * + * @implNote In the reference implementation, the classes implementing the created + * function objects are strongly reachable from the defining class loader of the + * caller, like classes and interfaces in Java source code. This technique + * reduces heap memory use, but as a consequence, the implementation classes can + * be unloaded only if the caller class can be unloaded. In particular, if the + * caller is a {@linkplain MethodHandles.Lookup.ClassOption#STRONG weak hidden + * class}, the implementation class, a strong hidden class, may not be unloaded + * even if the caller may be unloaded. + * * @since 1.8 */ public final class LambdaMetafactory { diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index fd3e20a524e..e94b1dc40f2 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1208,11 +1208,7 @@ private static MethodHandle restoreToType(MethodHandle vamh, private static boolean checkInjectedInvoker(Class hostClass, Class invokerClass) { assert (hostClass.getClassLoader() == invokerClass.getClassLoader()) : hostClass.getName()+" (CL)"; - try { - assert (hostClass.getProtectionDomain() == invokerClass.getProtectionDomain()) : hostClass.getName()+" (PD)"; - } catch (SecurityException ex) { - // Self-check was blocked by security manager. This is OK. - } + assert (hostClass.getProtectionDomain() == invokerClass.getProtectionDomain()) : hostClass.getName()+" (PD)"; try { // Test the invoker to ensure that it really injects into the right place. MethodHandle invoker = IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT); 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 ac9765ddc3b..4ffbf826317 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,9 +28,11 @@ import jdk.internal.misc.VM; import jdk.internal.ref.CleanerFactory; import sun.invoke.util.Wrapper; +import sun.security.action.GetPropertyAction; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Field; +import java.util.Properties; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE; @@ -690,4 +692,23 @@ static boolean canBeCalledVirtual(MemberName symbolicRef, Class definingClass return (definingClass.isAssignableFrom(symbolicRefClass) || // Msym overrides Mdef symbolicRefClass.isInterface()); // Mdef implements Msym } + + //--- AOTCache support + + /** + * In normal execution, this is set to true, so that LambdaFormEditor and MethodTypeForm will + * use soft references to allow class unloading. + * + * When dumping the AOTCache, this is set to false so that no cached heap objects will + * contain soft references (which are not yet supported by AOTCache - see JDK-8341587). AOTCache + * only stores LambdaFormEditors and MethodTypeForms for classes in the boot/platform/app loaders. + * Such classes will never be unloaded, so it's OK to use hard references. + */ + static final boolean USE_SOFT_CACHE; + + static { + Properties props = GetPropertyAction.privilegedGetProperties(); + USE_SOFT_CACHE = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE", "true")); + } } diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java index dcfa671a17f..0ab2dbfdae9 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -33,8 +33,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.UndeclaredThrowableException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -56,10 +54,7 @@ import jdk.internal.constant.ConstantUtils; import jdk.internal.loader.ClassLoaders; import jdk.internal.module.Modules; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; import jdk.internal.util.ClassFileDumper; -import sun.reflect.misc.ReflectUtil; import static java.lang.constant.ConstantDescs.*; import static java.lang.invoke.MethodHandleStatics.*; @@ -159,7 +154,6 @@ private MethodHandleProxies() { } // do not instantiate * be converted to the type required by the requested interface */ @SuppressWarnings("doclint:reference") // cross-module links - @CallerSensitive public static T asInterfaceInstance(final Class intfc, final MethodHandle target) { if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) throw newIllegalArgumentException("not a public interface", intfc.getName()); @@ -168,17 +162,7 @@ public static T asInterfaceInstance(final Class intfc, final MethodHandle if (intfc.isHidden()) throw newIllegalArgumentException("a hidden interface", intfc.getName()); Objects.requireNonNull(target); - final MethodHandle mh; - @SuppressWarnings("removal") - var sm = System.getSecurityManager(); - if (sm != null) { - final Class caller = Reflection.getCallerClass(); - final ClassLoader ccl = caller != null ? caller.getClassLoader() : null; - ReflectUtil.checkProxyPackageAccess(ccl, intfc); - mh = ccl != null ? bindCaller(target, caller) : target; - } else { - mh = target; - } + final MethodHandle mh = target; // Define one hidden class for each interface. Create an instance of // the hidden class for a given target method handle which will be @@ -283,17 +267,7 @@ private static Class newProxyClass(Class intfc) { // define the dynamic module to the class loader of the interface var definer = new Lookup(intfc).makeHiddenClassDefiner(className, template, DUMPER); - @SuppressWarnings("removal") - var sm = System.getSecurityManager(); - Lookup lookup; - if (sm != null) { - @SuppressWarnings("removal") - var l = AccessController.doPrivileged((PrivilegedAction) () -> - definer.defineClassAsLookup(true)); - lookup = l; - } else { - lookup = definer.defineClassAsLookup(true); - } + Lookup lookup = definer.defineClassAsLookup(true); // cache the wrapper type var ret = lookup.lookupClass(); WRAPPER_TYPES.add(ret); diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java index 7d87d4f79a8..f50edd5626a 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -28,7 +28,6 @@ import jdk.internal.misc.CDS; import jdk.internal.misc.Unsafe; import jdk.internal.util.ClassFileDumper; -import sun.security.action.GetPropertyAction; import java.lang.reflect.ClassFileFormatVersion; import java.util.Properties; @@ -66,7 +65,7 @@ private MethodHandleStatics() { } // do not instantiate static final ClassFileDumper DUMP_CLASS_FILES; static { - Properties props = GetPropertyAction.privilegedGetProperties(); + Properties props = System.getProperties(); DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean( props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES")); 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 b077c730440..7542b0e513a 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -36,8 +36,6 @@ import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyAccess; import sun.invoke.util.Wrapper; -import sun.reflect.misc.ReflectUtil; -import sun.security.util.SecurityConstants; import java.lang.classfile.ClassFile; import java.lang.classfile.ClassModel; @@ -243,9 +241,6 @@ public static Lookup privateLookupIn(Class targetClass, Lookup caller) throws return new Lookup(targetClass); } - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) sm.checkPermission(SecurityConstants.ACCESS_PERMISSION); if (targetClass.isPrimitive()) throw new IllegalArgumentException(targetClass + " is a primitive class"); if (targetClass.isArray()) @@ -463,9 +458,6 @@ public static T classDataAt(Lookup caller, String name, Class type, int i * @since 1.8 */ public static T reflectAs(Class expected, MethodHandle target) { - @SuppressWarnings("removal") - SecurityManager smgr = System.getSecurityManager(); - if (smgr != null) smgr.checkPermission(SecurityConstants.ACCESS_PERMISSION); Lookup lookup = Lookup.IMPL_LOOKUP; // use maximally privileged lookup return lookup.revealDirect(target).reflectAs(expected, lookup); } @@ -741,8 +733,6 @@ public static T reflectAs(Class expected, MethodHandle tar *

    *
  • access private fields, methods, and constructors of the lookup class and its nestmates *
  • create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions - *
  • avoid package access checks - * for classes accessible to the lookup class *
  • create {@link Lookup#in delegated lookup objects} which have private access to other classes * within the same package member *
@@ -1759,23 +1749,11 @@ public Lookup dropLookupMode(int modeToDrop) { * @see ClassLoader#defineClass(String,byte[],int,int,ProtectionDomain) */ public Class defineClass(byte[] bytes) throws IllegalAccessException { - ensureDefineClassPermission(); if ((lookupModes() & PACKAGE) == 0) throw new IllegalAccessException("Lookup does not have PACKAGE access"); return makeClassDefiner(bytes.clone()).defineClass(false); } - private void ensureDefineClassPermission() { - if (allowedModes == TRUSTED) return; - - if (!hasFullPrivilegeAccess()) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(new RuntimePermission("defineClass")); - } - } - /** * The set of class options that specify whether a hidden class created by * {@link Lookup#defineHiddenClass(byte[], boolean, ClassOption...) @@ -2042,7 +2020,6 @@ public Lookup defineHiddenClass(byte[] bytes, boolean initialize, ClassOption... { Objects.requireNonNull(bytes); int flags = ClassOption.optionsToFlag(options); - ensureDefineClassPermission(); if (!hasFullPrivilegeAccess()) { throw new IllegalAccessException(this + " does not have full privilege access"); } @@ -2128,7 +2105,6 @@ public Lookup defineHiddenClassWithClassData(byte[] bytes, Object classData, boo int flags = ClassOption.optionsToFlag(options); - ensureDefineClassPermission(); if (!hasFullPrivilegeAccess()) { throw new IllegalAccessException(this + " does not have full privilege access"); } @@ -2768,7 +2744,6 @@ public Class ensureInitialized(Class targetClass) throws IllegalAccess if (!VerifyAccess.isClassAccessible(targetClass, lookupClass, prevLookupClass, allowedModes)) { throw makeAccessException(targetClass); } - checkSecurityManager(targetClass); // ensure class initialization Unsafe.getUnsafe().ensureClassInitialized(targetClass); @@ -2872,7 +2847,6 @@ public Class accessClass(Class targetClass) throws IllegalAccessExcept if (!isClassAccessible(targetClass)) { throw makeAccessException(targetClass); } - checkSecurityManager(targetClass); return targetClass; } @@ -3292,7 +3266,7 @@ public MethodHandle unreflect(Method m) throws IllegalAccessException { assert(method.isMethod()); @SuppressWarnings("deprecation") Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerLookup(method)); + return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, findBoundCallerLookup(method)); } private MethodHandle unreflectForMH(Method m) { // these names require special lookups because they throw UnsupportedOperationException @@ -3343,7 +3317,7 @@ public MethodHandle unreflectSpecial(Method m, Class specialCaller) throws Il MemberName method = new MemberName(m, true); assert(method.isMethod()); // ignore m.isAccessible: this is a new kind of access - return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerLookup(method)); + return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerLookup(method)); } /** @@ -3375,12 +3349,12 @@ public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessE assert(ctor.isConstructor()); @SuppressWarnings("deprecation") Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor); + return lookup.getDirectConstructor(ctor.getDeclaringClass(), ctor); } /* * Produces a method handle that is capable of creating instances of the given class - * and instantiated by the given constructor. No security manager check. + * and instantiated by the given constructor. * * This method should only be used by ReflectionFactory::newConstructorForSerialization. */ @@ -3473,7 +3447,7 @@ private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAcc : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); @SuppressWarnings("deprecation") Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); + return lookup.getDirectField(field.getReferenceKind(), f.getDeclaringClass(), field); } /** @@ -3550,8 +3524,8 @@ private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAcc public VarHandle unreflectVarHandle(Field f) throws IllegalAccessException { MemberName getField = new MemberName(f, false); MemberName putField = new MemberName(f, true); - return getFieldVarHandleNoSecurityManager(getField.getReferenceKind(), putField.getReferenceKind(), - f.getDeclaringClass(), getField, putField); + return getFieldVarHandle(getField.getReferenceKind(), putField.getReferenceKind(), + f.getDeclaringClass(), getField, putField); } /** @@ -3586,10 +3560,9 @@ public MethodHandleInfo revealDirect(MethodHandle target) { if (refKind == REF_invokeVirtual && defc.isInterface()) // Symbolic reference is through interface but resolves to Object method (toString, etc.) refKind = REF_invokeInterface; - // Check SM permissions and member access before cracking. + // Check member access before cracking. try { checkAccess(refKind, defc, member); - checkSecurityManager(defc, member); } catch (IllegalAccessException ex) { throw new IllegalArgumentException(ex); } @@ -3716,69 +3689,6 @@ public boolean hasFullPrivilegeAccess() { return (allowedModes & (PRIVATE|MODULE)) == (PRIVATE|MODULE); } - /** - * Perform steps 1 and 2b access checks - * for ensureInitialized, findClass or accessClass. - */ - void checkSecurityManager(Class refc) { - if (allowedModes == TRUSTED) return; - - @SuppressWarnings("removal") - SecurityManager smgr = System.getSecurityManager(); - if (smgr == null) return; - - // Step 1: - boolean fullPrivilegeLookup = hasFullPrivilegeAccess(); - if (!fullPrivilegeLookup || - !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) { - ReflectUtil.checkPackageAccess(refc); - } - - // Step 2b: - if (!fullPrivilegeLookup) { - smgr.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - } - - /** - * 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 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); - Objects.requireNonNull(m); - - if (allowedModes == TRUSTED) return; - - @SuppressWarnings("removal") - SecurityManager smgr = System.getSecurityManager(); - if (smgr == null) return; - - // Step 1: - boolean fullPrivilegeLookup = hasFullPrivilegeAccess(); - if (!fullPrivilegeLookup || - !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) { - ReflectUtil.checkPackageAccess(refc); - } - - // Step 2a: - if (m.isPublic()) return; - if (!fullPrivilegeLookup) { - smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); - } - - // Step 3: - Class defc = m.getDeclaringClass(); - if (!fullPrivilegeLookup && defc != refc) { - ReflectUtil.checkPackageAccess(defc); - } - } - void checkMethod(byte refKind, Class refc, MemberName m) throws IllegalAccessException { boolean wantStatic = (refKind == REF_invokeStatic); String message; @@ -3918,30 +3828,18 @@ private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, /** Check access and get the requested method. */ private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method, Lookup callerLookup) throws IllegalAccessException { final boolean doRestrict = true; - final boolean checkSecurity = true; - return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup); + return getDirectMethodCommon(refKind, refc, method, doRestrict, callerLookup); } /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */ private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class refc, MemberName method, Lookup callerLookup) throws IllegalAccessException { final boolean doRestrict = false; - final boolean checkSecurity = true; - return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerLookup); - } - /** Check access and get the requested method, eliding security manager checks. */ - private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class refc, MemberName method, Lookup callerLookup) throws IllegalAccessException { - final boolean doRestrict = true; - final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants - return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup); + return getDirectMethodCommon(REF_invokeSpecial, refc, method, doRestrict, callerLookup); } /** Common code for all methods; do not call directly except from immediately above. */ private MethodHandle getDirectMethodCommon(byte refKind, Class refc, MemberName method, - boolean checkSecurity, boolean doRestrict, Lookup boundCaller) throws IllegalAccessException { checkMethod(refKind, refc, method); - // Optionally check with the security manager; this isn't needed for unreflect* calls. - if (checkSecurity) - checkSecurityManager(refc, method); assert(!method.isMethodHandleInvoke()); if (refKind == REF_invokeSpecial && @@ -4010,21 +3908,11 @@ private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, Lookup /** Check access and get the requested field. */ private MethodHandle getDirectField(byte refKind, Class refc, MemberName field) throws IllegalAccessException { - final boolean checkSecurity = true; - return getDirectFieldCommon(refKind, refc, field, checkSecurity); - } - /** Check access and get the requested field, eliding security manager checks. */ - private MethodHandle getDirectFieldNoSecurityManager(byte refKind, Class refc, MemberName field) throws IllegalAccessException { - final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants - return getDirectFieldCommon(refKind, refc, field, checkSecurity); + return getDirectFieldCommon(refKind, refc, field); } /** Common code for all fields; do not call directly except from immediately above. */ - private MethodHandle getDirectFieldCommon(byte refKind, Class refc, MemberName field, - boolean checkSecurity) throws IllegalAccessException { + private MethodHandle getDirectFieldCommon(byte refKind, Class refc, MemberName field) throws IllegalAccessException { checkField(refKind, refc, field); - // Optionally check with the security manager; this isn't needed for unreflect* calls. - if (checkSecurity) - checkSecurityManager(refc, field); DirectMethodHandle dmh = DirectMethodHandle.make(refc, field); boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) && restrictProtectedReceiver(field)); @@ -4035,26 +3923,17 @@ private MethodHandle getDirectFieldCommon(byte refKind, Class refc, MemberNam private VarHandle getFieldVarHandle(byte getRefKind, byte putRefKind, Class refc, MemberName getField, MemberName putField) throws IllegalAccessException { - final boolean checkSecurity = true; - return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity); - } - private VarHandle getFieldVarHandleNoSecurityManager(byte getRefKind, byte putRefKind, - Class refc, MemberName getField, MemberName putField) - throws IllegalAccessException { - final boolean checkSecurity = false; - return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity); + return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField); } private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind, - Class refc, MemberName getField, MemberName putField, - boolean checkSecurity) throws IllegalAccessException { + Class refc, MemberName getField, + MemberName putField) throws IllegalAccessException { assert getField.isStatic() == putField.isStatic(); assert getField.isGetter() && putField.isSetter(); assert MethodHandleNatives.refKindIsStatic(getRefKind) == MethodHandleNatives.refKindIsStatic(putRefKind); assert MethodHandleNatives.refKindIsGetter(getRefKind) && MethodHandleNatives.refKindIsSetter(putRefKind); checkField(getRefKind, refc, getField); - if (checkSecurity) - checkSecurityManager(refc, getField); if (!putField.isFinal()) { // A VarHandle does not support updates to final fields, any @@ -4062,8 +3941,6 @@ private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind, // therefore the following write-based accessibility checks are // only required for non-final fields checkField(putRefKind, refc, putField); - if (checkSecurity) - checkSecurityManager(refc, putField); } boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) && @@ -4081,22 +3958,12 @@ private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind, } /** Check access and get the requested constructor. */ private MethodHandle getDirectConstructor(Class refc, MemberName ctor) throws IllegalAccessException { - final boolean checkSecurity = true; - return getDirectConstructorCommon(refc, ctor, checkSecurity); - } - /** Check access and get the requested constructor, eliding security manager checks. */ - private MethodHandle getDirectConstructorNoSecurityManager(Class refc, MemberName ctor) throws IllegalAccessException { - final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants - return getDirectConstructorCommon(refc, ctor, checkSecurity); + return getDirectConstructorCommon(refc, ctor); } /** Common code for all constructors; do not call directly except from immediately above. */ - private MethodHandle getDirectConstructorCommon(Class refc, MemberName ctor, - boolean checkSecurity) throws IllegalAccessException { + private MethodHandle getDirectConstructorCommon(Class refc, MemberName ctor) throws IllegalAccessException { assert(ctor.isConstructor()); checkAccess(REF_newInvokeSpecial, refc, ctor); - // Optionally check with the security manager; this isn't needed for unreflect* calls. - if (checkSecurity) - checkSecurityManager(refc, ctor); assert(!MethodHandleNatives.isCallerSensitive(ctor)); // maybeBindCaller not relevant here return DirectMethodHandle.make(ctor).setVarargs(ctor); } @@ -4163,14 +4030,9 @@ private boolean canBeCached(byte refKind, Class defc, MemberName member) { return false; } } - try { - MemberName resolved2 = publicLookup().resolveOrNull(refKind, + MemberName resolved2 = publicLookup().resolveOrNull(refKind, new MemberName(refKind, defc, member.getName(), member.getType())); - if (resolved2 == null) { - return false; - } - checkSecurityManager(defc, resolved2); - } catch (SecurityException ex) { + if (resolved2 == null) { return false; } return true; @@ -4178,11 +4040,11 @@ private boolean canBeCached(byte refKind, Class defc, MemberName member) { private MethodHandle getDirectMethodForConstant(byte refKind, Class defc, MemberName member) throws ReflectiveOperationException { if (MethodHandleNatives.refKindIsField(refKind)) { - return getDirectFieldNoSecurityManager(refKind, defc, member); + return getDirectField(refKind, defc, member); } else if (MethodHandleNatives.refKindIsMethod(refKind)) { - return getDirectMethodNoSecurityManager(refKind, defc, member, findBoundCallerLookup(member)); + return getDirectMethod(refKind, defc, member, findBoundCallerLookup(member)); } else if (refKind == REF_newInvokeSpecial) { - return getDirectConstructorNoSecurityManager(defc, member); + return getDirectConstructor(defc, member); } // oops throw newIllegalArgumentException("bad MethodHandle constant #"+member); diff --git a/src/java.base/share/classes/java/lang/invoke/MethodType.java b/src/java.base/share/classes/java/lang/invoke/MethodType.java index a7afea7c939..5e1c0f8581c 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodType.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java @@ -28,29 +28,25 @@ import java.lang.constant.ClassDesc; import java.lang.constant.Constable; import java.lang.constant.MethodTypeDesc; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.Collections; import java.util.function.Supplier; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.StringJoiner; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.stream.Stream; import jdk.internal.util.ReferencedKeySet; import jdk.internal.util.ReferenceKey; +import jdk.internal.misc.CDS; import jdk.internal.vm.annotation.Stable; import sun.invoke.util.BytecodeDescriptor; import sun.invoke.util.VerifyType; import sun.invoke.util.Wrapper; -import sun.security.util.SecurityConstants; import static java.lang.invoke.MethodHandleStatics.UNSAFE; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; @@ -398,6 +394,17 @@ private static MethodType makeImpl(Class rtype, Class[] ptypes, boolean tr ptypes = NO_PTYPES; trusted = true; } MethodType primordialMT = new MethodType(rtype, ptypes); + if (archivedMethodTypes != null) { + // If this JVM process reads from archivedMethodTypes, it never + // modifies the table. So there's no need for synchronization. + // See copyInternTable() below. + assert CDS.isUsingArchive(); + MethodType mt = archivedMethodTypes.get(primordialMT); + if (mt != null) { + return mt; + } + } + MethodType mt = internTable.get(primordialMT); if (mt != null) return mt; @@ -416,7 +423,9 @@ private static MethodType makeImpl(Class rtype, Class[] ptypes, boolean tr mt.form = MethodTypeForm.findForm(mt); return internTable.intern(mt); } + private static final @Stable MethodType[] objectOnlyTypes = new MethodType[20]; + private static @Stable HashMap archivedMethodTypes; /** * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array. @@ -1183,13 +1192,6 @@ Invokers invokers() { public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader) throws IllegalArgumentException, TypeNotPresentException { - if (loader == null) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - } return fromDescriptor(descriptor, (loader == null) ? ClassLoader.getSystemClassLoader() : loader); } @@ -1394,4 +1396,30 @@ private Object readResolve() { wrapAlt = null; return mt; } + + static HashMap copyInternTable() { + HashMap copy = new HashMap<>(); + + for (Iterator i = internTable.iterator(); i.hasNext(); ) { + MethodType t = i.next(); + copy.put(t, t); + } + + return copy; + } + + // This is called from C code, at the very end of Java code execution + // during the AOT cache assembly phase. + static void createArchivedObjects() { + // After the archivedMethodTypes field is assigned, this table + // is never modified. So we don't need synchronization when reading from + // it (which happens only in a future JVM process, never in the current process). + // + // @implNote CDS.isDumpingStaticArchive() is mutually exclusive with + // CDS.isUsingArchive(); at most one of them can return true for any given JVM + // process. + assert CDS.isDumpingStaticArchive(); + archivedMethodTypes = copyInternTable(); + internTable.clear(); + } } diff --git a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java index 09377618797..69545478ec4 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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.lang.ref.SoftReference; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; +import static java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE; /** * Shared information for a group of method types, which differ @@ -51,7 +52,7 @@ final class MethodTypeForm { final MethodType basicType; // the canonical erasure, with primitives simplified // Cached adapter information: - final SoftReference[] methodHandles; + private final Object[] methodHandles; // Indexes into methodHandles: static final int @@ -61,7 +62,7 @@ final class MethodTypeForm { MH_LIMIT = 3; // Cached lambda form information, for basic types only: - final SoftReference[] lambdaForms; + private final Object[] lambdaForms; // Indexes into lambdaForms: static final int @@ -109,39 +110,55 @@ public MethodType basicType() { return basicType; } + @SuppressWarnings({"rawtypes", "unchecked"}) public MethodHandle cachedMethodHandle(int which) { - SoftReference entry = methodHandles[which]; - return (entry != null) ? entry.get() : null; + Object entry = methodHandles[which]; + if (entry == null) { + return null; + } else if (entry instanceof MethodHandle mh) { + return mh; + } else { + return ((SoftReference)entry).get(); + } } public synchronized MethodHandle setCachedMethodHandle(int which, MethodHandle mh) { // Simulate a CAS, to avoid racy duplication of results. - SoftReference entry = methodHandles[which]; - if (entry != null) { - MethodHandle prev = entry.get(); - if (prev != null) { - return prev; - } + MethodHandle prev = cachedMethodHandle(which); + if (prev != null) { + return prev; + } + if (USE_SOFT_CACHE) { + methodHandles[which] = new SoftReference<>(mh); + } else { + methodHandles[which] = mh; } - methodHandles[which] = new SoftReference<>(mh); return mh; } + @SuppressWarnings({"rawtypes", "unchecked"}) public LambdaForm cachedLambdaForm(int which) { - SoftReference entry = lambdaForms[which]; - return (entry != null) ? entry.get() : null; + Object entry = lambdaForms[which]; + if (entry == null) { + return null; + } else if (entry instanceof LambdaForm lf) { + return lf; + } else { + return ((SoftReference)entry).get(); + } } public synchronized LambdaForm setCachedLambdaForm(int which, LambdaForm form) { // Simulate a CAS, to avoid racy duplication of results. - SoftReference entry = lambdaForms[which]; - if (entry != null) { - LambdaForm prev = entry.get(); - if (prev != null) { - return prev; - } + LambdaForm prev = cachedLambdaForm(which); + if (prev != null) { + return prev; + } + if (USE_SOFT_CACHE) { + lambdaForms[which] = new SoftReference<>(form); + } else { + lambdaForms[which] = form; } - lambdaForms[which] = new SoftReference<>(form); return form; } @@ -191,8 +208,8 @@ protected MethodTypeForm(MethodType erasedType) { this.primitiveCount = primitiveCount; this.parameterSlotCount = (short)pslotCount; - this.lambdaForms = new SoftReference[LF_LIMIT]; - this.methodHandles = new SoftReference[MH_LIMIT]; + this.lambdaForms = new Object[LF_LIMIT]; + this.methodHandles = new Object[MH_LIMIT]; } else { this.basicType = MethodType.methodType(basicReturnType, basicPtypes, true); // fill in rest of data from the basic type: diff --git a/src/java.base/share/classes/java/lang/invoke/SerializedLambda.java b/src/java.base/share/classes/java/lang/invoke/SerializedLambda.java index 41aec5c47a1..3767bf23388 100644 --- a/src/java.base/share/classes/java/lang/invoke/SerializedLambda.java +++ b/src/java.base/share/classes/java/lang/invoke/SerializedLambda.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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,9 +28,6 @@ import java.io.InvalidObjectException; import java.io.ObjectStreamException; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Objects; /** @@ -265,25 +262,11 @@ public Object getCapturedArg(int i) { @java.io.Serial private Object readResolve() throws ObjectStreamException { try { - @SuppressWarnings("removal") - Method deserialize = AccessController.doPrivileged(new PrivilegedExceptionAction<>() { - @Override - public Method run() throws Exception { - Method m = capturingClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class); - m.setAccessible(true); - return m; - } - }); - + Method deserialize = capturingClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class); + deserialize.setAccessible(true); return deserialize.invoke(null, this); } catch (ReflectiveOperationException roe) { throw new InvalidObjectException("ReflectiveOperationException during deserialization", roe); - } catch (PrivilegedActionException e) { - Exception cause = e.getException(); - if (cause instanceof RuntimeException re) - throw re; - else - throw new RuntimeException("Exception in SerializedLambda.readResolve", e); } } diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 2f5b8f2407e..7e91057cbf4 100644 --- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -1080,6 +1080,8 @@ private StringConcatFactory() { * without copying. */ private static final class InlineHiddenClassStrategy { + // The CLASS_NAME prefix must be the same as used by HeapShared::is_string_concat_klass() + // in the HotSpot code. static final String CLASS_NAME = "java.lang.String$$StringConcat"; static final String METHOD_NAME = "concat"; diff --git a/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/src/java.base/share/classes/java/lang/module/ModuleFinder.java index 6b2e9228ad5..bc470633039 100644 --- a/src/java.base/share/classes/java/lang/module/ModuleFinder.java +++ b/src/java.base/share/classes/java/lang/module/ModuleFinder.java @@ -26,9 +26,6 @@ package java.lang.module; import java.nio.file.Path; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -130,16 +127,8 @@ public interface ModuleFinder { * * @return A {@code ModuleFinder} that locates the system modules */ - @SuppressWarnings("removal") static ModuleFinder ofSystem() { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("accessSystemModules")); - PrivilegedAction pa = SystemModuleFinders::ofSystem; - return AccessController.doPrivileged(pa); - } else { - return SystemModuleFinders.ofSystem(); - } + return SystemModuleFinders.ofSystem(); } /** diff --git a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java index 8ed4485666f..a045f9c196a 100644 --- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java +++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java @@ -28,15 +28,12 @@ import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandle; import java.lang.ref.WeakReference; -import java.security.AccessController; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.VM; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.reflect.ReflectionFactory; -import sun.security.action.GetPropertyAction; -import sun.security.util.SecurityConstants; /** * The {@code AccessibleObject} class is the base class for {@code Field}, @@ -81,17 +78,6 @@ public class AccessibleObject implements AnnotatedElement { SharedSecrets.setJavaLangReflectAccess(new ReflectAccess()); } - static void checkPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // SecurityConstants.ACCESS_PERMISSION is used to check - // whether a client has sufficient privilege to defeat Java - // language access control checks. - sm.checkPermission(SecurityConstants.ACCESS_PERMISSION); - } - } - /** * Convenience method to set the {@code accessible} flag for an * array of reflected objects. @@ -114,7 +100,6 @@ static void checkPermission() { */ @CallerSensitive public static void setAccessible(AccessibleObject[] array, boolean flag) { - checkPermission(); if (flag) { Class caller = Reflection.getCallerClass(); array = array.clone(); @@ -196,7 +181,6 @@ public static void setAccessible(AccessibleObject[] array, boolean flag) { */ @CallerSensitive // overrides in Method/Field/Constructor are @CS public void setAccessible(boolean flag) { - AccessibleObject.checkPermission(); setAccessible0(flag); } @@ -257,8 +241,6 @@ boolean setAccessible0(boolean flag) { */ @CallerSensitive public final boolean trySetAccessible() { - AccessibleObject.checkPermission(); - if (override == true) return true; // if it's not a Constructor, Method, Field then no access check @@ -502,10 +484,7 @@ protected AccessibleObject() {} // Reflection factory used by subclasses for creating field, // method, and constructor accessors. Note that this is called // very early in the bootstrapping process. - @SuppressWarnings("removal") - static final ReflectionFactory reflectionFactory = - AccessController.doPrivileged( - new ReflectionFactory.GetReflectionFactoryAction()); + static final ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory(); /** * {@inheritDoc} @@ -623,8 +602,7 @@ public Annotation[] getDeclaredAnnotations() { // For non-public members or members in package-private classes, // it is necessary to perform somewhat expensive access checks. // If the access check succeeds for a given class, it will - // always succeed (it is not affected by the granting or revoking - // of permissions); we speed up the check in the common case by + // always succeed; we speed up the check in the common case by // remembering the last Class for which the check succeeded. // // The simple access check for Constructor is to see if @@ -756,8 +734,7 @@ private boolean slowVerifyAccess(Class caller, Class memberClass, */ private static boolean printStackTraceWhenAccessFails() { if (!printStackPropertiesSet && VM.initLevel() >= 1) { - String s = GetPropertyAction.privilegedGetProperty( - "sun.reflect.debugModuleAccessChecks"); + String s = System.getProperty("sun.reflect.debugModuleAccessChecks"); if (s != null) { printStackWhenAccessFails = !s.equalsIgnoreCase("false"); } diff --git a/src/java.base/share/classes/java/lang/reflect/Constructor.java b/src/java.base/share/classes/java/lang/reflect/Constructor.java index 5eeceb68920..30445307369 100644 --- a/src/java.base/share/classes/java/lang/reflect/Constructor.java +++ b/src/java.base/share/classes/java/lang/reflect/Constructor.java @@ -181,7 +181,6 @@ Constructor newWithAccessor(ConstructorAccessor accessor) { @Override @CallerSensitive public void setAccessible(boolean flag) { - AccessibleObject.checkPermission(); if (flag) { checkCanSetAccessible(Reflection.getCallerClass()); } diff --git a/src/java.base/share/classes/java/lang/reflect/Field.java b/src/java.base/share/classes/java/lang/reflect/Field.java index f13893310a9..bffa211fe12 100644 --- a/src/java.base/share/classes/java/lang/reflect/Field.java +++ b/src/java.base/share/classes/java/lang/reflect/Field.java @@ -170,7 +170,6 @@ Field copy() { @Override @CallerSensitive public void setAccessible(boolean flag) { - AccessibleObject.checkPermission(); if (flag) checkCanSetAccessible(Reflection.getCallerClass()); setAccessible0(flag); } @@ -1155,7 +1154,6 @@ private void checkAccess(Class caller, Object obj) modifiers); } - // security check is done before calling this method private FieldAccessor getFieldAccessor() { FieldAccessor a = fieldAccessor; return (a != null) ? a : acquireFieldAccessor(); diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java index e60d83de0c8..f1d5ee63919 100644 --- a/src/java.base/share/classes/java/lang/reflect/Method.java +++ b/src/java.base/share/classes/java/lang/reflect/Method.java @@ -173,7 +173,6 @@ Method copy() { @Override @CallerSensitive public void setAccessible(boolean flag) { - AccessibleObject.checkPermission(); if (flag) checkCanSetAccessible(Reflection.getCallerClass()); setAccessible0(flag); } diff --git a/src/java.base/share/classes/java/lang/reflect/Proxy.java b/src/java.base/share/classes/java/lang/reflect/Proxy.java index fade83c0b38..77f3d3e1e71 100644 --- a/src/java.base/share/classes/java/lang/reflect/Proxy.java +++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java @@ -30,8 +30,6 @@ import java.lang.invoke.MethodType; import java.lang.invoke.WrongMethodTypeException; import java.lang.module.ModuleDescriptor; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Collections; @@ -52,13 +50,9 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.module.Modules; import jdk.internal.misc.VM; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; import jdk.internal.loader.ClassLoaderValue; import jdk.internal.vm.annotation.Stable; import sun.reflect.misc.ReflectUtil; -import sun.security.action.GetPropertyAction; -import sun.security.util.SecurityConstants; import static java.lang.invoke.MethodType.methodType; import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC; @@ -366,17 +360,11 @@ protected Proxy(InvocationHandler h) { * @see Package and Module Membership of Proxy Class */ @Deprecated - @CallerSensitive public static Class getProxyClass(ClassLoader loader, Class... interfaces) throws IllegalArgumentException { - @SuppressWarnings("removal") - Class caller = System.getSecurityManager() == null - ? null - : Reflection.getCallerClass(); - - return getProxyConstructor(caller, loader, interfaces) + return getProxyConstructor(loader, interfaces) .getDeclaringClass(); } @@ -386,25 +374,18 @@ public static Class getProxyClass(ClassLoader loader, * and an array of interfaces. The returned constructor will have the * {@link Constructor#setAccessible(boolean) accessible} flag already set. * - * @param caller passed from a public-facing @CallerSensitive method if - * SecurityManager is set or {@code null} if there's no - * SecurityManager * @param loader the class loader to define the proxy class * @param interfaces the list of interfaces for the proxy class * to implement * @return a Constructor of the proxy class taking single * {@code InvocationHandler} parameter */ - private static Constructor getProxyConstructor(Class caller, - ClassLoader loader, + private static Constructor getProxyConstructor(ClassLoader loader, Class... interfaces) { // optimization for single interface if (interfaces.length == 1) { Class intf = interfaces[0]; - if (caller != null) { - checkProxyAccess(caller, loader, intf); - } return proxyCache.sub(intf).computeIfAbsent( loader, (ld, clv) -> new ProxyBuilder(ld, clv.key()).build() @@ -412,9 +393,6 @@ private static Constructor getProxyConstructor(Class caller, } else { // interfaces cloned final Class[] intfsArray = interfaces.clone(); - if (caller != null) { - checkProxyAccess(caller, loader, intfsArray); - } final List> intfs = Arrays.asList(intfsArray); return proxyCache.sub(intfs).computeIfAbsent( loader, @@ -423,39 +401,6 @@ private static Constructor getProxyConstructor(Class caller, } } - /* - * Check permissions required to create a Proxy class. - * - * To define a proxy class, it performs the access checks as in - * Class.forName (VM will invoke ClassLoader.checkPackageAccess): - * 1. "getClassLoader" permission check if loader == null - * 2. checkPackageAccess on the interfaces it implements - * - * To get a constructor and new instance of a proxy class, it performs - * the package access check on the interfaces it implements - * as in Class.getConstructor. - * - * If an interface is non-public, the proxy class must be defined by - * the defining loader of the interface. If the caller's class loader - * is not the same as the defining loader of the interface, the VM - * will throw IllegalAccessError when the generated proxy class is - * being defined. - */ - private static void checkProxyAccess(Class caller, - ClassLoader loader, - Class ... interfaces) - { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader ccl = caller.getClassLoader(); - if (loader == null && ccl != null) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - ReflectUtil.checkProxyPackageAccess(ccl, interfaces); - } - } - /** * Builder for a proxy class. * @@ -516,7 +461,7 @@ private static Class defineProxyClass(ProxyClassContext context, List intf) { @@ -630,11 +574,7 @@ private static boolean isDebug(String flag) { * accessible flag already set. If the target module does not have access * to any interface types, IllegalAccessError will be thrown by the VM * at defineClass time. - * - * Must call the checkProxyAccess method to perform permission checks - * before calling this. */ - @SuppressWarnings("removal") Constructor build() { Class proxyClass = defineProxyClass(context, interfaces); @@ -644,12 +584,7 @@ Constructor build() { } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - cons.setAccessible(true); - return null; - } - }); + cons.setAccessible(true); return cons; } @@ -788,7 +723,7 @@ private static ProxyClassContext proxyClassContext(ClassLoader loader, throw new IllegalArgumentException( "cannot have non-public interfaces in different packages"); } - if (getLoader(m) != loader) { + if (m.getClassLoader() != loader) { // the specified loader is not the same class loader // of the non-public interface throw new IllegalArgumentException( @@ -979,36 +914,24 @@ private static Module getDynamicModule(ClassLoader loader) { * * @see Package and Module Membership of Proxy Class */ - @CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) { Objects.requireNonNull(h); - @SuppressWarnings("removal") - final Class caller = System.getSecurityManager() == null - ? null - : Reflection.getCallerClass(); - /* * Look up or generate the designated proxy class and its constructor. */ - Constructor cons = getProxyConstructor(caller, loader, interfaces); + Constructor cons = getProxyConstructor(loader, interfaces); - return newProxyInstance(caller, cons, h); + return newProxyInstance(cons, h); } - private static Object newProxyInstance(Class caller, // null if no SecurityManager - Constructor cons, - InvocationHandler h) { + private static Object newProxyInstance(Constructor cons, InvocationHandler h) { /* * Invoke its constructor with the designated invocation handler. */ try { - if (caller != null) { - checkNewProxyPermission(caller, cons.getDeclaringClass()); - } - return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException | InstantiationException e) { throw new InternalError(e.toString(), e); @@ -1022,35 +945,6 @@ private static Object newProxyInstance(Class caller, // null if no SecurityMa } } - private static void checkNewProxyPermission(Class caller, Class proxyClass) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { - ClassLoader ccl = caller.getClassLoader(); - ClassLoader pcl = proxyClass.getClassLoader(); - - // do permission check if the caller is in a different runtime package - // of the proxy class - String pkg = proxyClass.getPackageName(); - String callerPkg = caller.getPackageName(); - - if (pcl != ccl || !pkg.equals(callerPkg)) { - sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg)); - } - } - } - } - - /** - * Returns the class loader for the given module. - */ - @SuppressWarnings("removal") - private static ClassLoader getLoader(Module m) { - PrivilegedAction pa = m::getClassLoader; - return AccessController.doPrivileged(pa); - } - /** * Returns true if the given class is a proxy class. * @@ -1075,8 +969,6 @@ public static boolean isProxyClass(Class cl) { * @throws IllegalArgumentException if the argument is not a * proxy instance */ - @SuppressWarnings("removal") - @CallerSensitive public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException { @@ -1089,16 +981,6 @@ public static InvocationHandler getInvocationHandler(Object proxy) final Proxy p = (Proxy) proxy; final InvocationHandler ih = p.h; - if (System.getSecurityManager() != null) { - Class ihClass = ih.getClass(); - Class caller = Reflection.getCallerClass(); - if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), - ihClass.getClassLoader())) - { - ReflectUtil.checkPackageAccess(ihClass); - } - } - return ih; } @@ -1249,20 +1131,14 @@ private static Class findProxyInterfaceOrElseThrow(Class proxyClass, Metho * * @return a lookup for proxy class of this proxy instance */ - @SuppressWarnings("removal") private static MethodHandles.Lookup proxyClassLookup(MethodHandles.Lookup caller, Class proxyClass) { - return AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public MethodHandles.Lookup run() { - try { - Method m = proxyClass.getDeclaredMethod("proxyClassLookup", MethodHandles.Lookup.class); - m.setAccessible(true); - return (MethodHandles.Lookup) m.invoke(null, caller); - } catch (ReflectiveOperationException e) { - throw new InternalError(e); - } - } - }); + try { + Method m = proxyClass.getDeclaredMethod("proxyClassLookup", MethodHandles.Lookup.class); + m.setAccessible(true); + return (MethodHandles.Lookup) m.invoke(null, caller); + } catch (ReflectiveOperationException e) { + throw new InternalError(e); + } } /* diff --git a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java index efbb3919ef5..96e0a7e729f 100644 --- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java +++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java @@ -43,7 +43,6 @@ import jdk.internal.constant.ClassOrInterfaceDescImpl; import jdk.internal.constant.ConstantUtils; import jdk.internal.constant.MethodTypeDescImpl; -import sun.security.action.GetBooleanAction; import static java.lang.classfile.ClassFile.*; import java.lang.classfile.attribute.StackMapFrameInfo; @@ -106,9 +105,8 @@ final class ProxyGenerator { */ @SuppressWarnings("removal") private static final boolean SAVE_GENERATED_FILES = - java.security.AccessController.doPrivileged( - new GetBooleanAction( - "jdk.proxy.ProxyGenerator.saveGeneratedFiles")); + Boolean.getBoolean("jdk.proxy.ProxyGenerator.saveGeneratedFiles"); + /* Preloaded ProxyMethod objects for methods in java.lang.Object */ private static final Method OBJECT_HASH_CODE_METHOD; @@ -215,27 +213,21 @@ static byte[] generateProxyClass(ClassLoader loader, final byte[] classFile = gen.generateClassFile(); if (SAVE_GENERATED_FILES) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - try { - int i = name.lastIndexOf('.'); - Path path; - if (i > 0) { - Path dir = Path.of(name.substring(0, i).replace('.', '/')); - Files.createDirectories(dir); - path = dir.resolve(name.substring(i + 1) + ".class"); - } else { - path = Path.of(name + ".class"); - } - Files.write(path, classFile); - return null; - } catch (IOException e) { - throw new InternalError( - "I/O exception saving generated file: " + e); - } - } - }); + try { + int i = name.lastIndexOf('.'); + Path path; + if (i > 0) { + Path dir = Path.of(name.substring(0, i).replace('.', '/')); + Files.createDirectories(dir); + path = dir.resolve(name.substring(i + 1) + ".class"); + } else { + path = Path.of(name + ".class"); + } + Files.write(path, classFile); + return null; + } catch (IOException e) { + throw new InternalError("I/O exception saving generated file: " + e); + } } return classFile; @@ -565,11 +557,6 @@ private void generateConstructor(ClassBuilder clb) { /** * Generate the class initializer. - * Discussion: Currently, for Proxy to work with SecurityManager, - * we rely on the parameter classes of the methods to be computed - * from Proxy instead of via user code paths like bootstrap method - * lazy evaluation. That might change if we can pass in the live - * Method objects directly.. */ private void generateStaticInitializer(ClassBuilder clb) { clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> { @@ -786,9 +773,6 @@ private void codeUnwrapReturnValue(CodeBuilder cob, Class type) { * Generate code for initializing the static field that stores * the Method object for this proxy method. A class loader is * anticipated at local variable index 0. - * The generated code must be run in an AccessController.doPrivileged - * block if a SecurityManager is present, as otherwise the code - * cannot pass {@code null} ClassLoader to forName. */ private void codeFieldInitialization(CodeBuilder cob) { var cp = cob.constantPool(); diff --git a/src/java.base/share/classes/java/net/Authenticator.java b/src/java.base/share/classes/java/net/Authenticator.java index 0935366abc1..9ac504f9a62 100644 --- a/src/java.base/share/classes/java/net/Authenticator.java +++ b/src/java.base/share/classes/java/net/Authenticator.java @@ -112,14 +112,6 @@ private void reset() { * any previously set authenticator is removed. */ public static synchronized void setDefault(Authenticator a) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - NetPermission setDefaultPermission - = new NetPermission("setDefaultAuthenticator"); - sm.checkPermission(setDefaultPermission); - } - theAuthenticator = a; } @@ -130,13 +122,6 @@ public static synchronized void setDefault(Authenticator a) { * @since 9 */ public static Authenticator getDefault() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - NetPermission requestPermission - = new NetPermission("requestPasswordAuthentication"); - sm.checkPermission(requestPermission); - } return theAuthenticator; } @@ -161,14 +146,6 @@ public static PasswordAuthentication requestPasswordAuthentication( String prompt, String scheme) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - NetPermission requestPermission - = new NetPermission("requestPasswordAuthentication"); - sm.checkPermission(requestPermission); - } - Authenticator a = theAuthenticator; if (a == null) { return null; @@ -212,14 +189,6 @@ public static PasswordAuthentication requestPasswordAuthentication( String prompt, String scheme) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - NetPermission requestPermission - = new NetPermission("requestPasswordAuthentication"); - sm.checkPermission(requestPermission); - } - Authenticator a = theAuthenticator; if (a == null) { return null; @@ -267,14 +236,6 @@ public static PasswordAuthentication requestPasswordAuthentication( URL url, RequestorType reqType) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - NetPermission requestPermission - = new NetPermission("requestPasswordAuthentication"); - sm.checkPermission(requestPermission); - } - Authenticator a = theAuthenticator; if (a == null) { return null; @@ -328,14 +289,6 @@ public static PasswordAuthentication requestPasswordAuthentication( URL url, RequestorType reqType) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - NetPermission requestPermission - = new NetPermission("requestPasswordAuthentication"); - sm.checkPermission(requestPermission); - } - Authenticator a = authenticator == null ? theAuthenticator : authenticator; if (a == null) { return null; diff --git a/src/java.base/share/classes/java/net/CookieHandler.java b/src/java.base/share/classes/java/net/CookieHandler.java index 4b5e3ebedd8..ec20c860591 100644 --- a/src/java.base/share/classes/java/net/CookieHandler.java +++ b/src/java.base/share/classes/java/net/CookieHandler.java @@ -28,7 +28,6 @@ import java.util.Map; import java.util.List; import java.io.IOException; -import sun.security.util.SecurityConstants; /** * A CookieHandler object provides a callback mechanism to hook up a @@ -73,11 +72,6 @@ public CookieHandler() {} * @see #setDefault(CookieHandler) */ public static synchronized CookieHandler getDefault() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.GET_COOKIEHANDLER_PERMISSION); - } return cookieHandler; } @@ -91,11 +85,6 @@ public static synchronized CookieHandler getDefault() { * @see #getDefault() */ public static synchronized void setDefault(CookieHandler cHandler) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.SET_COOKIEHANDLER_PERMISSION); - } cookieHandler = cHandler; } diff --git a/src/java.base/share/classes/java/net/IDN.java b/src/java.base/share/classes/java/net/IDN.java index 5e01ab6532d..6f11643264f 100644 --- a/src/java.base/share/classes/java/net/IDN.java +++ b/src/java.base/share/classes/java/net/IDN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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,8 +26,6 @@ import java.io.InputStream; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; import jdk.internal.icu.impl.Punycode; import jdk.internal.icu.text.StringPrep; @@ -248,14 +246,7 @@ public static String toUnicode(String input) { StringPrep stringPrep = null; try { final String IDN_PROFILE = "/sun/net/idn/uidna.spp"; - @SuppressWarnings("removal") - InputStream stream = System.getSecurityManager() != null - ? AccessController.doPrivileged(new PrivilegedAction<>() { - public InputStream run() { - return StringPrep.class.getResourceAsStream(IDN_PROFILE); - }}) - : StringPrep.class.getResourceAsStream(IDN_PROFILE); - + InputStream stream = StringPrep.class.getResourceAsStream(IDN_PROFILE); stringPrep = new StringPrep(stream); stream.close(); } catch (IOException e) { diff --git a/src/java.base/share/classes/java/net/NetworkInterface.java b/src/java.base/share/classes/java/net/NetworkInterface.java index 1c5edd1c23f..29a07d9b76d 100644 --- a/src/java.base/share/classes/java/net/NetworkInterface.java +++ b/src/java.base/share/classes/java/net/NetworkInterface.java @@ -27,6 +27,7 @@ import java.util.Arrays; import java.util.Enumeration; +import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Spliterator; @@ -79,9 +80,9 @@ public final class NetworkInterface { private String name; private String displayName; private int index; - private InetAddress addrs[]; - private InterfaceAddress bindings[]; - private NetworkInterface childs[]; + private InetAddress[] addrs; + private InterfaceAddress[] bindings; + private NetworkInterface[] childs; private NetworkInterface parent = null; private boolean virtual = false; private static final NetworkInterface defaultInterface; @@ -118,87 +119,46 @@ public String getName() { } /** - * Get an Enumeration with all, or a subset, of the InetAddresses bound to - * this network interface. + * Get an Enumeration of the InetAddresses bound to this network interface. * * @implNote - * The returned enumeration contains all, or a subset, of the InetAddresses that were - * bound to the interface at the time the {@linkplain #getNetworkInterfaces() + * The returned enumeration contains the InetAddresses that were bound to + * the interface at the time the {@linkplain #getNetworkInterfaces() * interface configuration was read} * - * @return an Enumeration object with all, or a subset, of the InetAddresses - * bound to this network interface + * @return an Enumeration object with the InetAddresses bound to this + * network interface * @see #inetAddresses() */ public Enumeration getInetAddresses() { - return enumerationFromArray(getCheckedInetAddresses()); + return enumerationFromArray(addrs); } /** - * Get a Stream of all, or a subset, of the InetAddresses bound to this - * network interface. + * Get a Stream of the InetAddresses bound to this network interface. * * @implNote - * The stream contains all, or a subset, of the InetAddresses that were - * bound to the interface at the time the {@linkplain #getNetworkInterfaces() + * The stream contains the InetAddresses that were bound to the + * interface at the time the {@linkplain #getNetworkInterfaces() * interface configuration was read} * - * @return a Stream object with all, or a subset, of the InetAddresses - * bound to this network interface + * @return a Stream object with the InetAddresses bound to this network interface * @since 9 */ public Stream inetAddresses() { - return streamFromArray(getCheckedInetAddresses()); - } - - private InetAddress[] getCheckedInetAddresses() { - InetAddress[] local_addrs = new InetAddress[addrs.length]; - boolean trusted = true; - - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - if (sec != null) { - try { - sec.checkPermission(new NetPermission("getNetworkInformation")); - } catch (SecurityException e) { - trusted = false; - } - } - int i = 0; - for (int j = 0; j < addrs.length; j++) { - try { - if (!trusted) { - sec.checkConnect(addrs[j].getHostAddress(), -1); - } - local_addrs[i++] = addrs[j]; - } catch (SecurityException e) { } - } - return Arrays.copyOf(local_addrs, i); + return streamFromArray(addrs); } /** - * Get a List of all, or a subset, of the {@code InterfaceAddresses} - * of this network interface. + * Get a List of the {@code InterfaceAddresses} of this network interface. + * + * @return a {@code List} object with the InterfaceAddress of this + * network interface * - * @return a {@code List} object with all, or a subset, of the - * InterfaceAddress of this network interface * @since 1.6 */ - public java.util.List getInterfaceAddresses() { - java.util.List lst = new java.util.ArrayList<>(1); - if (bindings != null) { - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - for (int j=0; j getInterfaceAddresses() { + return bindings == null ? List.of() : List.of(bindings); } /** @@ -556,18 +516,6 @@ public boolean supportsMulticast() throws SocketException { * @since 1.6 */ public byte[] getHardwareAddress() throws SocketException { - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - if (sec != null) { - try { - sec.checkPermission(new NetPermission("getNetworkInformation")); - } catch (SecurityException e) { - if (!getInetAddresses().hasMoreElements()) { - // don't have connect permission to any local address - return null; - } - } - } if (isLoopback0(name, index)) { return null; } diff --git a/src/java.base/share/classes/java/net/ProxySelector.java b/src/java.base/share/classes/java/net/ProxySelector.java index ee1f9ef3710..613fe2aa176 100644 --- a/src/java.base/share/classes/java/net/ProxySelector.java +++ b/src/java.base/share/classes/java/net/ProxySelector.java @@ -28,8 +28,6 @@ import java.io.IOException; import java.util.List; -import sun.security.util.SecurityConstants; - /** * Selects the proxy server to use, if any, when connecting to the * network resource referenced by a URL. A proxy selector is a @@ -94,11 +92,6 @@ public ProxySelector() {} * @since 1.5 */ public static ProxySelector getDefault() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.GET_PROXYSELECTOR_PERMISSION); - } return theProxySelector; } @@ -114,11 +107,6 @@ public static ProxySelector getDefault() { * @since 1.5 */ public static void setDefault(ProxySelector ps) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.SET_PROXYSELECTOR_PERMISSION); - } theProxySelector = ps; } diff --git a/src/java.base/share/classes/java/net/ResponseCache.java b/src/java.base/share/classes/java/net/ResponseCache.java index 292c1b7610d..3339f41883b 100644 --- a/src/java.base/share/classes/java/net/ResponseCache.java +++ b/src/java.base/share/classes/java/net/ResponseCache.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.util.Map; import java.util.List; -import sun.security.util.SecurityConstants; /** * Represents implementations of URLConnection caches. An instance of @@ -84,11 +83,6 @@ public ResponseCache() {} * @since 1.5 */ public static synchronized ResponseCache getDefault() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.GET_RESPONSECACHE_PERMISSION); - } return theResponseCache; } @@ -104,11 +98,6 @@ public static synchronized ResponseCache getDefault() { * @since 1.5 */ public static synchronized void setDefault(ResponseCache responseCache) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.SET_RESPONSECACHE_PERMISSION); - } theResponseCache = responseCache; } diff --git a/src/java.base/share/classes/java/net/ServerSocket.java b/src/java.base/share/classes/java/net/ServerSocket.java index c6560fee35a..945693ef65e 100644 --- a/src/java.base/share/classes/java/net/ServerSocket.java +++ b/src/java.base/share/classes/java/net/ServerSocket.java @@ -33,7 +33,6 @@ import java.util.Set; import java.util.Collections; -import sun.security.util.SecurityConstants; import sun.net.PlatformSocketImpl; /** @@ -89,13 +88,6 @@ public class ServerSocket implements java.io.Closeable { // used to coordinate creating and closing underlying socket private final Object socketLock = new Object(); - /** - * Creates a server socket with the given {@code SocketImpl}. - */ - private ServerSocket(Void unused, SocketImpl impl) { - this.impl = Objects.requireNonNull(impl); - } - /** * Creates a server socket with a user-specified {@code SocketImpl}. * @@ -106,16 +98,7 @@ private ServerSocket(Void unused, SocketImpl impl) { * @since 12 */ protected ServerSocket(SocketImpl impl) { - this(checkPermission(), impl); - } - - private static Void checkPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION); - } - return null; + this.impl = Objects.requireNonNull(impl); } /** @@ -237,7 +220,7 @@ public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOExcept this.impl = createImpl(); try { bind(new InetSocketAddress(bindAddr, port), backlog); - } catch (IOException | SecurityException e) { + } catch (IOException e) { close(); throw e; } @@ -338,11 +321,6 @@ public void bind(SocketAddress endpoint, int backlog) throws IOException { if (backlog < 1) backlog = 50; - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) - security.checkListen(epoint.getPort()); - // SocketImpl bind+listen throw if already bound or closed SocketImpl impl = getImpl(); impl.bind(epoint.getAddress(), epoint.getPort()); @@ -364,14 +342,7 @@ public InetAddress getInetAddress() { if (!isBound()) return null; try { - InetAddress in = getImpl().getInetAddress(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkConnect(in.getHostAddress(), -1); - return in; - } catch (SecurityException e) { - return InetAddress.getLoopbackAddress(); + return getImpl().getInetAddress(); } catch (SocketException e) { // nothing // If we're bound, the impl has been created @@ -631,17 +602,6 @@ private void implAccept(SocketImpl si) throws IOException { throw e; } - // check permission, close SocketImpl/connection if denied - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkAccept(si.getInetAddress().getHostAddress(), si.getPort()); - } catch (SecurityException se) { - si.close(); - throw se; - } - } } /** @@ -835,15 +795,10 @@ public boolean getReuseAddress() throws SocketException { * * @return a string representation of this socket. */ - @SuppressWarnings("removal") public String toString() { if (!isBound()) return "ServerSocket[unbound]"; - InetAddress in; - if (System.getSecurityManager() != null) - in = getInetAddress(); - else - in = impl.getInetAddress(); + InetAddress in = impl.getInetAddress(); return "ServerSocket[addr=" + in + ",localport=" + impl.getLocalPort() + "]"; } @@ -884,11 +839,6 @@ public static synchronized void setSocketFactory(SocketImplFactory fac) throws I if (factory != null) { throw new SocketException("factory already defined"); } - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkSetFactory(); - } factory = fac; } diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java index 9825457aac1..83c0dec682c 100644 --- a/src/java.base/share/classes/java/net/Socket.java +++ b/src/java.base/share/classes/java/net/Socket.java @@ -28,7 +28,6 @@ import jdk.internal.event.SocketReadEvent; import jdk.internal.event.SocketWriteEvent; import jdk.internal.invoke.MhUtil; -import sun.security.util.SecurityConstants; import java.io.InputStream; import java.io.InterruptedIOException; @@ -157,15 +156,6 @@ private static boolean isOutputShutdown(int s) { return (s & SHUT_OUT) != 0; } - /** - * Creates an unconnected socket with the given {@code SocketImpl}. - */ - private Socket(Void unused, SocketImpl impl) { - if (impl != null) { - this.impl = impl; - } - } - /** * Creates an unconnected Socket. *

@@ -212,22 +202,10 @@ public Socket(Proxy proxy) { : sun.net.ApplicationProxy.create(proxy); Proxy.Type type = p.type(); if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); InetSocketAddress epoint = (InetSocketAddress) p.address(); if (epoint.getAddress() != null) { checkAddress (epoint.getAddress(), "Socket"); } - if (security != null) { - if (epoint.isUnresolved()) - epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort()); - if (epoint.isUnresolved()) - security.checkConnect(epoint.getHostName(), epoint.getPort()); - else - security.checkConnect(epoint.getAddress().getHostAddress(), - epoint.getPort()); - } - // create a SOCKS or HTTP SocketImpl that delegates to a platform SocketImpl SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false); impl = (type == Proxy.Type.SOCKS) ? new SocksSocketImpl(p, delegate) @@ -259,18 +237,9 @@ public Socket(Proxy proxy) { * @since 1.1 */ protected Socket(SocketImpl impl) throws SocketException { - this(checkPermission(impl), impl); - } - - private static Void checkPermission(SocketImpl impl) { if (impl != null) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION); - } + this.impl = impl; } - return null; } /** @@ -497,7 +466,7 @@ private Socket(SocketAddress address, SocketAddress localAddr, boolean stream) if (localAddr != null) bind(localAddr); connect(address); - } catch (IOException | IllegalArgumentException | SecurityException e) { + } catch (IOException | IllegalArgumentException e) { try { close(); } catch (IOException ce) { @@ -684,15 +653,6 @@ public void connect(SocketAddress endpoint, int timeout) throws IOException { int port = epoint.getPort(); checkAddress(addr, "connect"); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - if (epoint.isUnresolved()) - security.checkConnect(epoint.getHostName(), port); - else - security.checkConnect(addr.getHostAddress(), port); - } - try { getImpl().connect(epoint, timeout); } catch (SocketTimeoutException e) { @@ -743,11 +703,6 @@ public void bind(SocketAddress bindpoint) throws IOException { InetAddress addr = epoint.getAddress(); int port = epoint.getPort(); checkAddress (addr, "bind"); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkListen(port); - } getImpl().bind(addr, port); getAndBitwiseOrState(BOUND); } @@ -795,15 +750,9 @@ public InetAddress getLocalAddress() { InetAddress in = null; try { in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkConnect(in.getHostAddress(), -1); if (in.isAnyLocalAddress()) { in = InetAddress.anyLocalAddress(); } - } catch (SecurityException e) { - in = InetAddress.getLoopbackAddress(); } catch (Exception e) { in = InetAddress.anyLocalAddress(); // "0.0.0.0" } @@ -1855,11 +1804,6 @@ public static synchronized void setSocketImplFactory(SocketImplFactory fac) if (factory != null) { throw new SocketException("factory already defined"); } - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkSetFactory(); - } factory = fac; } diff --git a/src/java.base/share/classes/java/net/URL.java b/src/java.base/share/classes/java/net/URL.java index 418651bc7c2..be4daa28f33 100644 --- a/src/java.base/share/classes/java/net/URL.java +++ b/src/java.base/share/classes/java/net/URL.java @@ -30,8 +30,6 @@ import java.io.InputStream; import java.net.spi.URLStreamHandlerProvider; import java.nio.file.Path; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Hashtable; import java.io.InvalidObjectException; import java.io.ObjectStreamException; @@ -39,8 +37,6 @@ import java.io.ObjectInputStream.GetField; import java.util.Iterator; import java.util.Locale; -import java.util.NoSuchElementException; -import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import jdk.internal.access.JavaNetURLAccess; @@ -48,8 +44,6 @@ import jdk.internal.misc.ThreadTracker; import jdk.internal.misc.VM; import sun.net.util.IPAddressUtil; -import sun.security.util.SecurityConstants; -import sun.security.action.GetPropertyAction; /** * Class {@code URL} represents a Uniform Resource @@ -485,14 +479,6 @@ public URL(String protocol, String host, String file) @Deprecated(since = "20") public URL(String protocol, String host, int port, String file, URLStreamHandler handler) throws MalformedURLException { - if (handler != null) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // check for permission to specify a handler - checkSpecifyHandler(sm); - } - } protocol = lowerCaseProtocol(protocol); this.protocol = protocol; @@ -683,15 +669,6 @@ public URL(URL context, String spec, URLStreamHandler handler) boolean aRef=false; boolean isRelative = false; - // Check for permission to specify a handler - if (handler != null) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkSpecifyHandler(sm); - } - } - try { limit = spec.length(); while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) { @@ -912,13 +889,6 @@ private boolean isValidProtocol(String protocol) { return true; } - /* - * Checks for permission to specify a stream handler. - */ - private void checkSpecifyHandler(@SuppressWarnings("removal") SecurityManager sm) { - sm.checkPermission(SecurityConstants.SPECIFY_HANDLER_PERMISSION); - } - /** * Sets the specified 8 fields of the URL. This is not a public method so * that only URLStreamHandlers can modify URL fields. URLs are otherwise @@ -956,9 +926,8 @@ void set(String protocol, String host, int port, /** * Returns the address of the host represented by this URL. - * A {@link SecurityException} or an {@link UnknownHostException} - * while getting the host address will result in this method returning - * {@code null} + * An {@link UnknownHostException} while getting the host address + * will result in this method returning {@code null}. * * @return an {@link InetAddress} representing the host */ @@ -972,7 +941,7 @@ synchronized InetAddress getHostAddress() { } try { hostAddress = InetAddress.getByName(host); - } catch (UnknownHostException | SecurityException ex) { + } catch (UnknownHostException e) { return null; } return hostAddress; @@ -1271,16 +1240,6 @@ public URLConnection openConnection(Proxy proxy) // Create a copy of Proxy as a security measure Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (p.type() != Proxy.Type.DIRECT && sm != null) { - InetSocketAddress epoint = (InetSocketAddress) p.address(); - if (epoint.isUnresolved()) - sm.checkConnect(epoint.getHostName(), epoint.getPort()); - else - sm.checkConnect(epoint.getAddress().getHostAddress(), - epoint.getPort()); - } return handler.openConnection(this, p); } @@ -1358,11 +1317,6 @@ public static void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) { if (factory != null) { throw new Error("factory already defined"); } - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkSetFactory(); - } handlers.clear(); // safe publication of URLStreamHandlerFactory with volatile write @@ -1398,8 +1352,7 @@ public URLStreamHandler createURLStreamHandler(String protocol) { } private static URLStreamHandler lookupViaProperty(String protocol) { - String packagePrefixList = - GetPropertyAction.privilegedGetProperty(protocolPathProp); + String packagePrefixList = System.getProperty(protocolPathProp); if (packagePrefixList == null || packagePrefixList.isEmpty()) { // not set return null; @@ -1435,47 +1388,6 @@ private static URLStreamHandler lookupViaProperty(String protocol) { return handler; } - private static Iterator providers() { - return new Iterator<>() { - - final ClassLoader cl = ClassLoader.getSystemClassLoader(); - final ServiceLoader sl = - ServiceLoader.load(URLStreamHandlerProvider.class, cl); - final Iterator i = sl.iterator(); - - URLStreamHandlerProvider next = null; - - private boolean getNext() { - while (next == null) { - try { - if (!i.hasNext()) - return false; - next = i.next(); - } catch (ServiceConfigurationError sce) { - if (sce.getCause() instanceof SecurityException) { - // Ignore security exceptions - continue; - } - throw sce; - } - } - return true; - } - - public boolean hasNext() { - return getNext(); - } - - public URLStreamHandlerProvider next() { - if (!getNext()) - throw new NoSuchElementException(); - URLStreamHandlerProvider n = next; - next = null; - return n; - } - }; - } - private static class ThreadTrackHolder { static final ThreadTracker TRACKER = new ThreadTracker(); } @@ -1488,26 +1400,23 @@ private static void endLookup(Object key) { ThreadTrackHolder.TRACKER.end(key); } - @SuppressWarnings("removal") private static URLStreamHandler lookupViaProviders(final String protocol) { Object key = tryBeginLookup(); if (key == null) { throw new Error("Circular loading of URL stream handler providers detected"); } try { - return AccessController.doPrivileged( - new PrivilegedAction<>() { - public URLStreamHandler run() { - Iterator itr = providers(); - while (itr.hasNext()) { - URLStreamHandlerProvider f = itr.next(); - URLStreamHandler h = f.createURLStreamHandler(protocol); - if (h != null) - return h; - } - return null; - } - }); + final ClassLoader cl = ClassLoader.getSystemClassLoader(); + final ServiceLoader sl = + ServiceLoader.load(URLStreamHandlerProvider.class, cl); + final Iterator itr = sl.iterator(); + while (itr.hasNext()) { + URLStreamHandlerProvider f = itr.next(); + URLStreamHandler h = f.createURLStreamHandler(protocol); + if (h != null) + return h; + } + return null; } finally { endLookup(key); } diff --git a/src/java.base/share/classes/java/net/URLClassLoader.java b/src/java.base/share/classes/java/net/URLClassLoader.java index 4d43d358a64..d867b7e2b62 100644 --- a/src/java.base/share/classes/java/net/URLClassLoader.java +++ b/src/java.base/share/classes/java/net/URLClassLoader.java @@ -30,14 +30,10 @@ import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; -import java.security.AccessControlContext; -import java.security.AccessController; import java.security.CodeSigner; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; import java.security.SecureClassLoader; import java.util.Enumeration; import java.util.List; @@ -76,10 +72,6 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { /* The search path for classes and resources */ private final URLClassPath ucp; - /* The context to be used when loading classes and resources */ - @SuppressWarnings("removal") - private final AccessControlContext acc; - /** * Constructs a new URLClassLoader for the given URLs. The URLs will be * searched in the order specified for classes and resources after first @@ -94,18 +86,9 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { * @throws NullPointerException if {@code urls} or any of its * elements is {@code null}. */ - @SuppressWarnings("removal") public URLClassLoader(URL[] urls, ClassLoader parent) { super(parent); - this.acc = AccessController.getContext(); - this.ucp = new URLClassPath(urls, acc); - } - - URLClassLoader(String name, URL[] urls, ClassLoader parent, - @SuppressWarnings("removal") AccessControlContext acc) { - super(name, parent); - this.acc = acc; - this.ucp = new URLClassPath(urls, acc); + this.ucp = new URLClassPath(urls); } /** @@ -122,17 +105,9 @@ public URLClassLoader(URL[] urls, ClassLoader parent) { * @throws NullPointerException if {@code urls} or any of its * elements is {@code null}. */ - @SuppressWarnings("removal") public URLClassLoader(URL[] urls) { super(); - this.acc = AccessController.getContext(); - this.ucp = new URLClassPath(urls, acc); - } - - URLClassLoader(URL[] urls, @SuppressWarnings("removal") AccessControlContext acc) { - super(); - this.acc = acc; - this.ucp = new URLClassPath(urls, acc); + this.ucp = new URLClassPath(urls); } /** @@ -149,12 +124,10 @@ public URLClassLoader(URL[] urls) { * @throws NullPointerException if {@code urls} or any of its * elements is {@code null}. */ - @SuppressWarnings("removal") public URLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) { super(parent); - this.acc = AccessController.getContext(); - this.ucp = new URLClassPath(urls, factory, acc); + this.ucp = new URLClassPath(urls, factory); } @@ -176,13 +149,11 @@ public URLClassLoader(URL[] urls, ClassLoader parent, * * @since 9 */ - @SuppressWarnings("removal") public URLClassLoader(String name, URL[] urls, ClassLoader parent) { super(name, parent); - this.acc = AccessController.getContext(); - this.ucp = new URLClassPath(urls, acc); + this.ucp = new URLClassPath(urls); } /** @@ -203,12 +174,10 @@ public URLClassLoader(String name, * * @since 9 */ - @SuppressWarnings("removal") public URLClassLoader(String name, URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) { super(name, parent); - this.acc = AccessController.getContext(); - this.ucp = new URLClassPath(urls, factory, acc); + this.ucp = new URLClassPath(urls, factory); } /* A map (used as a set) to keep track of closeable local resources @@ -299,11 +268,6 @@ public InputStream getResourceAsStream(String name) { * @since 1.7 */ public void close() throws IOException { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(new RuntimePermission("closeClassLoader")); - } List errors = ucp.closeLoaders(); // now close any remaining streams. @@ -369,40 +333,24 @@ public URL[] getURLs() { * or if the loader is closed. * @throws NullPointerException if {@code name} is {@code null}. */ - @SuppressWarnings("removal") protected Class findClass(final String name) throws ClassNotFoundException { - final Class result; - try { - result = AccessController.doPrivileged( - new PrivilegedExceptionAction<>() { - public Class run() throws ClassNotFoundException { - String path = name.replace('.', '/').concat(".class"); - Resource res = ucp.getResource(path, false); - if (res != null) { - try { - return defineClass(name, res); - } catch (IOException e) { - throw new ClassNotFoundException(name, e); - } catch (ClassFormatError e2) { - if (res.getDataError() != null) { - e2.addSuppressed(res.getDataError()); - } - throw e2; - } - } else { - return null; - } - } - }, acc); - } catch (java.security.PrivilegedActionException pae) { - throw (ClassNotFoundException) pae.getException(); - } - if (result == null) { - throw new ClassNotFoundException(name); + String path = name.replace('.', '/').concat(".class"); + Resource res = ucp.getResource(path); + if (res != null) { + try { + return defineClass(name, res); + } catch (IOException e) { + throw new ClassNotFoundException(name, e); + } catch (ClassFormatError e2) { + if (res.getDataError() != null) { + e2.addSuppressed(res.getDataError()); + } + throw e2; + } } - return result; + throw new ClassNotFoundException(name); } /* @@ -575,18 +523,7 @@ private boolean isSealed(String name, Manifest man) { * if the resource could not be found, or if the loader is closed. */ public URL findResource(final String name) { - /* - * The same restriction to finding classes applies to resources - */ - @SuppressWarnings("removal") - URL url = AccessController.doPrivileged( - new PrivilegedAction<>() { - public URL run() { - return ucp.findResource(name, true); - } - }, acc); - - return url != null ? URLClassPath.checkURL(url) : null; + return ucp.findResource(name); } /** @@ -598,10 +535,11 @@ public URL run() { * @return An {@code Enumeration} of {@code URL}s. * If the loader is closed, the Enumeration contains no elements. */ + @Override public Enumeration findResources(final String name) throws IOException { - final Enumeration e = ucp.findResources(name, true); + final Enumeration e = ucp.findResources(name); return new Enumeration<>() { private URL url = null; @@ -610,23 +548,14 @@ private boolean next() { if (url != null) { return true; } - do { - @SuppressWarnings("removal") - URL u = AccessController.doPrivileged( - new PrivilegedAction<>() { - public URL run() { - if (!e.hasMoreElements()) - return null; - return e.nextElement(); - } - }, acc); - if (u == null) - break; - url = URLClassPath.checkURL(u); - } while (url == null); + if (!e.hasMoreElements()) { + return false; + } + url = e.nextElement(); return url != null; } + @Override public URL nextElement() { if (!next()) { throw new NoSuchElementException(); @@ -636,6 +565,7 @@ public URL nextElement() { return u; } + @Override public boolean hasMoreElements() { return next(); } @@ -666,7 +596,6 @@ public boolean hasMoreElements() { * @throws NullPointerException if {@code codesource} is {@code null}. * @return the permissions for the codesource */ - @SuppressWarnings("removal") protected PermissionCollection getPermissions(CodeSource codesource) { PermissionCollection perms = super.getPermissions(codesource); @@ -712,23 +641,13 @@ protected PermissionCollection getPermissions(CodeSource codesource) String host = locUrl.getHost(); if (host != null && !host.isEmpty()) p = new SocketPermission(host, - SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION); + SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION); } // make sure the person that created this class loader // would have this permission if (p != null) { - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - final Permission fp = p; - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() throws SecurityException { - sm.checkPermission(fp); - return null; - } - }, acc); - } perms.add(p); } return perms; @@ -746,18 +665,7 @@ public Void run() throws SecurityException { */ public static URLClassLoader newInstance(final URL[] urls, final ClassLoader parent) { - // Save the caller's context - @SuppressWarnings("removal") - final AccessControlContext acc = AccessController.getContext(); - // Need a privileged block to create the class loader - @SuppressWarnings("removal") - URLClassLoader ucl = AccessController.doPrivileged( - new PrivilegedAction<>() { - public URLClassLoader run() { - return new FactoryURLClassLoader(null, urls, parent, acc); - } - }); - return ucl; + return new URLClassLoader(null, urls, parent); } /** @@ -770,53 +678,10 @@ public URLClassLoader run() { * @return the resulting class loader */ public static URLClassLoader newInstance(final URL[] urls) { - // Save the caller's context - @SuppressWarnings("removal") - final AccessControlContext acc = AccessController.getContext(); - // Need a privileged block to create the class loader - @SuppressWarnings("removal") - URLClassLoader ucl = AccessController.doPrivileged( - new PrivilegedAction<>() { - public URLClassLoader run() { - return new FactoryURLClassLoader(urls, acc); - } - }); - return ucl; + return new URLClassLoader(urls); } static { ClassLoader.registerAsParallelCapable(); } } - -final class FactoryURLClassLoader extends URLClassLoader { - - static { - ClassLoader.registerAsParallelCapable(); - } - - FactoryURLClassLoader(String name, URL[] urls, ClassLoader parent, - @SuppressWarnings("removal") AccessControlContext acc) { - super(name, urls, parent, acc); - } - - FactoryURLClassLoader(URL[] urls, @SuppressWarnings("removal") AccessControlContext acc) { - super(urls, acc); - } - - public final Class loadClass(String name, boolean resolve) - throws ClassNotFoundException - { - // First check if we have permission to access the package. This - // should go away once we've added support for exported packages. - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - int i = name.lastIndexOf('.'); - if (i != -1) { - sm.checkPackageAccess(name.substring(0, i)); - } - } - return super.loadClass(name, resolve); - } -} diff --git a/src/java.base/share/classes/java/net/URLConnection.java b/src/java.base/share/classes/java/net/URLConnection.java index 168e4df29df..209b84de200 100644 --- a/src/java.base/share/classes/java/net/URLConnection.java +++ b/src/java.base/share/classes/java/net/URLConnection.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.PrivilegedAction; import java.util.Hashtable; import java.util.concurrent.ConcurrentHashMap; import java.util.Date; @@ -42,10 +41,8 @@ import java.util.Map; import java.util.List; import java.security.Permission; -import java.security.AccessController; import sun.security.util.SecurityConstants; import sun.net.www.MessageHeader; -import sun.security.action.GetPropertyAction; /** * The abstract class {@code URLConnection} is the superclass @@ -328,9 +325,6 @@ public String getContentTypeFor(String fileName) { * @since 1.2 */ public static void setFileNameMap(FileNameMap map) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) sm.checkSetFactory(); fileNameMap = map; } @@ -1285,11 +1279,6 @@ public static synchronized void setContentHandlerFactory(ContentHandlerFactory f if (factory != null) { throw new Error("factory already defined"); } - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkSetFactory(); - } factory = fac; } @@ -1401,35 +1390,22 @@ private ContentHandler lookupContentHandlerClassFor(String contentType) { @SuppressWarnings("removal") private ContentHandler lookupContentHandlerViaProvider(String contentType) { - return AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public ContentHandler run() { - ClassLoader cl = ClassLoader.getSystemClassLoader(); - ServiceLoader sl = - ServiceLoader.load(ContentHandlerFactory.class, cl); - - Iterator iterator = sl.iterator(); - - ContentHandler handler = null; - while (iterator.hasNext()) { - ContentHandlerFactory f; - try { - f = iterator.next(); - } catch (ServiceConfigurationError e) { - if (e.getCause() instanceof SecurityException) { - continue; - } - throw e; - } - handler = f.createContentHandler(contentType); - if (handler != null) { - break; - } - } - return handler; - } - }); + + ClassLoader cl = ClassLoader.getSystemClassLoader(); + ServiceLoader sl = + ServiceLoader.load(ContentHandlerFactory.class, cl); + + Iterator iterator = sl.iterator(); + + ContentHandler handler = null; + while (iterator.hasNext()) { + ContentHandlerFactory f = iterator.next(); + handler = f.createContentHandler(contentType); + if (handler != null) { + break; + } + } + return handler; } /** @@ -1465,8 +1441,7 @@ private String typeToPackageName(String contentType) { * is always the last one on the returned package list. */ private String getContentHandlerPkgPrefixes() { - String packagePrefixList = - GetPropertyAction.privilegedGetProperty(contentPathProp, ""); + String packagePrefixList = System.getProperty(contentPathProp, ""); if (packagePrefixList != "") { packagePrefixList += "|"; diff --git a/src/java.base/share/classes/java/net/spi/URLStreamHandlerProvider.java b/src/java.base/share/classes/java/net/spi/URLStreamHandlerProvider.java index 202f3e654fa..05733f7287d 100644 --- a/src/java.base/share/classes/java/net/spi/URLStreamHandlerProvider.java +++ b/src/java.base/share/classes/java/net/spi/URLStreamHandlerProvider.java @@ -49,19 +49,9 @@ public abstract class URLStreamHandlerProvider implements URLStreamHandlerFactory { - private static Void checkPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(new RuntimePermission("setFactory")); - return null; - } - private URLStreamHandlerProvider(Void ignore) { } - /** * Initializes a new URL stream handler provider. */ protected URLStreamHandlerProvider() { - this(checkPermission()); } } diff --git a/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java b/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java index e35e0ee687f..1d9e32c31d3 100644 --- a/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java +++ b/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java @@ -31,8 +31,6 @@ import java.util.ServiceLoader; import java.util.ServiceConfigurationError; import java.util.concurrent.*; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * Service-provider class for asynchronous channels. @@ -62,20 +60,15 @@ protected AsynchronousChannelProvider() { private static class ProviderHolder { static final AsynchronousChannelProvider provider = load(); - @SuppressWarnings("removal") private static AsynchronousChannelProvider load() { - return AccessController - .doPrivileged(new PrivilegedAction<>() { - public AsynchronousChannelProvider run() { - AsynchronousChannelProvider p; - p = loadProviderFromProperty(); - if (p != null) - return p; - p = loadProviderAsService(); - if (p != null) - return p; - return sun.nio.ch.DefaultAsynchronousChannelProvider.create(); - }}); + AsynchronousChannelProvider p; + p = loadProviderFromProperty(); + if (p != null) + return p; + p = loadProviderAsService(); + if (p != null) + return p; + return sun.nio.ch.DefaultAsynchronousChannelProvider.create(); } private static AsynchronousChannelProvider loadProviderFromProperty() { @@ -87,7 +80,7 @@ private static AsynchronousChannelProvider loadProviderFromProperty() { Object tmp = Class.forName(cn, true, ClassLoader.getSystemClassLoader()).newInstance(); return (AsynchronousChannelProvider)tmp; - } catch (ClassNotFoundException | SecurityException | + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException x) { throw new ServiceConfigurationError(null, x); } @@ -98,17 +91,7 @@ private static AsynchronousChannelProvider loadProviderAsService() { ServiceLoader.load(AsynchronousChannelProvider.class, ClassLoader.getSystemClassLoader()); Iterator i = sl.iterator(); - for (;;) { - try { - return (i.hasNext()) ? i.next() : null; - } catch (ServiceConfigurationError sce) { - if (sce.getCause() instanceof SecurityException) { - // Ignore the security exception, try the next provider - continue; - } - throw sce; - } - } + return sl.findFirst().orElse(null); } } diff --git a/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java b/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java index bfb23d048f6..f07f45620d8 100644 --- a/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java +++ b/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java @@ -33,8 +33,6 @@ import java.nio.channels.Pipe; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Iterator; import java.util.Objects; import java.util.ServiceLoader; @@ -81,17 +79,13 @@ protected SelectorProvider() { private static class Holder { static final SelectorProvider INSTANCE = provider(); - @SuppressWarnings("removal") static SelectorProvider provider() { - PrivilegedAction pa = () -> { - SelectorProvider sp; - if ((sp = loadProviderFromProperty()) != null) - return sp; - if ((sp = loadProviderAsService()) != null) - return sp; - return sun.nio.ch.DefaultSelectorProvider.get(); - }; - return AccessController.doPrivileged(pa); + SelectorProvider sp; + if ((sp = loadProviderFromProperty()) != null) + return sp; + if ((sp = loadProviderAsService()) != null) + return sp; + return sun.nio.ch.DefaultSelectorProvider.get(); } private static SelectorProvider loadProviderFromProperty() { @@ -105,8 +99,7 @@ private static SelectorProvider loadProviderFromProperty() { NoSuchMethodException | IllegalAccessException | InvocationTargetException | - InstantiationException | - SecurityException x) { + InstantiationException x) { throw new ServiceConfigurationError(null, x); } } @@ -116,17 +109,7 @@ private static SelectorProvider loadProviderAsService() { ServiceLoader.load(SelectorProvider.class, ClassLoader.getSystemClassLoader()); Iterator i = sl.iterator(); - for (;;) { - try { - return i.hasNext() ? i.next() : null; - } catch (ServiceConfigurationError sce) { - if (sce.getCause() instanceof SecurityException) { - // Ignore the security exception, try the next provider - continue; - } - throw sce; - } - } + return sl.findFirst().orElse(null); } } diff --git a/src/java.base/share/classes/java/nio/charset/Charset.java b/src/java.base/share/classes/java/nio/charset/Charset.java index 35c7e5b1cd5..4766c907d55 100644 --- a/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/src/java.base/share/classes/java/nio/charset/Charset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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,12 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.spi.CharsetProvider; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; -import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.Set; import java.util.SortedMap; @@ -346,9 +343,7 @@ private static void cache(String charsetName, Charset cs) { cache1 = new Object[] { charsetName, cs }; } - // Creates an iterator that walks over the available providers, ignoring - // those whose lookup or instantiation causes a security exception to be - // thrown. Should be invoked with full privileges. + // Creates an iterator that walks over the available providers // private static Iterator providers() { return new Iterator<>() { @@ -360,17 +355,9 @@ private static Iterator providers() { private boolean getNext() { while (next == null) { - try { - if (!i.hasNext()) - return false; - next = i.next(); - } catch (ServiceConfigurationError sce) { - if (sce.getCause() instanceof SecurityException) { - // Ignore security exceptions - continue; - } - throw sce; - } + if (!i.hasNext()) + return false; + next = i.next(); } return true; } @@ -406,7 +393,6 @@ private static void endLookup(Object key) { ThreadTrackHolder.TRACKER.end(key); } - @SuppressWarnings("removal") private static Charset lookupViaProviders(final String charsetName) { // The runtime startup sequence looks up standard charsets as a @@ -426,20 +412,13 @@ private static Charset lookupViaProviders(final String charsetName) { return null; } try { - return AccessController.doPrivileged( - new PrivilegedAction<>() { - public Charset run() { - for (Iterator i = providers(); - i.hasNext();) { - CharsetProvider cp = i.next(); - Charset cs = cp.charsetForName(charsetName); - if (cs != null) - return cs; - } - return null; - } - }); - + for (Iterator i = providers(); i.hasNext();) { + CharsetProvider cp = i.next(); + Charset cs = cp.charsetForName(charsetName); + if (cs != null) + return cs; + } + return null; } finally { endLookup(key); } @@ -449,22 +428,18 @@ public Charset run() { private static class ExtendedProviderHolder { static final CharsetProvider[] extendedProviders = extendedProviders(); // returns ExtendedProvider, if installed - @SuppressWarnings("removal") private static CharsetProvider[] extendedProviders() { - return AccessController.doPrivileged(new PrivilegedAction<>() { - public CharsetProvider[] run() { - CharsetProvider[] cps = new CharsetProvider[1]; - int n = 0; - ServiceLoader sl = - ServiceLoader.loadInstalled(CharsetProvider.class); - for (CharsetProvider cp : sl) { - if (n + 1 > cps.length) { - cps = Arrays.copyOf(cps, cps.length << 1); - } - cps[n++] = cp; - } - return n == cps.length ? cps : Arrays.copyOf(cps, n); - }}); + CharsetProvider[] cps = new CharsetProvider[1]; + int n = 0; + ServiceLoader sl = + ServiceLoader.loadInstalled(CharsetProvider.class); + for (CharsetProvider cp : sl) { + if (n + 1 > cps.length) { + cps = Arrays.copyOf(cps, cps.length << 1); + } + cps[n++] = cp; + } + return n == cps.length ? cps : Arrays.copyOf(cps, n); } } @@ -628,26 +603,20 @@ private static void put(Iterator i, Map m) { * @return An immutable, case-insensitive map from canonical charset names * to charset objects */ - @SuppressWarnings("removal") public static SortedMap availableCharsets() { - return AccessController.doPrivileged( - new PrivilegedAction<>() { - public SortedMap run() { - TreeMap m = - new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - put(standardProvider.charsets(), m); - CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders; - for (CharsetProvider ecp :ecps) { - put(ecp.charsets(), m); - } - for (Iterator i = providers(); i.hasNext();) { - CharsetProvider cp = i.next(); - put(cp.charsets(), m); - } - return Collections.unmodifiableSortedMap(m); - } - }); + TreeMap m = + new TreeMap<>( + String.CASE_INSENSITIVE_ORDER); + put(standardProvider.charsets(), m); + CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders; + for (CharsetProvider ecp :ecps) { + put(ecp.charsets(), m); + } + for (Iterator i = providers(); i.hasNext();) { + CharsetProvider cp = i.next(); + put(cp.charsets(), m); + } + return Collections.unmodifiableSortedMap(m); } private @Stable static Charset defaultCharset; diff --git a/src/java.base/share/classes/java/nio/file/CopyMoveHelper.java b/src/java.base/share/classes/java/nio/file/CopyMoveHelper.java index 24a89456661..357e200e930 100644 --- a/src/java.base/share/classes/java/nio/file/CopyMoveHelper.java +++ b/src/java.base/share/classes/java/nio/file/CopyMoveHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -116,13 +116,9 @@ static void copyToForeignTarget(Path source, Path target, // attributes of source file BasicFileAttributes sourceAttrs = null; if (sourcePosixView != null) { - try { - sourceAttrs = Files.readAttributes(source, - PosixFileAttributes.class, - linkOptions); - } catch (SecurityException ignored) { - // okay to continue if RuntimePermission("accessUserInformation") not granted - } + sourceAttrs = Files.readAttributes(source, + PosixFileAttributes.class, + linkOptions); } if (sourceAttrs == null) sourceAttrs = Files.readAttributes(source, @@ -173,11 +169,7 @@ else if (Files.exists(target)) if (sourceAttrs instanceof PosixFileAttributes sourcePosixAttrs && targetView instanceof PosixFileAttributeView targetPosixView) { - try { - targetPosixView.setPermissions(sourcePosixAttrs.permissions()); - } catch (SecurityException ignored) { - // okay to continue if RuntimePermission("accessUserInformation") not granted - } + targetPosixView.setPermissions(sourcePosixAttrs.permissions()); } } catch (Throwable x) { // rollback diff --git a/src/java.base/share/classes/java/nio/file/FileSystems.java b/src/java.base/share/classes/java/nio/file/FileSystems.java index ddf1033c7ee..ab0538a1d41 100644 --- a/src/java.base/share/classes/java/nio/file/FileSystems.java +++ b/src/java.base/share/classes/java/nio/file/FileSystems.java @@ -25,12 +25,10 @@ package java.nio.file; -import java.nio.file.spi.FileSystemProvider; -import java.net.URI; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.lang.reflect.Constructor; +import java.net.URI; +import java.nio.file.spi.FileSystemProvider; import java.util.Collections; import java.util.Map; import java.util.ServiceConfigurationError; @@ -96,13 +94,7 @@ private static class DefaultFileSystemHolder { // returns default file system private static FileSystem defaultFileSystem() { // load default provider - @SuppressWarnings("removal") - FileSystemProvider provider = AccessController - .doPrivileged(new PrivilegedAction<>() { - public FileSystemProvider run() { - return getDefaultProvider(); - } - }); + FileSystemProvider provider = getDefaultProvider(); // return file system return provider.getFileSystem(URI.create("file:///")); diff --git a/src/java.base/share/classes/java/nio/file/FileTreeIterator.java b/src/java.base/share/classes/java/nio/file/FileTreeIterator.java index 2901d1d9884..0f8c646dc5e 100644 --- a/src/java.base/share/classes/java/nio/file/FileTreeIterator.java +++ b/src/java.base/share/classes/java/nio/file/FileTreeIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2023, 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 @@ -58,8 +58,6 @@ class FileTreeIterator implements Iterator, Closeable { * if {@code maxDepth} is negative * @throws IOException * if an I/O errors occurs opening the starting file - * @throws SecurityException - * if the security manager denies access to the starting file * @throws NullPointerException * if {@code start} or {@code options} is {@code null} or * the options array contains a {@code null} element diff --git a/src/java.base/share/classes/java/nio/file/FileTreeWalker.java b/src/java.base/share/classes/java/nio/file/FileTreeWalker.java index 02f5c7de773..e5f01ea87d7 100644 --- a/src/java.base/share/classes/java/nio/file/FileTreeWalker.java +++ b/src/java.base/share/classes/java/nio/file/FileTreeWalker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -198,16 +198,12 @@ IOException ioeException() { * the walk is following sym links is not. The {@code canUseCached} * argument determines whether this method can use cached attributes. */ - @SuppressWarnings("removal") private BasicFileAttributes getAttributes(Path file, boolean canUseCached) throws IOException { // if attributes are cached then use them if possible - if (canUseCached && - (file instanceof BasicFileAttributesHolder) && - (System.getSecurityManager() == null)) - { - BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get(); + if (canUseCached && (file instanceof BasicFileAttributesHolder bfah)) { + BasicFileAttributes cached = bfah.get(); if (cached != null && (!followLinks || !cached.isSymbolicLink())) { return cached; } @@ -250,7 +246,7 @@ private boolean wouldLoop(Path dir, Object key) { // cycle detected return true; } - } catch (IOException | SecurityException x) { + } catch (IOException e) { // ignore } } @@ -262,25 +258,16 @@ private boolean wouldLoop(Path dir, Object key) { * Visits the given file, returning the {@code Event} corresponding to that * visit. * - * The {@code ignoreSecurityException} parameter determines whether - * any SecurityException should be ignored or not. If a SecurityException - * is thrown, and is ignored, then this method returns {@code null} to - * mean that there is no event corresponding to a visit to the file. - * * The {@code canUseCached} parameter determines whether cached attributes * for the file can be used or not. */ - private Event visit(Path entry, boolean ignoreSecurityException, boolean canUseCached) { + private Event visit(Path entry, boolean canUseCached) { // need the file attributes BasicFileAttributes attrs; try { attrs = getAttributes(entry, canUseCached); } catch (IOException ioe) { return new Event(EventType.ENTRY, entry, ioe); - } catch (SecurityException se) { - if (ignoreSecurityException) - return null; - throw se; } // at maximum depth or file is not a directory @@ -301,10 +288,6 @@ private Event visit(Path entry, boolean ignoreSecurityException, boolean canUseC stream = Files.newDirectoryStream(entry); } catch (IOException ioe) { return new Event(EventType.ENTRY, entry, ioe); - } catch (SecurityException se) { - if (ignoreSecurityException) - return null; - throw se; } // push a directory node to the stack and return an event @@ -321,7 +304,6 @@ Event walk(Path file) { throw new IllegalStateException("Closed"); Event ev = visit(file, - false, // ignoreSecurityException false); // canUseCached assert ev != null; return ev; @@ -372,7 +354,6 @@ Event next() { // visit the entry ev = visit(entry, - true, // ignoreSecurityException true); // canUseCached } while (ev == null); diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 9599193d5d7..5dd8d219ba9 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -58,8 +58,6 @@ import java.nio.file.attribute.UserPrincipal; import java.nio.file.spi.FileSystemProvider; import java.nio.file.spi.FileTypeDetector; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -696,14 +694,8 @@ public static Path createDirectories(Path dir, FileAttribute... attrs) } catch (IOException x) { // parent may not exist or other reason } - SecurityException se = null; - Path absDir = dir; - try { - absDir = dir.toAbsolutePath(); - } catch (SecurityException x) { - // don't have permission to get absolute path - se = x; - } + Path absDir = dir.toAbsolutePath(); + // find a descendant that exists Path parent = absDir.getParent(); while (parent != null) { @@ -717,12 +709,8 @@ public static Path createDirectories(Path dir, FileAttribute... attrs) } if (parent == null) { // unable to find existing parent - if (se == null) { - throw new FileSystemException(absDir.toString(), null, - "Unable to determine if root directory exists"); - } else { - throw se; - } + throw new FileSystemException(absDir.toString(), null, + "Unable to determine if root directory exists"); } // create directories @@ -1525,29 +1513,19 @@ private static class FileTypeDetectors{ loadInstalledDetectors(); // creates the default file type detector - @SuppressWarnings("removal") private static FileTypeDetector createDefaultFileTypeDetector() { - return AccessController - .doPrivileged(new PrivilegedAction<>() { - @Override public FileTypeDetector run() { - return sun.nio.fs.DefaultFileTypeDetector.create(); - }}); + return sun.nio.fs.DefaultFileTypeDetector.create(); } // loads all installed file type detectors - @SuppressWarnings("removal") private static List loadInstalledDetectors() { - return AccessController - .doPrivileged(new PrivilegedAction<>() { - @Override public List run() { - List list = new ArrayList<>(); - ServiceLoader loader = ServiceLoader - .load(FileTypeDetector.class, ClassLoader.getSystemClassLoader()); - for (FileTypeDetector detector: loader) { - list.add(detector); - } - return list; - }}); + List list = new ArrayList<>(); + ServiceLoader loader = ServiceLoader + .load(FileTypeDetector.class, ClassLoader.getSystemClassLoader()); + for (FileTypeDetector detector: loader) { + list.add(detector); + } + return list; } } @@ -2863,26 +2841,16 @@ public static long copy(InputStream in, Path target, CopyOption... options) } // attempt to delete an existing file - SecurityException se = null; if (replaceExisting) { - try { - deleteIfExists(target); - } catch (SecurityException x) { - se = x; - } + deleteIfExists(target); } - // attempt to create target file. If it fails with - // FileAlreadyExistsException then it may be because the security - // manager prevented us from deleting the file, in which case we just - // throw the SecurityException. + // attempt to create target file. OutputStream ostream; try { ostream = newOutputStream(target, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE); } catch (FileAlreadyExistsException x) { - if (se != null) - throw se; // someone else won the race and created the file throw x; } diff --git a/src/java.base/share/classes/java/nio/file/TempFileHelper.java b/src/java.base/share/classes/java/nio/file/TempFileHelper.java index 0d7a8cab849..e5ba85fcf36 100644 --- a/src/java.base/share/classes/java/nio/file/TempFileHelper.java +++ b/src/java.base/share/classes/java/nio/file/TempFileHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -117,16 +117,12 @@ private static Path create(Path dir, } // loop generating random names until file or directory can be created - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); for (;;) { Path f; try { f = generatePath(prefix, suffix, dir); } catch (InvalidPathException e) { // don't reveal temporary directory location - if (sm != null) - throw new IllegalArgumentException("Invalid prefix or suffix"); throw e; } try { @@ -135,11 +131,6 @@ private static Path create(Path dir, } else { return Files.createFile(f, attrs); } - } catch (SecurityException e) { - // don't reveal temporary directory location - if (dir == tmpdir && sm != null) - throw new SecurityException("Unable to create temporary file or directory"); - throw e; } catch (FileAlreadyExistsException e) { // ignore } diff --git a/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java b/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java index 0f91e9b5f89..14e5ce90c2c 100644 --- a/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java +++ b/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java @@ -45,7 +45,6 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.LinkOption; -import java.nio.file.LinkPermission; import java.nio.file.NoSuchFileException; import java.nio.file.NotDirectoryException; import java.nio.file.NotLinkException; @@ -68,8 +67,6 @@ import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.ExecutorService; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.nio.ch.FileChannelImpl; @@ -185,13 +182,7 @@ public static List installedProviders() { } loadingProviders = true; - @SuppressWarnings("removal") - List list = AccessController - .doPrivileged(new PrivilegedAction<>() { - @Override - public List run() { - return loadInstalledProviders(); - }}); + List list = loadInstalledProviders(); // insert the default provider at the start of the list list.add(0, defaultProvider); diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java index 589c027b2dc..03fdf7a3c99 100644 --- a/src/java.base/share/classes/java/util/Arrays.java +++ b/src/java.base/share/classes/java/util/Arrays.java @@ -985,11 +985,8 @@ public static void parallelSort(T[] a, int fromIndex, int toIndex, * circular dependencies. To be removed in a future release. */ static final class LegacyMergeSort { - @SuppressWarnings("removal") private static final boolean userRequested = - java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "java.util.Arrays.useLegacyMergeSort")).booleanValue(); + Boolean.getBoolean("java.util.Arrays.useLegacyMergeSort"); } /** diff --git a/src/java.base/share/classes/java/util/Calendar.java b/src/java.base/share/classes/java/util/Calendar.java index 7ac98c02297..7cf389df42b 100644 --- a/src/java.base/share/classes/java/util/Calendar.java +++ b/src/java.base/share/classes/java/util/Calendar.java @@ -43,12 +43,6 @@ import java.io.ObjectOutputStream; import java.io.OptionalDataException; import java.io.Serializable; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PermissionCollection; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.ProtectionDomain; import java.text.DateFormat; import java.text.DateFormatSymbols; import java.time.Instant; @@ -3564,25 +3558,9 @@ private synchronized void writeObject(ObjectOutputStream stream) } } - @SuppressWarnings("removal") - private static class CalendarAccessControlContext { - private static final AccessControlContext INSTANCE; - static { - RuntimePermission perm = new RuntimePermission("accessClassInPackage.sun.util.calendar"); - PermissionCollection perms = perm.newPermissionCollection(); - perms.add(perm); - INSTANCE = new AccessControlContext(new ProtectionDomain[] { - new ProtectionDomain(null, perms) - }); - } - private CalendarAccessControlContext() { - } - } - /** * Reconstitutes this object from a stream (i.e., deserialize it). */ - @SuppressWarnings("removal") @java.io.Serial private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException @@ -3617,16 +3595,8 @@ else if (serialVersionOnStream >= 0) // If there's a ZoneInfo object, use it for zone. ZoneInfo zi = null; try { - zi = AccessController.doPrivileged( - new PrivilegedExceptionAction<>() { - @Override - public ZoneInfo run() throws Exception { - return (ZoneInfo) input.readObject(); - } - }, - CalendarAccessControlContext.INSTANCE); - } catch (PrivilegedActionException pae) { - Exception e = pae.getException(); + zi = (ZoneInfo) input.readObject(); + } catch (Exception e) { if (!(e instanceof OptionalDataException)) { if (e instanceof RuntimeException) { throw (RuntimeException) e; diff --git a/src/java.base/share/classes/java/util/Currency.java b/src/java.base/share/classes/java/util/Currency.java index 0bc86f3281e..789eefad5d5 100644 --- a/src/java.base/share/classes/java/util/Currency.java +++ b/src/java.base/share/classes/java/util/Currency.java @@ -32,8 +32,6 @@ import java.io.InputStream; import java.io.IOException; import java.io.Serializable; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.concurrent.ConcurrentHashMap; @@ -213,63 +211,57 @@ public final class Currency implements Serializable { initStatic(); } - @SuppressWarnings("removal") private static void initStatic() { - AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Void run() { - try { - try (InputStream in = getClass().getResourceAsStream("/java/util/currency.data")) { - if (in == null) { - throw new InternalError("Currency data not found"); - } - DataInputStream dis = new DataInputStream(new BufferedInputStream(in)); - if (dis.readInt() != MAGIC_NUMBER) { - throw new InternalError("Currency data is possibly corrupted"); - } - formatVersion = dis.readInt(); - if (formatVersion != VALID_FORMAT_VERSION) { - throw new InternalError("Currency data format is incorrect"); - } - dataVersion = dis.readInt(); - mainTable = readIntArray(dis, A_TO_Z * A_TO_Z); - int scCount = dis.readInt(); - specialCasesList = readSpecialCases(dis, scCount); - int ocCount = dis.readInt(); - otherCurrenciesList = readOtherCurrencies(dis, ocCount); - } - } catch (IOException e) { - throw new InternalError(e); - } - // look for the properties file for overrides - String propsFile = System.getProperty("java.util.currency.data"); - if (propsFile == null) { - propsFile = StaticProperty.javaHome() + File.separator + "lib" + - File.separator + "currency.properties"; + try { + try (InputStream in = Currency.class.getResourceAsStream("/java/util/currency.data")) { + if (in == null) { + throw new InternalError("Currency data not found"); } - try { - File propFile = new File(propsFile); - if (propFile.exists()) { - Properties props = new Properties(); - try (FileReader fr = new FileReader(propFile)) { - props.load(fr); - } - Pattern propertiesPattern = - Pattern.compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*" + - "(\\d+)\\s*,?\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:" + - "\\d{2}:\\d{2})?"); - List currencyEntries - = getValidCurrencyData(props, propertiesPattern); - currencyEntries.forEach(Currency::replaceCurrencyData); - } - } catch (IOException e) { - CurrencyProperty.info("currency.properties is ignored" - + " because of an IOException", e); + DataInputStream dis = new DataInputStream(new BufferedInputStream(in)); + if (dis.readInt() != MAGIC_NUMBER) { + throw new InternalError("Currency data is possibly corrupted"); } - return null; + formatVersion = dis.readInt(); + if (formatVersion != VALID_FORMAT_VERSION) { + throw new InternalError("Currency data format is incorrect"); + } + dataVersion = dis.readInt(); + mainTable = readIntArray(dis, A_TO_Z * A_TO_Z); + int scCount = dis.readInt(); + specialCasesList = readSpecialCases(dis, scCount); + int ocCount = dis.readInt(); + otherCurrenciesList = readOtherCurrencies(dis, ocCount); } - }); + } catch (IOException e) { + throw new InternalError(e); + } + + // look for the properties file for overrides + String propsFile = System.getProperty("java.util.currency.data"); + if (propsFile == null) { + propsFile = StaticProperty.javaHome() + File.separator + "lib" + + File.separator + "currency.properties"; + } + try { + File propFile = new File(propsFile); + if (propFile.exists()) { + Properties props = new Properties(); + try (FileReader fr = new FileReader(propFile)) { + props.load(fr); + } + Pattern propertiesPattern = + Pattern.compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*" + + "(\\d+)\\s*,?\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:" + + "\\d{2}:\\d{2})?"); + List currencyEntries + = getValidCurrencyData(props, propertiesPattern); + currencyEntries.forEach(Currency::replaceCurrencyData); + } + } catch (IOException e) { + CurrencyProperty.info("currency.properties is ignored" + + " because of an IOException", e); + } } /** @@ -494,10 +486,7 @@ public static Set getAvailableCurrencies() { } } } - - @SuppressWarnings("unchecked") - Set result = (Set) available.clone(); - return result; + return new HashSet<>(available); } /** diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index 600b20de639..c055c160367 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -1216,10 +1216,6 @@ public static synchronized void setDefault(Locale.Category category, if (newLocale == null) throw new NullPointerException("Can't set default locale to NULL"); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) sm.checkPermission(new PropertyPermission - ("user.language", "write")); switch (category) { case DISPLAY: defaultDisplayLocale = newLocale; diff --git a/src/java.base/share/classes/java/util/Properties.java b/src/java.base/share/classes/java/util/Properties.java index 45ca0363660..015cdbc7107 100644 --- a/src/java.base/share/classes/java/util/Properties.java +++ b/src/java.base/share/classes/java/util/Properties.java @@ -949,9 +949,6 @@ private void store0(BufferedWriter bw, String comments, boolean escUnicode) } private static void writeDateComment(BufferedWriter bw) throws IOException { - // value of java.properties.date system property isn't sensitive - // and so doesn't need any security manager checks to make the value accessible - // to the callers String sysPropVal = StaticProperty.javaPropertiesDate(); if (sysPropVal != null && !sysPropVal.isEmpty()) { writeComments(bw, sysPropVal); diff --git a/src/java.base/share/classes/java/util/PropertyResourceBundle.java b/src/java.base/share/classes/java/util/PropertyResourceBundle.java index 02391fa2de2..aba65cbcd88 100644 --- a/src/java.base/share/classes/java/util/PropertyResourceBundle.java +++ b/src/java.base/share/classes/java/util/PropertyResourceBundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -46,7 +46,6 @@ import java.nio.charset.MalformedInputException; import java.nio.charset.UnmappableCharacterException; import sun.nio.cs.ISO_8859_1; -import sun.security.action.GetPropertyAction; import sun.util.PropertyResourceBundleCharset; import sun.util.ResourceBundleEnumeration; @@ -132,9 +131,9 @@ public class PropertyResourceBundle extends ResourceBundle { // Check whether the strict encoding is specified. // The possible encoding is either "ISO-8859-1" or "UTF-8". - private static final String encoding = GetPropertyAction - .privilegedGetProperty("java.util.PropertyResourceBundle.encoding", "") - .toUpperCase(Locale.ROOT); + private static final String encoding = + System.getProperty("java.util.PropertyResourceBundle.encoding", "") + .toUpperCase(Locale.ROOT); /** * Creates a property resource bundle from an {@link java.io.InputStream diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java index 83f58b8506f..989cc09f388 100644 --- a/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/src/java.base/share/classes/java/util/ResourceBundle.java @@ -42,7 +42,6 @@ import java.io.IOException; import java.io.InputStream; -import java.io.UncheckedIOException; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; @@ -53,10 +52,6 @@ import java.net.JarURLConnection; import java.net.URL; import java.net.URLConnection; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.jar.JarEntry; @@ -70,12 +65,9 @@ import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.util.ReferencedKeyMap; -import sun.security.action.GetPropertyAction; import sun.util.locale.BaseLocale; import sun.util.resources.Bundles; -import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; - /** * @@ -581,10 +573,8 @@ public Locale getLocale() { return locale; } - @SuppressWarnings("removal") private static ClassLoader getLoader(Module module) { - PrivilegedAction pa = module::getClassLoader; - return AccessController.doPrivileged(pa); + return module.getClassLoader(); } /** @@ -1506,15 +1496,12 @@ private static Control getDefaultControl(Module targetModule, String baseName) { } private static class ResourceBundleControlProviderHolder { - private static final PrivilegedAction> pa = - () -> ServiceLoader.load(ResourceBundleControlProvider.class, - ClassLoader.getSystemClassLoader()).stream() - .map(ServiceLoader.Provider::get) - .toList(); - @SuppressWarnings("removal") private static final List CONTROL_PROVIDERS = - AccessController.doPrivileged(pa); + ServiceLoader.load(ResourceBundleControlProvider.class, + ClassLoader.getSystemClassLoader()).stream() + .map(ServiceLoader.Provider::get) + .toList(); private static Control getControl(String baseName) { return CONTROL_PROVIDERS.isEmpty() ? @@ -1594,13 +1581,6 @@ private static ResourceBundle getBundleFromModule(Class caller, Control control) { Objects.requireNonNull(module); Module callerModule = getCallerModule(caller); - if (callerModule != module) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(GET_CLASSLOADER_PERMISSION); - } - } return getBundleImpl(callerModule, module, baseName, locale, control); } @@ -1885,7 +1865,6 @@ private static ServiceLoader getServiceLoader(Module mod * Returns the service type of the given baseName that is visible * to the given class loader */ - @SuppressWarnings("removal") private static Class getResourceBundleProviderType(String baseName, ClassLoader loader) { @@ -1900,27 +1879,20 @@ private static ServiceLoader getServiceLoader(Module mod // Use the class loader of the getBundle caller so that the caller's // visibility of the provider type is checked. - return AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public Class run() { - try { - Class c = Class.forName(providerName, false, loader); - if (ResourceBundleProvider.class.isAssignableFrom(c)) { - @SuppressWarnings("unchecked") - Class s = (Class) c; - return s; - } - } catch (ClassNotFoundException e) {} - return null; - } - }); + try { + Class c = Class.forName(providerName, false, loader); + if (ResourceBundleProvider.class.isAssignableFrom(c)) { + @SuppressWarnings("unchecked") + Class s = (Class) c; + return s; + } + } catch (ClassNotFoundException _) {} + return null; } /** * Loads ResourceBundle from service providers. */ - @SuppressWarnings("removal") private static ResourceBundle loadBundleFromProviders(String baseName, Locale locale, ServiceLoader providers, @@ -1928,34 +1900,28 @@ private static ResourceBundle loadBundleFromProviders(String baseName, { if (providers == null) return null; - return AccessController.doPrivileged( - new PrivilegedAction<>() { - public ResourceBundle run() { - for (Iterator itr = providers.iterator(); itr.hasNext(); ) { - try { - ResourceBundleProvider provider = itr.next(); - if (cacheKey != null && cacheKey.callerHasProvider == null - && cacheKey.getModule() == provider.getClass().getModule()) { - cacheKey.callerHasProvider = Boolean.TRUE; - } - ResourceBundle bundle = provider.getBundle(baseName, locale); - trace("provider %s %s locale: %s bundle: %s%n", provider, baseName, locale, bundle); - if (bundle != null) { - return bundle; - } - } catch (ServiceConfigurationError | SecurityException e) { - if (cacheKey != null) { - cacheKey.setCause(e); - } - } - } - if (cacheKey != null && cacheKey.callerHasProvider == null) { - cacheKey.callerHasProvider = Boolean.FALSE; - } - return null; - } - }); - + for (Iterator itr = providers.iterator(); itr.hasNext(); ) { + try { + ResourceBundleProvider provider = itr.next(); + if (cacheKey != null && cacheKey.callerHasProvider == null + && cacheKey.getModule() == provider.getClass().getModule()) { + cacheKey.callerHasProvider = Boolean.TRUE; + } + ResourceBundle bundle = provider.getBundle(baseName, locale); + trace("provider %s %s locale: %s bundle: %s%n", provider, baseName, locale, bundle); + if (bundle != null) { + return bundle; + } + } catch (ServiceConfigurationError e) { + if (cacheKey != null) { + cacheKey.setCause(e); + } + } + } + if (cacheKey != null && cacheKey.callerHasProvider == null) { + cacheKey.callerHasProvider = Boolean.FALSE; + } + return null; } /* @@ -3153,7 +3119,6 @@ public ResourceBundle newBundle(String baseName, Locale locale, String format, return bundle; } - @SuppressWarnings("removal") private ResourceBundle newBundle0(String bundleName, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException { @@ -3177,28 +3142,20 @@ private ResourceBundle newBundle0(String bundleName, String format, bundleClass.getName() + " in " + m.toString()); } try { - Constructor ctor = AccessController.doPrivileged( - new PrivilegedExceptionAction<>() { - @Override - public Constructor run() throws NoSuchMethodException { - return bundleClass.getDeclaredConstructor(); - } - }); + Constructor ctor = bundleClass.getDeclaredConstructor(); if (!Modifier.isPublic(ctor.getModifiers())) { throw new IllegalAccessException("no-arg constructor in " + bundleClass.getName() + " is not publicly accessible."); } // java.base may not be able to read the bundleClass's module. - PrivilegedAction pa1 = () -> { ctor.setAccessible(true); return null; }; - AccessController.doPrivileged(pa1); + ctor.setAccessible(true); bundle = ctor.newInstance((Object[]) null); } catch (InvocationTargetException e) { uncheckedThrow(e); - } catch (PrivilegedActionException e) { - assert e.getCause() instanceof NoSuchMethodException; + } catch (NoSuchMethodException e) { throw new InstantiationException("public no-arg constructor " + - "does not exist in " + bundleClass.getName()); + "does not exist in " + bundleClass.getName()); } } else { throw new ClassCastException(c.getName() @@ -3212,27 +3169,16 @@ public Constructor run() throws NoSuchMethodException { return bundle; } - final boolean reloadFlag = reload; - InputStream stream = null; - try { - stream = AccessController.doPrivileged( - new PrivilegedExceptionAction<>() { - public InputStream run() throws IOException { - URL url = loader.getResource(resourceName); - if (url == null) return null; - - URLConnection connection = url.openConnection(); - if (reloadFlag) { - // Disable caches to get fresh data for - // reloading. - connection.setUseCaches(false); - } - return connection.getInputStream(); - } - }); - } catch (PrivilegedActionException e) { - throw (IOException) e.getCause(); + URL url = loader.getResource(resourceName); + if (url == null) return null; + + URLConnection connection = url.openConnection(); + if (reload) { + // Disable caches to get fresh data for + // reloading. + connection.setUseCaches(false); } + InputStream stream = connection.getInputStream(); if (stream != null) { try { bundle = new PropertyResourceBundle(stream); @@ -3563,7 +3509,6 @@ private static class ResourceBundleProviderHelper { /** * Returns a new ResourceBundle instance of the given bundleClass */ - @SuppressWarnings("removal") static ResourceBundle newResourceBundle(Class bundleClass) { try { @SuppressWarnings("unchecked") @@ -3573,8 +3518,7 @@ static ResourceBundle newResourceBundle(Class bundleCl return null; } // java.base may not be able to read the bundleClass's module. - PrivilegedAction pa = () -> { ctor.setAccessible(true); return null;}; - AccessController.doPrivileged(pa); + ctor.setAccessible(true); try { return ctor.newInstance((Object[]) null); } catch (InvocationTargetException e) { @@ -3602,9 +3546,7 @@ static ResourceBundle loadResourceBundle(Module callerModule, { String bundleName = Control.INSTANCE.toBundleName(baseName, locale); try { - PrivilegedAction> pa = () -> Class.forName(module, bundleName); - @SuppressWarnings("removal") - Class c = AccessController.doPrivileged(pa, null, GET_CLASSLOADER_PERMISSION); + Class c = Class.forName(module, bundleName); trace("local in %s %s caller %s: %s%n", module, bundleName, callerModule, c); if (c == null) { @@ -3662,56 +3604,46 @@ static ResourceBundle loadPropertyResourceBundle(Module callerModule, { String bundleName = Control.INSTANCE.toBundleName(baseName, locale); - PrivilegedAction pa = () -> { - try { - String resourceName = Control.INSTANCE - .toResourceName0(bundleName, "properties"); - if (resourceName == null) { - return null; - } - trace("local in %s %s caller %s%n", module, resourceName, callerModule); - - // if the package is in the given module but not opened - // locate it from the given module first. - String pn = toPackageName(bundleName); - trace(" %s/%s is accessible to %s : %s%n", - module.getName(), pn, callerModule, - isAccessible(callerModule, module, pn)); - if (isAccessible(callerModule, module, pn)) { - InputStream in = module.getResourceAsStream(resourceName); - if (in != null) { - return in; - } - } - - ClassLoader loader = module.getClassLoader(); - trace("loader for %s %s caller %s%n", module, resourceName, callerModule); - - try { - if (loader != null) { - return loader.getResourceAsStream(resourceName); - } else { - URL url = BootLoader.findResource(resourceName); - if (url != null) { - return url.openStream(); - } - } - } catch (Exception e) {} - return null; - - } catch (IOException e) { - throw new UncheckedIOException(e); + String resourceName = Control.INSTANCE + .toResourceName0(bundleName, "properties"); + if (resourceName == null) { + return null; + } + trace("local in %s %s caller %s%n", module, resourceName, callerModule); + + + // if the package is in the given module but not opened + // locate it from the given module first. + String pn = toPackageName(bundleName); + trace(" %s/%s is accessible to %s : %s%n", + module.getName(), pn, callerModule, + isAccessible(callerModule, module, pn)); + if (isAccessible(callerModule, module, pn)) { + InputStream in = module.getResourceAsStream(resourceName); + if (in != null) { + return new PropertyResourceBundle(in); } - }; + } + ClassLoader loader = module.getClassLoader(); + trace("loader for %s %s caller %s%n", module, resourceName, callerModule); - try (@SuppressWarnings("removal") InputStream stream = AccessController.doPrivileged(pa)) { + try { + InputStream stream = null; + if (loader != null) { + stream = loader.getResourceAsStream(resourceName); + } else { + URL url = BootLoader.findResource(resourceName); + if (url != null) { + stream = url.openStream(); + } + } if (stream != null) { return new PropertyResourceBundle(stream); } else { return null; } - } catch (UncheckedIOException e) { - throw e.getCause(); + } catch (Exception e) { + return null; } } @@ -3722,8 +3654,8 @@ private static String toPackageName(String bundleName) { } - private static final boolean TRACE_ON = Boolean.parseBoolean( - GetPropertyAction.privilegedGetProperty("resource.bundle.debug", "false")); + private static final boolean TRACE_ON = Boolean.getBoolean( + System.getProperty("resource.bundle.debug", "false")); private static void trace(String format, Object... params) { if (TRACE_ON) diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java index 07ed1875190..c634d6321c0 100644 --- a/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/src/java.base/share/classes/java/util/ServiceLoader.java @@ -35,11 +35,6 @@ import java.lang.reflect.Modifier; import java.net.URL; import java.net.URLConnection; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Stream; @@ -396,10 +391,6 @@ public final class ServiceLoader // null when locating provider using a module layer private final ClassLoader loader; - // The access control context taken when the ServiceLoader is created - @SuppressWarnings("removal") - private final AccessControlContext acc; - // The lazy-lookup iterator for iterator operations private Iterator> lookupIterator1; private final List instantiatedProviders = new ArrayList<>(); @@ -462,7 +453,6 @@ public static interface Provider extends Supplier { * If {@code svc} is not accessible to {@code caller} or the caller * module does not use the service type. */ - @SuppressWarnings("removal") private ServiceLoader(Class caller, ModuleLayer layer, Class svc) { Objects.requireNonNull(caller); Objects.requireNonNull(layer); @@ -473,9 +463,6 @@ private ServiceLoader(Class caller, ModuleLayer layer, Class svc) { this.serviceName = svc.getName(); this.layer = layer; this.loader = null; - this.acc = (System.getSecurityManager() != null) - ? AccessController.getContext() - : null; } /** @@ -486,7 +473,6 @@ private ServiceLoader(Class caller, ModuleLayer layer, Class svc) { * If {@code svc} is not accessible to {@code caller} or the caller * module does not use the service type. */ - @SuppressWarnings("removal") private ServiceLoader(Class caller, Class svc, ClassLoader cl) { Objects.requireNonNull(svc); @@ -515,9 +501,6 @@ private ServiceLoader(Class caller, Class svc, ClassLoader cl) { this.serviceName = svc.getName(); this.layer = null; this.loader = cl; - this.acc = (System.getSecurityManager() != null) - ? AccessController.getContext() - : null; } /** @@ -529,7 +512,6 @@ private ServiceLoader(Class caller, Class svc, ClassLoader cl) { * @throws ServiceConfigurationError * If the caller module does not use the service type. */ - @SuppressWarnings("removal") private ServiceLoader(Module callerModule, Class svc, ClassLoader cl) { if (!callerModule.canUse(svc)) { fail(svc, callerModule + " does not declare `uses`"); @@ -539,9 +521,6 @@ private ServiceLoader(Module callerModule, Class svc, ClassLoader cl) { this.serviceName = svc.getName(); this.layer = null; this.loader = cl; - this.acc = (System.getSecurityManager() != null) - ? AccessController.getContext() - : null; } /** @@ -601,7 +580,6 @@ private boolean inExplicitModule(Class clazz) { * provider method or there is more than one public static * provider method */ - @SuppressWarnings("removal") private Method findStaticProviderMethod(Class clazz) { List methods = null; try { @@ -628,12 +606,7 @@ private Method findStaticProviderMethod(Class clazz) { } } if (result != null) { - Method m = result; - PrivilegedAction pa = () -> { - m.setAccessible(true); - return null; - }; - AccessController.doPrivileged(pa); + result.setAccessible(true); } return result; } @@ -644,27 +617,16 @@ private Method findStaticProviderMethod(Class clazz) { * @throws ServiceConfigurationError if the class does not have * public no-arg constructor */ - @SuppressWarnings("removal") private Constructor getConstructor(Class clazz) { - PrivilegedExceptionAction> pa - = new PrivilegedExceptionAction<>() { - @Override - public Constructor run() throws Exception { - Constructor ctor = clazz.getConstructor(); - if (inExplicitModule(clazz)) - ctor.setAccessible(true); - return ctor; - } - }; Constructor ctor = null; try { - ctor = AccessController.doPrivileged(pa); - } catch (Throwable x) { - if (x instanceof PrivilegedActionException) - x = x.getCause(); + ctor = clazz.getConstructor(); + } catch (NoSuchMethodException ex) { String cn = clazz.getName(); - fail(service, cn + " Unable to get public no-arg constructor", x); + fail(service, cn + " Unable to get public no-arg constructor", ex); } + if (inExplicitModule(clazz)) + ctor.setAccessible(true); return ctor; } @@ -678,29 +640,23 @@ private static class ProviderImpl implements Provider { final Class type; final Method factoryMethod; // factory method or null final Constructor ctor; // public no-args constructor or null - @SuppressWarnings("removal") - final AccessControlContext acc; ProviderImpl(Class service, Class type, - Method factoryMethod, - @SuppressWarnings("removal") AccessControlContext acc) { + Method factoryMethod) { this.service = service; this.type = type; this.factoryMethod = factoryMethod; this.ctor = null; - this.acc = acc; } ProviderImpl(Class service, Class type, - Constructor ctor, - @SuppressWarnings("removal") AccessControlContext acc) { + Constructor ctor) { this.service = service; this.type = type; this.factoryMethod = null; this.ctor = ctor; - this.acc = acc; } @Override @@ -723,36 +679,14 @@ public S get() { * permissions that are restricted by the security context of whatever * created this loader. */ - @SuppressWarnings("removal") private S invokeFactoryMethod() { Object result = null; - Throwable exc = null; - if (acc == null) { - try { - result = factoryMethod.invoke(null); - } catch (Throwable x) { - exc = x; - } - } else { - PrivilegedExceptionAction pa = new PrivilegedExceptionAction<>() { - @Override - public Object run() throws Exception { - return factoryMethod.invoke(null); - } - }; - // invoke factory method with permissions restricted by acc - try { - result = AccessController.doPrivileged(pa, acc); - } catch (Throwable x) { - if (x instanceof PrivilegedActionException) - x = x.getCause(); - exc = x; - } - } - if (exc != null) { - if (exc instanceof InvocationTargetException) - exc = exc.getCause(); - fail(service, factoryMethod + " failed", exc); + try { + result = factoryMethod.invoke(null); + } catch (Throwable ex) { + if (ex instanceof InvocationTargetException) + ex = ex.getCause(); + fail(service, factoryMethod + " failed", ex); } if (result == null) { fail(service, factoryMethod + " returned null"); @@ -767,38 +701,16 @@ public Object run() throws Exception { * with a security manager then the constructor runs with permissions that * are restricted by the security context of whatever created this loader. */ - @SuppressWarnings("removal") private S newInstance() { S p = null; - Throwable exc = null; - if (acc == null) { - try { - p = ctor.newInstance(); - } catch (Throwable x) { - exc = x; - } - } else { - PrivilegedExceptionAction pa = new PrivilegedExceptionAction<>() { - @Override - public S run() throws Exception { - return ctor.newInstance(); - } - }; - // invoke constructor with permissions restricted by acc - try { - p = AccessController.doPrivileged(pa, acc); - } catch (Throwable x) { - if (x instanceof PrivilegedActionException) - x = x.getCause(); - exc = x; - } - } - if (exc != null) { - if (exc instanceof InvocationTargetException) - exc = exc.getCause(); + try { + p = ctor.newInstance(); + } catch (Throwable ex) { + if (ex instanceof InvocationTargetException) + ex = ex.getCause(); String cn = ctor.getDeclaringClass().getName(); fail(service, - "Provider " + cn + " could not be instantiated", exc); + "Provider " + cn + " could not be instantiated", ex); } return p; } @@ -809,15 +721,14 @@ public S run() throws Exception { @Override public int hashCode() { - return Objects.hash(service, type, acc); + return Objects.hash(service, type); } @Override public boolean equals(Object ob) { return ob instanceof @SuppressWarnings("unchecked")ProviderImpl that && this.service == that.service - && this.type == that.type - && Objects.equals(this.acc, that.acc); + && this.type == that.type; } } @@ -831,7 +742,6 @@ public boolean equals(Object ob) { * isn't the expected sub-type (or doesn't define a provider * factory method that returns the expected type) */ - @SuppressWarnings("removal") private Provider loadProvider(ServiceProvider provider) { Module module = provider.module(); if (!module.canRead(service.getModule())) { @@ -841,22 +751,10 @@ private Provider loadProvider(ServiceProvider provider) { String cn = provider.providerName(); Class clazz = null; - if (acc == null) { - try { - clazz = Class.forName(module, cn); - } catch (LinkageError e) { - fail(service, "Unable to load " + cn, e); - } - } else { - PrivilegedExceptionAction> pa = () -> Class.forName(module, cn); - try { - clazz = AccessController.doPrivileged(pa); - } catch (Throwable x) { - if (x instanceof PrivilegedActionException) - x = x.getCause(); - fail(service, "Unable to load " + cn, x); - return null; - } + try { + clazz = Class.forName(module, cn); + } catch (LinkageError e) { + fail(service, "Unable to load " + cn, e); } if (clazz == null) { fail(service, "Provider " + cn + " not found"); @@ -878,7 +776,7 @@ private Provider loadProvider(ServiceProvider provider) { @SuppressWarnings("unchecked") Class type = (Class) returnType; - return new ProviderImpl(service, type, factoryMethod, acc); + return new ProviderImpl(service, type, factoryMethod); } } @@ -891,7 +789,7 @@ private Provider loadProvider(ServiceProvider provider) { Class type = (Class) clazz; @SuppressWarnings("unchecked") Constructor ctor = (Constructor ) getConstructor(clazz); - return new ProviderImpl(service, type, ctor, acc); + return new ProviderImpl(service, type, ctor); } /** @@ -997,20 +895,6 @@ private List providers(ModuleLayer layer) { return catalog.findServices(serviceName); } - /** - * Returns the class loader that a module is defined to - */ - @SuppressWarnings("removal") - private ClassLoader loaderFor(Module module) { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return module.getClassLoader(); - } else { - PrivilegedAction pa = module::getClassLoader; - return AccessController.doPrivileged(pa); - } - } - /** * Returns an iterator to iterate over the implementations of {@code * service} in modules defined to the given class loader or in custom @@ -1041,7 +925,7 @@ private Iterator iteratorFor(ClassLoader loader) { while (iterator.hasNext()) { ModuleLayer layer = iterator.next(); for (ServiceProvider sp : providers(layer)) { - ClassLoader l = loaderFor(sp.module()); + ClassLoader l = sp.module().getClassLoader(); if (l != null && l != platformClassLoader) { allProviders.add(sp); } @@ -1225,7 +1109,7 @@ private boolean hasNextService() { Class type = (Class) clazz; Constructor ctor = (Constructor)getConstructor(clazz); - ProviderImpl p = new ProviderImpl(service, type, ctor, acc); + ProviderImpl p = new ProviderImpl(service, type, ctor); nextProvider = (ProviderImpl) p; } else { fail(service, clazz.getName() + " not a subtype"); @@ -1253,30 +1137,14 @@ private Provider nextService() { } } - @SuppressWarnings("removal") @Override public boolean hasNext() { - if (acc == null) { - return hasNextService(); - } else { - PrivilegedAction action = new PrivilegedAction<>() { - public Boolean run() { return hasNextService(); } - }; - return AccessController.doPrivileged(action, acc); - } + return hasNextService(); } - @SuppressWarnings("removal") @Override public Provider next() { - if (acc == null) { - return nextService(); - } else { - PrivilegedAction> action = new PrivilegedAction<>() { - public Provider run() { return nextService(); } - }; - return AccessController.doPrivileged(action, acc); - } + return nextService(); } } diff --git a/src/java.base/share/classes/java/util/TimeZone.java b/src/java.base/share/classes/java/util/TimeZone.java index f1a2d92b6ba..f0b122418c9 100644 --- a/src/java.base/share/classes/java/util/TimeZone.java +++ b/src/java.base/share/classes/java/util/TimeZone.java @@ -43,7 +43,6 @@ import java.time.ZoneOffset; import jdk.internal.util.StaticProperty; -import sun.security.action.GetPropertyAction; import sun.util.calendar.ZoneInfo; import sun.util.calendar.ZoneInfoFile; import sun.util.locale.provider.TimeZoneNameUtility; @@ -683,7 +682,7 @@ static TimeZone getDefaultRef() { private static synchronized TimeZone setDefaultZone() { TimeZone tz; // get the time zone ID from the system properties - Properties props = GetPropertyAction.privilegedGetProperties(); + Properties props = System.getProperties(); String zoneID = props.getProperty("user.timezone"); // if the time zone ID is not set (yet), perform the @@ -729,12 +728,6 @@ private static synchronized TimeZone setDefaultZone() { */ public static void setDefault(TimeZone zone) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new PropertyPermission - ("user.timezone", "write")); - } // by saving a defensive clone and returning a clone in getDefault() too, // the defaultTimeZone instance is isolated from user code which makes it // effectively immutable. This is important to avoid races when the diff --git a/src/java.base/share/classes/java/util/TreeMap.java b/src/java.base/share/classes/java/util/TreeMap.java index 0e544573f01..79aec5c1456 100644 --- a/src/java.base/share/classes/java/util/TreeMap.java +++ b/src/java.base/share/classes/java/util/TreeMap.java @@ -420,10 +420,9 @@ else if (cmp > 0) } /** - * Gets the entry corresponding to the specified key; if no such entry - * exists, returns the entry for the least key greater than the specified - * key; if no such entry exists (i.e., the greatest key in the Tree is less - * than the specified key), returns {@code null}. + * Returns the entry for the least key greater than or equal to the specified key; + * if no such entry exists (i.e. the specified key is greater than any key in the tree, + * or the tree is empty), returns {@code null}. */ final Entry getCeilingEntry(K key) { Entry p = root; @@ -453,10 +452,9 @@ final Entry getCeilingEntry(K key) { } /** - * Gets the entry corresponding to the specified key; if no such entry - * exists, returns the entry for the greatest key less than the specified - * key; if no such entry exists (i.e., the least key in the Tree is greater - * than the specified key), returns {@code null}. + * Returns the entry for the greatest key less than or equal to the specified key; + * if no such entry exists (i.e. the specified key is less than any key in the tree, + * or the tree is empty), returns {@code null}. */ final Entry getFloorEntry(K key) { Entry p = root; diff --git a/src/java.base/share/classes/java/util/Tripwire.java b/src/java.base/share/classes/java/util/Tripwire.java index c807a419619..ec20b956375 100644 --- a/src/java.base/share/classes/java/util/Tripwire.java +++ b/src/java.base/share/classes/java/util/Tripwire.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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,9 +26,6 @@ import sun.util.logging.PlatformLogger; -import java.security.AccessController; -import java.security.PrivilegedAction; - /** * Utility class for detecting inadvertent uses of boxing in * {@code java.util} classes. The detection is turned on or off based on @@ -49,9 +46,7 @@ final class Tripwire { private static final String TRIPWIRE_PROPERTY = "org.openjdk.java.util.stream.tripwire"; /** Should debugging checks be enabled? */ - @SuppressWarnings("removal") - static final boolean ENABLED = AccessController.doPrivileged( - (PrivilegedAction) () -> Boolean.getBoolean(TRIPWIRE_PROPERTY)); + static final boolean ENABLED = Boolean.getBoolean(TRIPWIRE_PROPERTY); private Tripwire() { } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index 5a23fdb05a6..53919011c6f 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -70,6 +70,7 @@ import java.util.stream.Stream; import jdk.internal.misc.Unsafe; import jdk.internal.util.ArraysSupport; +import jdk.internal.vm.annotation.Stable; /** * A hash table supporting full concurrency of retrievals and @@ -595,7 +596,16 @@ public class ConcurrentHashMap extends AbstractMap static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash /** Number of CPUS, to place bounds on some sizings */ - static final int NCPU = Runtime.getRuntime().availableProcessors(); + static @Stable int NCPU; + + static { + runtimeSetup(); + } + + // Called from JVM when loading an AOT cache. + private static void runtimeSetup() { + NCPU = Runtime.getRuntime().availableProcessors(); + } /** * Serialized pseudo-fields, provided only for jdk7 compatibility. diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index e8dafaa0ac4..6a60a2397ce 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -3165,7 +3165,7 @@ public KeySpliterator trySplit() { current = n; Index r = q.down; row = (s.right != null) ? s : s.down; - est -= est >>> 2; + est >>>= 1; return new KeySpliterator(cmp, r, e, sk, est); } } @@ -3221,14 +3221,14 @@ public final Comparator getComparator() { } // factory method for KeySpliterator final KeySpliterator keySpliterator() { - Index h; Node n; long est; + Index h; Node hn, n; long est; VarHandle.acquireFence(); - if ((h = head) == null) { + if ((h = head) == null || (hn = h.node) == null) { n = null; est = 0L; } else { - n = h.node; + n = hn.next; est = getAdderCount(); } return new KeySpliterator(comparator, h, n, null, est); @@ -3255,7 +3255,7 @@ public ValueSpliterator trySplit() { current = n; Index r = q.down; row = (s.right != null) ? s : s.down; - est -= est >>> 2; + est >>>= 1; return new ValueSpliterator(cmp, r, e, sk, est); } } @@ -3307,14 +3307,14 @@ public int characteristics() { // Almost the same as keySpliterator() final ValueSpliterator valueSpliterator() { - Index h; Node n; long est; + Index h; Node hn, n; long est; VarHandle.acquireFence(); - if ((h = head) == null) { + if ((h = head) == null || (hn = h.node) == null) { n = null; est = 0L; } else { - n = h.node; + n = hn.next; est = getAdderCount(); } return new ValueSpliterator(comparator, h, n, null, est); @@ -3341,7 +3341,7 @@ public EntrySpliterator trySplit() { current = n; Index r = q.down; row = (s.right != null) ? s : s.down; - est -= est >>> 2; + est >>>= 1; return new EntrySpliterator(cmp, r, e, sk, est); } } @@ -3411,14 +3411,14 @@ public final Comparator> getComparator() { // Almost the same as keySpliterator() final EntrySpliterator entrySpliterator() { - Index h; Node n; long est; + Index h; Node hn, n; long est; VarHandle.acquireFence(); - if ((h = head) == null) { + if ((h = head) == null || (hn = h.node) == null) { n = null; est = 0L; } else { - n = h.node; + n = hn.next; est = getAdderCount(); } return new EntrySpliterator(comparator, h, n, null, est); diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index 2a2fbc54d86..0bcb7978e90 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -527,20 +527,11 @@ public Spliterator spliterator() { /** Initializes map field; for use in clone. */ private void setMap(ConcurrentNavigableMap map) { - @SuppressWarnings("removal") - Field mapField = java.security.AccessController.doPrivileged( - (java.security.PrivilegedAction) () -> { - try { - Field f = ConcurrentSkipListSet.class - .getDeclaredField("m"); - f.setAccessible(true); - return f; - } catch (ReflectiveOperationException e) { - throw new Error(e); - }}); try { + Field mapField = ConcurrentSkipListSet.class.getDeclaredField("m"); + mapField.setAccessible(true); mapField.set(this, map); - } catch (IllegalAccessException e) { + } catch (IllegalAccessException | NoSuchFieldException e) { throw new Error(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index f0f60730eb6..f5069c61d45 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -2096,20 +2096,11 @@ public List reversed() { /** Initializes the lock; for use when deserializing or cloning. */ private void resetLock() { - @SuppressWarnings("removal") - Field lockField = java.security.AccessController.doPrivileged( - (java.security.PrivilegedAction) () -> { - try { - Field f = CopyOnWriteArrayList.class - .getDeclaredField("lock"); - f.setAccessible(true); - return f; - } catch (ReflectiveOperationException e) { - throw new Error(e); - }}); try { + Field lockField = CopyOnWriteArrayList.class.getDeclaredField("lock"); + lockField.setAccessible(true); lockField.set(this, new Object()); - } catch (IllegalAccessException e) { + } catch (IllegalAccessException | NoSuchFieldException e) { throw new Error(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/Executors.java b/src/java.base/share/classes/java/util/concurrent/Executors.java index a0a25b1a70d..f804e225790 100644 --- a/src/java.base/share/classes/java/util/concurrent/Executors.java +++ b/src/java.base/share/classes/java/util/concurrent/Executors.java @@ -37,16 +37,12 @@ import static java.lang.ref.Reference.reachabilityFence; import java.lang.ref.Cleaner.Cleanable; -import java.security.AccessControlContext; -import java.security.AccessController; import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import jdk.internal.ref.CleanerFactory; -import sun.security.util.SecurityConstants; /** * Factory and utility methods for {@link Executor}, {@link @@ -559,27 +555,13 @@ public String toString() { */ private static final class PrivilegedCallable implements Callable { final Callable task; - @SuppressWarnings("removal") - final AccessControlContext acc; - @SuppressWarnings("removal") PrivilegedCallable(Callable task) { this.task = task; - this.acc = AccessController.getContext(); } - @SuppressWarnings("removal") public T call() throws Exception { - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public T run() throws Exception { - return task.call(); - } - }, acc); - } catch (PrivilegedActionException e) { - throw e.getException(); - } + return task.call(); } public String toString() { @@ -595,49 +577,26 @@ private static final class PrivilegedCallableUsingCurrentClassLoader implements Callable { final Callable task; @SuppressWarnings("removal") - final AccessControlContext acc; final ClassLoader ccl; @SuppressWarnings("removal") PrivilegedCallableUsingCurrentClassLoader(Callable task) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // Calls to getContextClassLoader from this class - // never trigger a security check, but we check - // whether our callers have this permission anyways. - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - - // Whether setContextClassLoader turns out to be necessary - // or not, we fail fast if permission is not available. - sm.checkPermission(new RuntimePermission("setContextClassLoader")); - } this.task = task; - this.acc = AccessController.getContext(); this.ccl = Thread.currentThread().getContextClassLoader(); } - @SuppressWarnings("removal") public T call() throws Exception { - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public T run() throws Exception { - Thread t = Thread.currentThread(); - ClassLoader cl = t.getContextClassLoader(); - if (ccl == cl) { - return task.call(); - } else { - t.setContextClassLoader(ccl); - try { - return task.call(); - } finally { - t.setContextClassLoader(cl); - } - } - } - }, acc); - } catch (PrivilegedActionException e) { - throw e.getException(); + Thread t = Thread.currentThread(); + ClassLoader cl = t.getContextClassLoader(); + if (ccl == cl) { + return task.call(); + } else { + t.setContextClassLoader(ccl); + try { + return task.call(); + } finally { + t.setContextClassLoader(cl); + } } } @@ -656,10 +615,7 @@ private static class DefaultThreadFactory implements ThreadFactory { private final String namePrefix; DefaultThreadFactory() { - @SuppressWarnings("removal") - SecurityManager s = System.getSecurityManager(); - group = (s != null) ? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); + group = Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; @@ -678,27 +634,14 @@ public Thread newThread(Runnable r) { } /** - * Thread factory capturing access control context and class loader. + * Thread factory capturing the current class loader. */ private static class PrivilegedThreadFactory extends DefaultThreadFactory { @SuppressWarnings("removal") - final AccessControlContext acc; final ClassLoader ccl; - @SuppressWarnings("removal") PrivilegedThreadFactory() { super(); - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // Calls to getContextClassLoader from this class - // never trigger a security check, but we check - // whether our callers have this permission anyways. - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - - // Fail fast - sm.checkPermission(new RuntimePermission("setContextClassLoader")); - } - this.acc = AccessController.getContext(); this.ccl = Thread.currentThread().getContextClassLoader(); } @@ -706,13 +649,8 @@ public Thread newThread(final Runnable r) { return super.newThread(new Runnable() { @SuppressWarnings("removal") public void run() { - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - Thread.currentThread().setContextClassLoader(ccl); - r.run(); - return null; - } - }, acc); + Thread.currentThread().setContextClassLoader(ccl); + r.run(); } }); } @@ -811,9 +749,7 @@ private static class AutoShutdownDelegatedExecutorService super(executor); Runnable action = () -> { if (!executor.isShutdown()) { - PrivilegedAction pa = () -> { executor.shutdown(); return null; }; - @SuppressWarnings("removal") - var ignore = AccessController.doPrivileged(pa); + executor.shutdown(); } }; cleanable = CleanerFactory.cleaner().register(this, action); diff --git a/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java b/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java index 17448e9bf3d..41c6b4914b9 100644 --- a/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java +++ b/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java @@ -26,8 +26,6 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.time.Duration; import java.time.Instant; import java.util.Objects; @@ -688,7 +686,7 @@ public StructuredTaskScope joinUntil(Instant deadline) /** * Interrupt all unfinished threads. */ - private void implInterruptAll() { + private void interruptAll() { flock.threads() .filter(t -> t != Thread.currentThread()) .forEach(t -> { @@ -698,19 +696,6 @@ private void implInterruptAll() { }); } - @SuppressWarnings("removal") - private void interruptAll() { - if (System.getSecurityManager() == null) { - implInterruptAll(); - } else { - PrivilegedAction pa = () -> { - implInterruptAll(); - return null; - }; - AccessController.doPrivileged(pa); - } - } - /** * Shutdown the task scope if not already shutdown. Return true if this method * shutdowns the task scope, false if already shutdown. diff --git a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index 751c190acc0..19eb3122947 100644 --- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -39,7 +39,6 @@ package java.util.concurrent; import java.io.ObjectStreamField; -import java.security.AccessControlContext; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; diff --git a/src/java.base/share/classes/java/util/concurrent/ThreadPerTaskExecutor.java b/src/java.base/share/classes/java/util/concurrent/ThreadPerTaskExecutor.java index e98ece084c0..f37ef6c956e 100644 --- a/src/java.base/share/classes/java/util/concurrent/ThreadPerTaskExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ThreadPerTaskExecutor.java @@ -26,7 +26,6 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import java.security.Permission; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -48,7 +47,6 @@ */ class ThreadPerTaskExecutor extends ThreadContainer implements ExecutorService { private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); - private static final Permission MODIFY_THREAD = new RuntimePermission("modifyThread"); private static final VarHandle STATE = MhUtil.findVarHandle( MethodHandles.lookup(), "state", int.class); @@ -80,18 +78,6 @@ static ThreadPerTaskExecutor create(ThreadFactory factory) { return executor; } - /** - * Throws SecurityException if there is a security manager set and it denies - * RuntimePermission("modifyThread"). - */ - @SuppressWarnings("removal") - private void checkPermission() { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(MODIFY_THREAD); - } - } - /** * Throws RejectedExecutionException if the executor has been shutdown. */ @@ -143,14 +129,12 @@ public long threadCount() { @Override public void shutdown() { - checkPermission(); if (!isShutdown()) tryShutdownAndTerminate(false); } @Override public List shutdownNow() { - checkPermission(); if (!isTerminated()) tryShutdownAndTerminate(true); return List.of(); @@ -202,7 +186,6 @@ private void awaitTermination() { @Override public void close() { - checkPermission(); awaitTermination(); } diff --git a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java index 65217849f19..e34810fe966 100644 --- a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -566,29 +566,6 @@ private void decrementWorkerCount() { private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); - /** - * Permission required for callers of shutdown and shutdownNow. - * We additionally require (see checkShutdownAccess) that callers - * have permission to actually interrupt threads in the worker set - * (as governed by Thread.interrupt, which relies on - * ThreadGroup.checkAccess, which in turn relies on - * SecurityManager.checkAccess). Shutdowns are attempted only if - * these checks pass. - * - * All actual invocations of Thread.interrupt (see - * interruptIdleWorkers and interruptWorkers) ignore - * SecurityExceptions, meaning that the attempted interrupts - * silently fail. In the case of shutdown, they should not fail - * unless the SecurityManager has inconsistent policies, sometimes - * allowing access to a thread and sometimes not. In such cases, - * failure to actually interrupt threads may disable or delay full - * termination. Other uses of interruptIdleWorkers are advisory, - * and failure to actually interrupt will merely delay response to - * configuration changes so is not handled exceptionally. - */ - private static final RuntimePermission shutdownPerm = - new RuntimePermission("modifyThread"); - /** * Class Worker mainly maintains interrupt control state for * threads running tasks, along with other minor bookkeeping. @@ -673,10 +650,7 @@ protected boolean tryRelease(int unused) { void interruptIfStarted() { Thread t; if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { - try { - t.interrupt(); - } catch (SecurityException ignore) { - } + t.interrupt(); } } } @@ -749,27 +723,7 @@ final void tryTerminate() { */ /** - * If there is a security manager, makes sure caller has - * permission to shut down threads in general (see shutdownPerm). - * If this passes, additionally makes sure the caller is allowed - * to interrupt each worker thread. This might not be true even if - * first check passed, if the SecurityManager treats some threads - * specially. - */ - private void checkShutdownAccess() { - // assert mainLock.isHeldByCurrentThread(); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(shutdownPerm); - for (Worker w : workers) - security.checkAccess(w.thread); - } - } - - /** - * Interrupts all threads, even if active. Ignores SecurityExceptions - * (in which case some threads may remain uninterrupted). + * Interrupts all threads, even if active. */ private void interruptWorkers() { // assert mainLock.isHeldByCurrentThread(); @@ -780,9 +734,7 @@ private void interruptWorkers() { /** * Interrupts threads that might be waiting for tasks (as * indicated by not being locked) so they can check for - * termination or configuration changes. Ignores - * SecurityExceptions (in which case some threads may remain - * uninterrupted). + * termination or configuration changes. * * @param onlyOne If true, interrupt at most one worker. This is * called only from tryTerminate when termination is otherwise @@ -805,7 +757,6 @@ private void interruptIdleWorkers(boolean onlyOne) { if (!t.isInterrupted() && w.tryLock()) { try { t.interrupt(); - } catch (SecurityException ignore) { } finally { w.unlock(); } @@ -1390,7 +1341,6 @@ public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { - checkShutdownAccess(); advanceRunState(SHUTDOWN); interruptIdleWorkers(); onShutdown(); // hook for ScheduledThreadPoolExecutor @@ -1420,7 +1370,6 @@ public List shutdownNow() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { - checkShutdownAccess(); advanceRunState(STOP); interruptWorkers(); tasks = drainQueue(); diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index 6d412315153..e01b3ec7d50 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -37,9 +37,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.function.IntBinaryOperator; import java.util.function.IntUnaryOperator; import jdk.internal.misc.Unsafe; @@ -385,30 +382,16 @@ private static final class AtomicIntegerFieldUpdaterImpl /** class holding the field */ private final Class tclass; - @SuppressWarnings("removal") AtomicIntegerFieldUpdaterImpl(final Class tclass, final String fieldName, final Class caller) { final Field field; final int modifiers; try { - field = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Field run() throws NoSuchFieldException { - return tclass.getDeclaredField(fieldName); - } - }); + field = tclass.getDeclaredField(fieldName); modifiers = field.getModifiers(); sun.reflect.misc.ReflectUtil.ensureMemberAccess( caller, tclass, null, modifiers); - ClassLoader cl = tclass.getClassLoader(); - ClassLoader ccl = caller.getClassLoader(); - if ((ccl != null) && (ccl != cl) && - ((cl == null) || !isAncestor(cl, ccl))) { - sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); - } - } catch (PrivilegedActionException pae) { - throw new RuntimeException(pae.getException()); } catch (Exception ex) { throw new RuntimeException(ex); } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index 0e496dbd6a5..57722f33371 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -37,9 +37,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.function.LongBinaryOperator; import java.util.function.LongUnaryOperator; import jdk.internal.misc.Unsafe; @@ -381,29 +378,15 @@ private static final class CASUpdater extends AtomicLongFieldUpdater { /** class holding the field */ private final Class tclass; - @SuppressWarnings("removal") CASUpdater(final Class tclass, final String fieldName, final Class caller) { final Field field; final int modifiers; try { - field = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Field run() throws NoSuchFieldException { - return tclass.getDeclaredField(fieldName); - } - }); + field = tclass.getDeclaredField(fieldName); modifiers = field.getModifiers(); sun.reflect.misc.ReflectUtil.ensureMemberAccess( caller, tclass, null, modifiers); - ClassLoader cl = tclass.getClassLoader(); - ClassLoader ccl = caller.getClassLoader(); - if ((ccl != null) && (ccl != cl) && - ((cl == null) || !isAncestor(cl, ccl))) { - sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); - } - } catch (PrivilegedActionException pae) { - throw new RuntimeException(pae.getException()); } catch (Exception ex) { throw new RuntimeException(ex); } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index ec00f40a568..dbec6b81dd9 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -329,20 +329,12 @@ private void readObject(java.io.ObjectInputStream s) throw new java.io.InvalidObjectException("Not array type"); if (a.getClass() != Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); - @SuppressWarnings("removal") - Field arrayField = java.security.AccessController.doPrivileged( - (java.security.PrivilegedAction) () -> { - try { - Field f = AtomicReferenceArray.class - .getDeclaredField("array"); - f.setAccessible(true); - return f; - } catch (ReflectiveOperationException e) { - throw new Error(e); - }}); try { + + Field arrayField = AtomicReferenceArray.class.getDeclaredField("array"); + arrayField.setAccessible(true); arrayField.set(this, a); - } catch (IllegalAccessException e) { + } catch (NoSuchFieldException | IllegalAccessException e) { throw new Error(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index b9dcdac9ba5..1c0c6d0afd0 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -37,9 +37,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.function.BinaryOperator; import java.util.function.UnaryOperator; import jdk.internal.misc.Unsafe; @@ -320,7 +317,6 @@ private static final class AtomicReferenceFieldUpdaterImpl * screenings fail. */ - @SuppressWarnings("removal") AtomicReferenceFieldUpdaterImpl(final Class tclass, final Class vclass, final String fieldName, @@ -329,24 +325,11 @@ private static final class AtomicReferenceFieldUpdaterImpl final Class fieldClass; final int modifiers; try { - field = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Field run() throws NoSuchFieldException { - return tclass.getDeclaredField(fieldName); - } - }); + field = tclass.getDeclaredField(fieldName); modifiers = field.getModifiers(); sun.reflect.misc.ReflectUtil.ensureMemberAccess( caller, tclass, null, modifiers); - ClassLoader cl = tclass.getClassLoader(); - ClassLoader ccl = caller.getClassLoader(); - if ((ccl != null) && (ccl != cl) && - ((cl == null) || !isAncestor(cl, ccl))) { - sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); - } fieldClass = field.getType(); - } catch (PrivilegedActionException pae) { - throw new RuntimeException(pae.getException()); } catch (Exception ex) { throw new RuntimeException(ex); } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java b/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java index 04ae2b45158..ad230f62ab6 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java @@ -380,17 +380,12 @@ else if (casBase(v = base, apply(fn, v, x))) BASE = MhUtil.findVarHandle(l1, "base", long.class); CELLSBUSY = MhUtil.findVarHandle(l1, "cellsBusy", int.class); - @SuppressWarnings("removal") - MethodHandles.Lookup l2 = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public MethodHandles.Lookup run() { - try { - return MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup()); - } catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - }}); - THREAD_PROBE = MhUtil.findVarHandle(l2, "threadLocalRandomProbe", int.class); + try { + MethodHandles.Lookup l2 = MethodHandles.privateLookupIn(Thread.class, l1); + THREAD_PROBE = MhUtil.findVarHandle(l2, "threadLocalRandomProbe", int.class); + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } } } diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index a14821d8046..7b64e3cdd04 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -28,7 +28,6 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.access.JavaUtilZipFileAccess; import jdk.internal.misc.ThreadTracker; -import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; import sun.security.util.SignatureFileVerifier; @@ -171,7 +170,7 @@ public class JarFile extends ZipFile { // multi-release jar file versions >= 9 BASE_VERSION = Runtime.Version.parse(Integer.toString(8)); BASE_VERSION_FEATURE = BASE_VERSION.feature(); - String jarVersion = GetPropertyAction.privilegedGetProperty("jdk.util.jar.version"); + String jarVersion = System.getProperty("jdk.util.jar.version"); int runtimeVersion = Runtime.version().feature(); if (jarVersion != null) { int jarVer = Integer.parseInt(jarVersion); @@ -180,8 +179,8 @@ public class JarFile extends ZipFile { : Math.max(jarVer, BASE_VERSION_FEATURE); } RUNTIME_VERSION = Runtime.Version.parse(Integer.toString(runtimeVersion)); - String enableMultiRelease = GetPropertyAction - .privilegedGetProperty("jdk.util.jar.enableMultiRelease", "true"); + String enableMultiRelease = System. + getProperty("jdk.util.jar.enableMultiRelease", "true"); switch (enableMultiRelease) { case "false" -> { MULTI_RELEASE_ENABLED = false; diff --git a/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java b/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java index 6eb35aed691..8db27ec586d 100644 --- a/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java +++ b/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,12 +32,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Locale; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; -import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; /** * {@code AbstractResourceBundleProvider} is an abstract class that provides @@ -78,11 +75,10 @@ * return null; * } * }} - * + *

* Refer to {@link ResourceBundleProvider} for details. * - * @see - * Resource Bundles and Named Modules + * @see ResourceBundle##resource-bundle-modules Resource Bundles and Named Modules * @since 9 */ public abstract class AbstractResourceBundleProvider implements ResourceBundleProvider { @@ -222,11 +218,8 @@ private ResourceBundle getBundle0(Module module, String bundleName) { * Returns the ResourceBundle of .class format if found in the module * of this provider. */ - private static ResourceBundle loadResourceBundle(Module module, String bundleName) - { - PrivilegedAction> pa = () -> Class.forName(module, bundleName); - @SuppressWarnings("removal") - Class c = AccessController.doPrivileged(pa, null, GET_CLASSLOADER_PERMISSION); + private static ResourceBundle loadResourceBundle(Module module, String bundleName) { + Class c = Class.forName(module, bundleName); if (c != null && ResourceBundle.class.isAssignableFrom(c)) { @SuppressWarnings("unchecked") Class bundleClass = (Class) c; @@ -241,28 +234,17 @@ private static ResourceBundle loadResourceBundle(Module module, String bundleNam */ private static ResourceBundle loadPropertyResourceBundle(Module module, String bundleName) - throws IOException - { + throws IOException { String resourceName = toResourceName(bundleName, "properties"); if (resourceName == null) { return null; } - PrivilegedAction pa = () -> { - try { - return module.getResourceAsStream(resourceName); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }; - try (@SuppressWarnings("removal") InputStream stream = AccessController.doPrivileged(pa)) { - if (stream != null) { - return new PropertyResourceBundle(stream); - } else { - return null; - } - } catch (UncheckedIOException e) { - throw e.getCause(); + InputStream stream = module.getResourceAsStream(resourceName); + if (stream != null) { + return new PropertyResourceBundle(stream); + } else { + return null; } } diff --git a/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java b/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java index 46712e5c80b..6e130872bd4 100644 --- a/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java +++ b/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java @@ -222,22 +222,10 @@ */ public abstract class LocaleServiceProvider { - private static Void checkPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("localeServiceProvider")); - } - return null; - } - private LocaleServiceProvider(Void ignore) { } - /** * Initializes a new locale service provider. */ - protected LocaleServiceProvider() { - this(checkPermission()); - } + protected LocaleServiceProvider() {} /** * {@return an array of all locales for which this locale service provider diff --git a/src/java.base/share/classes/java/util/spi/ToolProvider.java b/src/java.base/share/classes/java/util/spi/ToolProvider.java index 1a3a710e0be..20909522859 100644 --- a/src/java.base/share/classes/java/util/spi/ToolProvider.java +++ b/src/java.base/share/classes/java/util/spi/ToolProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -27,8 +27,6 @@ import java.io.PrintStream; import java.io.PrintWriter; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Objects; import java.util.Optional; import java.util.ServiceLoader; @@ -178,18 +176,14 @@ default int run(PrintStream out, PrintStream err, String... args) { * * @throws NullPointerException if {@code name} is {@code null} */ - @SuppressWarnings("removal") static Optional findFirst(String name) { Objects.requireNonNull(name); ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); - return AccessController.doPrivileged( - (PrivilegedAction>) () -> { - ServiceLoader sl = - ServiceLoader.load(ToolProvider.class, systemClassLoader); - return StreamSupport.stream(sl.spliterator(), false) - .filter(p -> p.name().equals(name)) - .findFirst(); - }); + + ServiceLoader sl = + ServiceLoader.load(ToolProvider.class, systemClassLoader); + return StreamSupport.stream(sl.spliterator(), false) + .filter(p -> p.name().equals(name)) + .findFirst(); } } - diff --git a/src/java.base/share/classes/java/util/stream/Tripwire.java b/src/java.base/share/classes/java/util/stream/Tripwire.java index 962c7d3e1b0..6aae5e67e50 100644 --- a/src/java.base/share/classes/java/util/stream/Tripwire.java +++ b/src/java.base/share/classes/java/util/stream/Tripwire.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,6 @@ */ package java.util.stream; -import java.security.AccessController; -import java.security.PrivilegedAction; - import sun.util.logging.PlatformLogger; /** @@ -49,9 +46,7 @@ final class Tripwire { private static final String TRIPWIRE_PROPERTY = "org.openjdk.java.util.stream.tripwire"; /** Should debugging checks be enabled? */ - @SuppressWarnings("removal") - static final boolean ENABLED = AccessController.doPrivileged( - (PrivilegedAction) () -> Boolean.getBoolean(TRIPWIRE_PROPERTY)); + static final boolean ENABLED = Boolean.getBoolean(TRIPWIRE_PROPERTY); private Tripwire() { } diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index a08d3bc7a1b..f736a092099 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -55,7 +55,6 @@ import jdk.internal.vm.annotation.Stable; import sun.nio.cs.UTF_8; import sun.nio.fs.DefaultFileSystemProvider; -import sun.security.action.GetPropertyAction; import sun.security.util.SignatureFileVerifier; import static java.util.zip.ZipConstants64.*; @@ -193,14 +192,6 @@ public ZipFile(File file, int mode, Charset charset) throws IOException } String name = file.getPath(); file = new File(name); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkRead(name); - if ((mode & OPEN_DELETE) != 0) { - sm.checkDelete(name); - } - } Objects.requireNonNull(charset, "charset"); this.filePath = name; @@ -1059,8 +1050,7 @@ private BitSet getMetaInfVersions(String name) { */ static boolean getDisableZip64ExtraFieldValidation() { boolean result; - String value = GetPropertyAction.privilegedGetProperty( - "jdk.util.zip.disableZip64ExtraFieldValidation"); + String value = System.getProperty("jdk.util.zip.disableZip64ExtraFieldValidation"); if (value == null) { result = false; } else { diff --git a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java index 3fe992ab440..47499858a37 100644 --- a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -35,7 +35,6 @@ import static java.util.zip.ZipEntry.isCENHeaderValid; import static java.util.zip.ZipUtils.*; import sun.nio.cs.UTF_8; -import sun.security.action.GetBooleanAction; /** * This class implements an output stream filter for writing files in the @@ -58,7 +57,7 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant * some in jdk7. */ private static final boolean inhibitZip64 = - GetBooleanAction.privilegedGetProperty("jdk.util.zip.inhibitZip64"); + Boolean.getBoolean("jdk.util.zip.inhibitZip64"); private static class XEntry { final ZipEntry entry; diff --git a/src/java.base/share/classes/javax/crypto/JceSecurity.java.template b/src/java.base/share/classes/javax/crypto/JceSecurity.java.template index cd5069d89dd..8b64b452b11 100644 --- a/src/java.base/share/classes/javax/crypto/JceSecurity.java.template +++ b/src/java.base/share/classes/javax/crypto/JceSecurity.java.template @@ -76,7 +76,6 @@ import sun.security.util.Debug; * @since 1.4 */ -@SuppressWarnings("removal") final class JceSecurity { private static final Debug debug = Debug.getInstance("jca"); @@ -109,15 +108,7 @@ final class JceSecurity { static { try { - AccessController.doPrivileged( - new PrivilegedExceptionAction<> () { - @Override - public Void run() throws Exception { - setupJurisdictionPolicies(); - return null; - } - } - ); + setupJurisdictionPolicies(); isRestricted = defaultPolicy.implies( CryptoAllPermission.INSTANCE) ? false : true; @@ -285,20 +276,14 @@ final class JceSecurity { synchronized (codeBaseCacheRef) { URL url = codeBaseCacheRef.get(clazz); if (url == null) { - url = AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public URL run() { - ProtectionDomain pd = clazz.getProtectionDomain(); - if (pd != null) { - CodeSource cs = pd.getCodeSource(); - if (cs != null) { - return cs.getLocation(); - } - } - return NULL_URL; - } - }); + url = NULL_URL; + ProtectionDomain pd = clazz.getProtectionDomain(); + if (pd != null) { + CodeSource cs = pd.getCodeSource(); + if (cs != null) { + url = cs.getLocation(); + } + } codeBaseCacheRef.put(clazz, url); } return (url == NULL_URL) ? null : url; diff --git a/src/java.base/share/classes/javax/crypto/JceSecurityManager.java b/src/java.base/share/classes/javax/crypto/JceSecurityManager.java index b178c8bfb02..6e4d39bb88f 100644 --- a/src/java.base/share/classes/javax/crypto/JceSecurityManager.java +++ b/src/java.base/share/classes/javax/crypto/JceSecurityManager.java @@ -65,18 +65,10 @@ final class JceSecurityManager { exemptPolicy = JceSecurity.getExemptPolicy(); allPerm = CryptoAllPermission.INSTANCE; - PrivilegedAction paSM = JceSecurityManager::new; - @SuppressWarnings("removal") - JceSecurityManager dummySecurityManager = - AccessController.doPrivileged(paSM); - INSTANCE = dummySecurityManager; + INSTANCE = new JceSecurityManager(); - PrivilegedAction paWalker = - () -> StackWalker.getInstance(Set.of(Option.DROP_METHOD_INFO, Option.RETAIN_CLASS_REFERENCE)); - @SuppressWarnings("removal") - StackWalker dummyWalker = AccessController.doPrivileged(paWalker); - - WALKER = dummyWalker; + WALKER = StackWalker.getInstance( + Set.of(Option.DROP_METHOD_INFO, Option.RETAIN_CLASS_REFERENCE)); } private JceSecurityManager() { diff --git a/src/java.base/share/classes/javax/crypto/ProviderVerifier.java b/src/java.base/share/classes/javax/crypto/ProviderVerifier.java index cbfd02c32f4..37d16dff568 100644 --- a/src/java.base/share/classes/javax/crypto/ProviderVerifier.java +++ b/src/java.base/share/classes/javax/crypto/ProviderVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -100,20 +100,12 @@ void verify() throws IOException { // Get a link to the Jarfile to search. try { - @SuppressWarnings("removal") - var tmp = AccessController.doPrivileged( - (PrivilegedExceptionAction) () -> { - JarURLConnection conn = - (JarURLConnection) url.openConnection(); - // You could do some caching here as - // an optimization. - conn.setUseCaches(false); - return conn.getJarFile(); - }); - jf = tmp; - } catch (java.security.PrivilegedActionException pae) { - throw new SecurityException("Cannot load " + url, - pae.getCause()); + JarURLConnection conn = (JarURLConnection) url.openConnection(); + // You could do some caching here as an optimization. + conn.setUseCaches(false); + jf = conn.getJarFile(); + } catch (IOException ioe) { + throw new SecurityException("Cannot load " + url, ioe); } if (jf != null) { diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index 80f4dfdf2aa..62ce8020d80 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -38,7 +38,6 @@ import java.net.URI; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; -import java.security.AccessControlContext; import java.security.ProtectionDomain; import java.util.List; import java.util.Map; diff --git a/src/java.base/share/classes/jdk/internal/access/JavaIOPrintStreamAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaObjectStreamReflectionAccess.java similarity index 81% rename from src/java.base/share/classes/jdk/internal/access/JavaIOPrintStreamAccess.java rename to src/java.base/share/classes/jdk/internal/access/JavaObjectStreamReflectionAccess.java index ec205e27dca..ea3e219e8ab 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaIOPrintStreamAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaObjectStreamReflectionAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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,10 +22,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package jdk.internal.access; -import java.io.PrintStream; +import java.lang.invoke.MethodHandle; -public interface JavaIOPrintStreamAccess { - Object lock(PrintStream ps); +public interface JavaObjectStreamReflectionAccess { + MethodHandle defaultReadObject(Class clazz); + MethodHandle defaultWriteObject(Class clazz); } diff --git a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java index 5acafe01a89..43a1daf762c 100644 --- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java +++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java @@ -71,14 +71,13 @@ public class SharedSecrets { private static JavaLangRefAccess javaLangRefAccess; private static JavaLangReflectAccess javaLangReflectAccess; private static JavaIOAccess javaIOAccess; - private static JavaIOPrintStreamAccess javaIOPrintStreamAccess; - private static JavaIOPrintWriterAccess javaIOPrintWriterAccess; private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; private static JavaIOFilePermissionAccess javaIOFilePermissionAccess; private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess; private static JavaObjectInputStreamReadString javaObjectInputStreamReadString; private static JavaObjectInputStreamAccess javaObjectInputStreamAccess; private static JavaObjectInputFilterAccess javaObjectInputFilterAccess; + private static JavaObjectStreamReflectionAccess javaObjectStreamReflectionAccess; private static JavaNetInetAddressAccess javaNetInetAddressAccess; private static JavaNetHttpCookieAccess javaNetHttpCookieAccess; private static JavaNetUriAccess javaNetUriAccess; @@ -288,32 +287,6 @@ public static JavaIOAccess getJavaIOAccess() { return access; } - public static void setJavaIOCPrintWriterAccess(JavaIOPrintWriterAccess a) { - javaIOPrintWriterAccess = a; - } - - public static JavaIOPrintWriterAccess getJavaIOPrintWriterAccess() { - var access = javaIOPrintWriterAccess; - if (access == null) { - ensureClassInitialized(PrintWriter.class); - access = javaIOPrintWriterAccess; - } - return access; - } - - public static void setJavaIOCPrintStreamAccess(JavaIOPrintStreamAccess a) { - javaIOPrintStreamAccess = a; - } - - public static JavaIOPrintStreamAccess getJavaIOPrintStreamAccess() { - var access = javaIOPrintStreamAccess; - if (access == null) { - ensureClassInitialized(PrintStream.class); - access = javaIOPrintStreamAccess; - } - return access; - } - public static void setJavaIOFileDescriptorAccess(JavaIOFileDescriptorAccess jiofda) { javaIOFileDescriptorAccess = jiofda; } @@ -459,6 +432,21 @@ public static void setJavaObjectInputFilterAccess(JavaObjectInputFilterAccess ac javaObjectInputFilterAccess = access; } + public static JavaObjectStreamReflectionAccess getJavaObjectStreamReflectionAccess() { + var access = javaObjectStreamReflectionAccess; + if (access == null) { + try { + Class.forName("java.io.ObjectStreamReflection$Access", true, null); + access = javaObjectStreamReflectionAccess; + } catch (ClassNotFoundException e) {} + } + return access; + } + + public static void setJavaObjectStreamReflectionAccess(JavaObjectStreamReflectionAccess access) { + javaObjectStreamReflectionAccess = access; + } + public static void setJavaIORandomAccessFileAccess(JavaIORandomAccessFileAccess jirafa) { javaIORandomAccessFileAccess = jirafa; } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java index b29b9f6f955..648582b8a7d 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java @@ -64,7 +64,7 @@ public final String name() { @Override public final void writeAttribute(BufWriter writer, T attr) { BufWriterImpl buf = (BufWriterImpl) writer; - buf.writeIndex(buf.constantPool().utf8Entry(name)); + buf.writeIndex(attr.attributeName()); int lengthIndex = buf.skip(4); writeBody(buf, attr); int written = buf.size() - lengthIndex - 4; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java index 59a2b03c91e..114101b02e5 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java @@ -47,6 +47,7 @@ public abstract sealed class BoundAttribute> private final AttributeMapper mapper; final ClassReaderImpl classReader; final int payloadStart; + Utf8Entry name; BoundAttribute(ClassReader classReader, AttributeMapper mapper, int payloadStart) { this.mapper = mapper; @@ -59,8 +60,11 @@ public int payloadLen() { } @Override - public String attributeName() { - return mapper.name(); + public Utf8Entry attributeName() { + if (name == null) { + name = classReader.readEntry(payloadStart - 6, Utf8Entry.class); + } + return name; } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java index b8fce2fd288..1ded017f2a2 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java @@ -574,7 +574,7 @@ private static MapNode classToTree(ClassModel clm, Verbosity verbosity) { list("flags", "flag", clm.flags().flags().stream().map(AccessFlag::name)), leaf("superclass", clm.superclass().map(ClassEntry::asInternalName).orElse("")), list("interfaces", "interface", clm.interfaces().stream().map(ClassEntry::asInternalName)), - list("attributes", "attribute", clm.attributes().stream().map(Attribute::attributeName))) + list("attributes", "attribute", clm.attributes().stream().map(Attribute::attributeName).map(Utf8Entry::stringValue))) .with(constantPoolToTree(clm.constantPool(), verbosity)) .with(attributesToTree(clm.attributes(), verbosity)) .with(new ListNodeImpl(BLOCK, "fields", clm.fields().stream().map(f -> @@ -672,7 +672,7 @@ private static MapNode fieldToTree(FieldModel f, Verbosity verbosity) { "flag", f.flags().flags().stream().map(AccessFlag::name)), leaf("field type", f.fieldType().stringValue()), list("attributes", - "attribute", f.attributes().stream().map(Attribute::attributeName))) + "attribute", f.attributes().stream().map(Attribute::attributeName).map(Utf8Entry::stringValue))) .with(attributesToTree(f.attributes(), verbosity)); } @@ -683,7 +683,7 @@ public static MapNode methodToTree(MethodModel m, Verbosity verbosity) { "flag", m.flags().flags().stream().map(AccessFlag::name)), leaf("method type", m.methodType().stringValue()), list("attributes", - "attribute", m.attributes().stream().map(Attribute::attributeName))) + "attribute", m.attributes().stream().map(Attribute::attributeName).map(Utf8Entry::stringValue))) .with(attributesToTree(m.attributes(), verbosity)) .with(codeToTree((CodeAttribute)m.code().orElse(null), verbosity)); } @@ -694,7 +694,7 @@ private static MapNode codeToTree(CodeAttribute com, Verbosity verbosity) { codeNode.with(leaf("max stack", com.maxStack())); codeNode.with(leaf("max locals", com.maxLocals())); codeNode.with(list("attributes", - "attribute", com.attributes().stream().map(Attribute::attributeName))); + "attribute", com.attributes().stream().map(Attribute::attributeName).map(Utf8Entry::stringValue))); var stackMap = new MapNodeImpl(BLOCK, "stack map frames"); var visibleTypeAnnos = new LinkedHashMap>(); var invisibleTypeAnnos = new LinkedHashMap>(); @@ -996,7 +996,7 @@ private static Node[] attributesToTree(List> attributes, Verbosity "name", rc.name().stringValue(), "type", rc.descriptor().stringValue())) .with(list("attributes", "attribute", rc.attributes().stream() - .map(Attribute::attributeName))) + .map(Attribute::attributeName).map(Utf8Entry::stringValue))) .with(attributesToTree(rc.attributes(), verbosity))))); case AnnotationDefaultAttribute ada -> nodes.add(new MapNodeImpl(FLOW, "annotation default").with(elementValueToTree(ada.defaultValue()))); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java index 7d554a35974..5093f6408c8 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java @@ -241,6 +241,11 @@ public void writeBody(BufWriterImpl b) { if (crSize < characterRangesCount) b.patchU2(pos, crSize); } + + @Override + public Utf8Entry attributeName() { + return constantPool.utf8Entry(Attributes.NAME_CHARACTER_RANGE_TABLE); + } }; attributes.withAttribute(a); } @@ -265,6 +270,11 @@ public void writeBody(BufWriterImpl b) { if (lvSize < localVariablesCount) b.patchU2(pos, lvSize); } + + @Override + public Utf8Entry attributeName() { + return constantPool.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE); + } }; attributes.withAttribute(a); } @@ -289,6 +299,11 @@ public void writeBody(BufWriterImpl b) { if (lvtSize < localVariableTypesCount) b.patchU2(pos, lvtSize); } + + @Override + public Utf8Entry attributeName() { + return constantPool.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TYPE_TABLE); + } }; attributes.withAttribute(a); } @@ -371,6 +386,11 @@ public void writeBody(BufWriterImpl buf) { dcb.attributes.writeTo(buf); buf.setLabelContext(null); } + + @Override + public Utf8Entry attributeName() { + return constantPool.utf8Entry(Attributes.NAME_CODE); + } }; } @@ -416,6 +436,11 @@ public void writeTo(BufWriterImpl b) { b.writeU2(buf.size() / 4); b.writeBytes(buf); } + + @Override + public Utf8Entry attributeName() { + return buf.constantPool().utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE); + } } private boolean codeAndExceptionsMatch(int codeLength) { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java b/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java index 0e26a8941e0..5ba81fc2927 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java @@ -146,6 +146,11 @@ public void writeBody(BufWriterImpl b) { for (int i = 0; i < bsmSize; i++) bootstrapMethodEntry(i).writeTo(buf); } + + @Override + public Utf8Entry attributeName() { + return utf8Entry(Attributes.NAME_BOOTSTRAP_METHODS); + } }; a.writeTo(buf); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java index a83c32dc05a..7e16aea5a52 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java @@ -35,6 +35,7 @@ import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.InvokeDynamicEntry; import java.lang.classfile.constantpool.MemberRefEntry; +import java.lang.classfile.constantpool.Utf8Entry; import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.util.ArrayList; @@ -401,6 +402,11 @@ public void writeBody(BufWriterImpl b) { prevFrame = fr; } } + + @Override + public Utf8Entry attributeName() { + return cp.utf8Entry(Attributes.NAME_STACK_MAP_TABLE); + } }; } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java b/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java index dfad66a897c..0b0f1836f66 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java @@ -54,11 +54,6 @@ public AttributeMapper attributeMapper() { return mapper; } - @Override - public String attributeName() { - return mapper.name(); - } - @Override @SuppressWarnings("unchecked") public void writeTo(BufWriterImpl buf) { @@ -93,6 +88,8 @@ public static final class UnboundConstantValueAttribute extends UnboundAttribute implements ConstantValueAttribute { + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_CONSTANT_VALUE); + private final ConstantValueEntry entry; public UnboundConstantValueAttribute(ConstantValueEntry entry) { @@ -105,27 +102,50 @@ public ConstantValueEntry constant() { return entry; } + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundDeprecatedAttribute extends UnboundAttribute implements DeprecatedAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_DEPRECATED); + public UnboundDeprecatedAttribute() { super(Attributes.deprecated()); } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundSyntheticAttribute extends UnboundAttribute implements SyntheticAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SYNTHETIC); + public UnboundSyntheticAttribute() { super(Attributes.synthetic()); } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundSignatureAttribute extends UnboundAttribute implements SignatureAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SIGNATURE); + private final Utf8Entry signature; public UnboundSignatureAttribute(Utf8Entry signature) { @@ -137,11 +157,19 @@ public UnboundSignatureAttribute(Utf8Entry signature) { public Utf8Entry signature() { return signature; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundExceptionsAttribute extends UnboundAttribute implements ExceptionsAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_EXCEPTIONS); + private final List exceptions; public UnboundExceptionsAttribute(List exceptions) { @@ -153,11 +181,19 @@ public UnboundExceptionsAttribute(List exceptions) { public List exceptions() { return exceptions; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundAnnotationDefaultAttribute extends UnboundAttribute implements AnnotationDefaultAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_ANNOTATION_DEFAULT); + private final AnnotationValue annotationDefault; public UnboundAnnotationDefaultAttribute(AnnotationValue annotationDefault) { @@ -169,10 +205,18 @@ public UnboundAnnotationDefaultAttribute(AnnotationValue annotationDefault) { public AnnotationValue defaultValue() { return annotationDefault; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundSourceFileAttribute extends UnboundAttribute implements SourceFileAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_FILE); + private final Utf8Entry sourceFile; public UnboundSourceFileAttribute(Utf8Entry sourceFile) { @@ -185,10 +229,17 @@ public Utf8Entry sourceFile() { return sourceFile; } + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundStackMapTableAttribute extends UnboundAttribute implements StackMapTableAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_STACK_MAP_TABLE); + private final List entries; public UnboundStackMapTableAttribute(List entries) { @@ -200,11 +251,19 @@ public UnboundStackMapTableAttribute(List entries) { public List entries() { return entries; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundInnerClassesAttribute extends UnboundAttribute implements InnerClassesAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_INNER_CLASSES); + private final List innerClasses; public UnboundInnerClassesAttribute(List innerClasses) { @@ -216,11 +275,19 @@ public UnboundInnerClassesAttribute(List innerClasses) { public List classes() { return innerClasses; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundRecordAttribute extends UnboundAttribute implements RecordAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RECORD); + private final List components; public UnboundRecordAttribute(List components) { @@ -232,11 +299,19 @@ public UnboundRecordAttribute(List components) { public List components() { return components; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundEnclosingMethodAttribute extends UnboundAttribute implements EnclosingMethodAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_ENCLOSING_METHOD); + private final ClassEntry classEntry; private final NameAndTypeEntry method; @@ -255,11 +330,19 @@ public ClassEntry enclosingClass() { public Optional enclosingMethod() { return Optional.ofNullable(method); } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundMethodParametersAttribute extends UnboundAttribute implements MethodParametersAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_METHOD_PARAMETERS); + private final List parameters; public UnboundMethodParametersAttribute(List parameters) { @@ -271,11 +354,19 @@ public UnboundMethodParametersAttribute(List parameters) { public List parameters() { return parameters; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundModuleTargetAttribute extends UnboundAttribute implements ModuleTargetAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_TARGET); + final Utf8Entry moduleTarget; public UnboundModuleTargetAttribute(Utf8Entry moduleTarget) { @@ -287,11 +378,19 @@ public UnboundModuleTargetAttribute(Utf8Entry moduleTarget) { public Utf8Entry targetPlatform() { return moduleTarget; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundModuleMainClassAttribute extends UnboundAttribute implements ModuleMainClassAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_MAIN_CLASS); + final ClassEntry mainClass; public UnboundModuleMainClassAttribute(ClassEntry mainClass) { @@ -303,11 +402,19 @@ public UnboundModuleMainClassAttribute(ClassEntry mainClass) { public ClassEntry mainClass() { return mainClass; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundModuleHashesAttribute extends UnboundAttribute implements ModuleHashesAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_HASHES); + private final Utf8Entry algorithm; private final List hashes; @@ -326,11 +433,19 @@ public Utf8Entry algorithm() { public List hashes() { return hashes; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundModulePackagesAttribute extends UnboundAttribute implements ModulePackagesAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_PACKAGES); + private final Collection packages; public UnboundModulePackagesAttribute(Collection packages) { @@ -342,11 +457,19 @@ public UnboundModulePackagesAttribute(Collection packages) { public List packages() { return List.copyOf(packages); } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundModuleResolutionAttribute extends UnboundAttribute implements ModuleResolutionAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_RESOLUTION); + private final int resolutionFlags; public UnboundModuleResolutionAttribute(int flags) { @@ -358,11 +481,19 @@ public UnboundModuleResolutionAttribute(int flags) { public int resolutionFlags() { return resolutionFlags; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundPermittedSubclassesAttribute extends UnboundAttribute implements PermittedSubclassesAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_PERMITTED_SUBCLASSES); + private final List permittedSubclasses; public UnboundPermittedSubclassesAttribute(List permittedSubclasses) { @@ -374,11 +505,19 @@ public UnboundPermittedSubclassesAttribute(List permittedSubclasses) public List permittedSubclasses() { return permittedSubclasses; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundNestMembersAttribute extends UnboundAttribute implements NestMembersAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_NEST_MEMBERS); + private final List memberEntries; public UnboundNestMembersAttribute(List memberEntries) { @@ -390,11 +529,19 @@ public UnboundNestMembersAttribute(List memberEntries) { public List nestMembers() { return memberEntries; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundNestHostAttribute extends UnboundAttribute implements NestHostAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_NEST_HOST); + private final ClassEntry hostEntry; public UnboundNestHostAttribute(ClassEntry hostEntry) { @@ -406,11 +553,19 @@ public UnboundNestHostAttribute(ClassEntry hostEntry) { public ClassEntry nestHost() { return hostEntry; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundCompilationIDAttribute extends UnboundAttribute implements CompilationIDAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_COMPILATION_ID); + private final Utf8Entry idEntry; public UnboundCompilationIDAttribute(Utf8Entry idEntry) { @@ -422,11 +577,19 @@ public UnboundCompilationIDAttribute(Utf8Entry idEntry) { public Utf8Entry compilationId() { return idEntry; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundSourceIDAttribute extends UnboundAttribute implements SourceIDAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_ID); + private final Utf8Entry idEntry; public UnboundSourceIDAttribute(Utf8Entry idEntry) { @@ -438,11 +601,19 @@ public UnboundSourceIDAttribute(Utf8Entry idEntry) { public Utf8Entry sourceId() { return idEntry; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundSourceDebugExtensionAttribute extends UnboundAttribute implements SourceDebugExtensionAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_SOURCE_DEBUG_EXTENSION); + private final byte[] contents; public UnboundSourceDebugExtensionAttribute(byte[] contents) { @@ -454,11 +625,19 @@ public UnboundSourceDebugExtensionAttribute(byte[] contents) { public byte[] contents() { return contents; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundCharacterRangeTableAttribute extends UnboundAttribute implements CharacterRangeTableAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_CHARACTER_RANGE_TABLE); + private final List ranges; public UnboundCharacterRangeTableAttribute(List ranges) { @@ -470,11 +649,19 @@ public UnboundCharacterRangeTableAttribute(List ranges) { public List characterRangeTable() { return ranges; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundLineNumberTableAttribute extends UnboundAttribute implements LineNumberTableAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE); + private final List lines; public UnboundLineNumberTableAttribute(List lines) { @@ -486,11 +673,19 @@ public UnboundLineNumberTableAttribute(List lines) { public List lineNumbers() { return lines; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundLocalVariableTableAttribute extends UnboundAttribute implements LocalVariableTableAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE); + private final List locals; public UnboundLocalVariableTableAttribute(List locals) { @@ -502,11 +697,19 @@ public UnboundLocalVariableTableAttribute(List locals) { public List localVariables() { return locals; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundLocalVariableTypeTableAttribute extends UnboundAttribute implements LocalVariableTypeTableAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TYPE_TABLE); + private final List locals; public UnboundLocalVariableTypeTableAttribute(List locals) { @@ -518,11 +721,19 @@ public UnboundLocalVariableTypeTableAttribute(List locals public List localVariableTypes() { return locals; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundRuntimeVisibleAnnotationsAttribute extends UnboundAttribute implements RuntimeVisibleAnnotationsAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_ANNOTATIONS); + private final List elements; public UnboundRuntimeVisibleAnnotationsAttribute(List elements) { @@ -534,11 +745,19 @@ public UnboundRuntimeVisibleAnnotationsAttribute(List elements) { public List annotations() { return elements; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundRuntimeInvisibleAnnotationsAttribute extends UnboundAttribute implements RuntimeInvisibleAnnotationsAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_ANNOTATIONS); + private final List elements; public UnboundRuntimeInvisibleAnnotationsAttribute(List elements) { @@ -550,11 +769,19 @@ public UnboundRuntimeInvisibleAnnotationsAttribute(List elements) { public List annotations() { return elements; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundRuntimeVisibleParameterAnnotationsAttribute extends UnboundAttribute implements RuntimeVisibleParameterAnnotationsAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS); + private final List> elements; public UnboundRuntimeVisibleParameterAnnotationsAttribute(List> elements) { @@ -572,11 +799,19 @@ public UnboundRuntimeVisibleParameterAnnotationsAttribute(List> public List> parameterAnnotations() { return elements; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundRuntimeInvisibleParameterAnnotationsAttribute extends UnboundAttribute implements RuntimeInvisibleParameterAnnotationsAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS); + private final List> elements; public UnboundRuntimeInvisibleParameterAnnotationsAttribute(List> elements) { @@ -594,11 +829,19 @@ public UnboundRuntimeInvisibleParameterAnnotationsAttribute(List> parameterAnnotations() { return elements; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundRuntimeVisibleTypeAnnotationsAttribute extends UnboundAttribute implements RuntimeVisibleTypeAnnotationsAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS); + private final List elements; public UnboundRuntimeVisibleTypeAnnotationsAttribute(List elements) { @@ -610,11 +853,19 @@ public UnboundRuntimeVisibleTypeAnnotationsAttribute(List elemen public List annotations() { return elements; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public static final class UnboundRuntimeInvisibleTypeAnnotationsAttribute extends UnboundAttribute implements RuntimeInvisibleTypeAnnotationsAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); + private final List elements; public UnboundRuntimeInvisibleTypeAnnotationsAttribute(List elements) { @@ -626,6 +877,11 @@ public UnboundRuntimeInvisibleTypeAnnotationsAttribute(List elem public List annotations() { return elements; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public record UnboundCharacterRangeInfo(int startPc, int endPc, @@ -749,6 +1005,9 @@ public record TypePathComponentImpl(TypeAnnotation.TypePathComponent.Kind typePa implements TypeAnnotation.TypePathComponent {} public static final class UnboundModuleAttribute extends UnboundAttribute implements ModuleAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE); + private final ModuleEntry moduleName; private final int moduleFlags; private final Utf8Entry moduleVersion; @@ -817,6 +1076,11 @@ public List uses() { public List provides() { return provides; } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } public abstract static non-sealed class AdHocAttribute> @@ -841,6 +1105,9 @@ public void writeTo(BufWriterImpl b) { public static final class EmptyBootstrapAttribute extends UnboundAttribute implements BootstrapMethodsAttribute { + + private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_BOOTSTRAP_METHODS); + public EmptyBootstrapAttribute() { super(Attributes.bootstrapMethods()); } @@ -854,5 +1121,10 @@ public int bootstrapMethodsSize() { public List bootstrapMethods() { return List.of(); } + + @Override + public Utf8Entry attributeName() { + return NAME; + } } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java index 1088724d8b4..fc6099f3e5b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java @@ -281,6 +281,11 @@ public void writeBody(BufWriterImpl b) { b.writeBytes(bytecode.array(), 0, bytecode.length()); b.writeU2U2(0, 0);//exception handlers & attributes } + + @Override + public Utf8Entry attributeName() { + return cp.utf8Entry(Attributes.NAME_CODE); + } })))); ClassPrinter.toYaml(clm.methods().get(0).code().get(), ClassPrinter.Verbosity.TRACE_ALL, dump); } catch (Error | Exception _) { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java index 521d74ae133..b7ddaace116 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/ParserVerifier.java @@ -176,8 +176,8 @@ private void verifyAttributes(ClassFileElement cfe, List errors) { if (cfe instanceof AttributedElement ae) { var attrNames = new HashSet(); for (var a : ae.attributes()) { - if (!a.attributeMapper().allowMultiple() && !attrNames.add(a.attributeName())) { - errors.add(new VerifyError("Multiple %s attributes in %s".formatted(a.attributeName(), toString(ae)))); + if (!a.attributeMapper().allowMultiple() && !attrNames.add(a.attributeName().stringValue())) { + errors.add(new VerifyError("Multiple %s attributes in %s".formatted(a.attributeName().stringValue(), toString(ae)))); } verifyAttribute(ae, a, errors); } @@ -331,7 +331,7 @@ private void verifyAttribute(AttributedElement ae, Attribute a, List= 0 && size != ((BoundAttribute)a).payloadLen()) { - errors.add(new VerifyError("Wrong %s attribute length in %s".formatted(a.attributeName(), toString(ae)))); + errors.add(new VerifyError("Wrong %s attribute length in %s".formatted(a.attributeName().stringValue(), toString(ae)))); } } diff --git a/src/java.base/share/classes/jdk/internal/constant/MethodTypeDescImpl.java b/src/java.base/share/classes/jdk/internal/constant/MethodTypeDescImpl.java index 826fc095bbd..fcbf6064853 100644 --- a/src/java.base/share/classes/jdk/internal/constant/MethodTypeDescImpl.java +++ b/src/java.base/share/classes/jdk/internal/constant/MethodTypeDescImpl.java @@ -32,8 +32,6 @@ import java.lang.constant.MethodTypeDesc; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -320,15 +318,8 @@ private String buildDescriptorString() { public MethodType resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException { MethodType mtype; try { - @SuppressWarnings("removal") - MethodType mt = AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public MethodType run() { - return MethodType.fromMethodDescriptorString(descriptorString(), - lookup.lookupClass().getClassLoader()); - } - }); - mtype = mt; + mtype = MethodType.fromMethodDescriptorString(descriptorString(), + lookup.lookupClass().getClassLoader()); } catch (TypeNotPresentException ex) { throw (ClassNotFoundException) ex.getCause(); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java b/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java index 7194813aff7..8adf51ef6fd 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java @@ -35,6 +35,7 @@ import jdk.internal.loader.NativeLibrary; import jdk.internal.loader.RawNativeLibraries; import jdk.internal.util.OperatingSystem; +import jdk.internal.util.StaticProperty; import static java.lang.foreign.ValueLayout.ADDRESS; @@ -125,7 +126,7 @@ private static SymbolLookup libLookup(Function loadClass(Module module, String name) { /** * Loads a native library from the system library path. */ - @SuppressWarnings("removal") public static void loadLibrary(String name) { - if (System.getSecurityManager() == null) { - BootLoader.getNativeLibraries().loadLibrary(name); - } else { - AccessController.doPrivileged(new java.security.PrivilegedAction<>() { - public Void run() { - BootLoader.getNativeLibraries().loadLibrary(name); - return null; - } - }); - } + getNativeLibraries().loadLibrary(name); } /** @@ -294,38 +282,28 @@ private static Module findModule(String location) { /** * Returns URL if the given location is a regular file path. */ - @SuppressWarnings("removal") private static URL toFileURL(String location) { - return AccessController.doPrivileged(new PrivilegedAction<>() { - public URL run() { - Path path = Path.of(location); - if (Files.isRegularFile(path)) { - try { - return path.toUri().toURL(); - } catch (MalformedURLException e) {} - } - return null; - } - }); + Path path = Path.of(location); + if (Files.isRegularFile(path)) { + try { + return path.toUri().toURL(); + } catch (MalformedURLException e) {} + } + return null; } /** * Returns the Manifest if the given location is a JAR file * containing a manifest. */ - @SuppressWarnings("removal") private static Manifest getManifest(String location) { - return AccessController.doPrivileged(new PrivilegedAction<>() { - public Manifest run() { - Path jar = Path.of(location); - try (InputStream in = Files.newInputStream(jar); - JarInputStream jis = new JarInputStream(in, false)) { - return jis.getManifest(); - } catch (IOException e) { - return null; - } - } - }); + Path jar = Path.of(location); + try (InputStream in = Files.newInputStream(jar); + JarInputStream jis = new JarInputStream(in, false)) { + return jis.getManifest(); + } catch (IOException e) { + return null; + } } } diff --git a/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java b/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java index 84e5c50672d..f6cc79fd127 100644 --- a/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java +++ b/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -35,13 +35,8 @@ import java.net.URI; import java.net.URL; import java.nio.ByteBuffer; -import java.security.AccessController; import java.security.CodeSigner; import java.security.CodeSource; -import java.security.PermissionCollection; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.security.SecureClassLoader; import java.util.ArrayList; import java.util.Collections; @@ -62,7 +57,6 @@ import jdk.internal.module.ModulePatcher.PatchedModuleReader; import jdk.internal.module.Resources; import jdk.internal.vm.annotation.Stable; -import sun.security.util.LazyCodeSourcePermissionCollection; /** @@ -281,31 +275,30 @@ public URL findResource(String mn, String name) throws IOException { url = findResourceOnClassPath(name); } - return checkURL(url); // check access before returning + return url; } /** * Returns an input stream to a resource of the given name in a module * defined to this class loader. */ - @SuppressWarnings("removal") public InputStream findResourceAsStream(String mn, String name) throws IOException { - // Need URL to resource when running with a security manager so that - // the right permission check is done. - if (System.getSecurityManager() != null || mn == null) { - URL url = findResource(mn, name); - return (url != null) ? url.openStream() : null; - } - - // find in module defined to this loader, no security manager - ModuleReference mref = nameToModule.get(mn); - if (mref != null) { - return moduleReaderFor(mref).open(name).orElse(null); + InputStream in = null; + if (mn != null) { + // find in module defined to this loader + ModuleReference mref = nameToModule.get(mn); + if (mref != null) { + in = moduleReaderFor(mref).open(name).orElse(null); + } } else { - return null; + URL url = findResourceOnClassPath(name); + if (url != null) { + in = url.openStream(); + } } + return in; } /** @@ -322,7 +315,7 @@ public URL findResource(String name) { if (module.loader() == this) { URL url; try { - url = findResource(module.name(), name); // checks URL + url = findResource(module.name(), name); } catch (IOException ioe) { return null; } @@ -342,7 +335,7 @@ public URL findResource(String name) { if (!urls.isEmpty()) { URL url = urls.get(0); if (url != null) { - return checkURL(url); // check access before returning + return url; } } } catch (IOException ioe) { @@ -352,8 +345,7 @@ public URL findResource(String name) { } // search class path - URL url = findResourceOnClassPath(name); - return checkURL(url); + return findResourceOnClassPath(name); } /** @@ -363,7 +355,7 @@ public URL findResource(String name) { */ @Override public Enumeration findResources(String name) throws IOException { - List checked = new ArrayList<>(); // list of checked URLs + List resources = new ArrayList<>(); // list of resource URLs String pn = Resources.toPackageName(name); LoadedModule module = packageToModule.get(pn); @@ -371,31 +363,30 @@ public Enumeration findResources(String name) throws IOException { // resource is in a package of a module defined to this loader if (module.loader() == this) { - URL url = findResource(module.name(), name); // checks URL + URL url = findResource(module.name(), name); if (url != null && (name.endsWith(".class") || url.toString().endsWith("/") || isOpen(module.mref(), pn))) { - checked.add(url); + resources.add(url); } } } else { // not in a package of a module defined to this loader for (URL url : findMiscResource(name)) { - url = checkURL(url); if (url != null) { - checked.add(url); + resources.add(url); } } } - // class path (not checked) + // class path Enumeration e = findResourcesOnClassPath(name); - // concat the checked URLs and the (not checked) class path + // concat the URLs of the resource in the modules and the class path return new Enumeration<>() { - final Iterator iterator = checked.iterator(); + final Iterator iterator = resources.iterator(); URL next; private boolean hasNext() { if (next != null) { @@ -404,9 +395,8 @@ private boolean hasNext() { next = iterator.next(); return true; } else { - // need to check each URL while (e.hasMoreElements() && next == null) { - next = checkURL(e.nextElement()); + next = e.nextElement(); } return next != null; } @@ -436,7 +426,6 @@ public URL nextElement() { * * The cache used by this method avoids repeated searching of all modules. */ - @SuppressWarnings("removal") private List findMiscResource(String name) throws IOException { SoftReference>> ref = this.resourceCache; Map> map = (ref != null) ? ref.get() : null; @@ -453,30 +442,20 @@ private List findMiscResource(String name) throws IOException { } // search all modules for the resource - List urls; - try { - urls = AccessController.doPrivileged( - new PrivilegedExceptionAction<>() { - @Override - public List run() throws IOException { - List result = null; - for (ModuleReference mref : nameToModule.values()) { - URI u = moduleReaderFor(mref).find(name).orElse(null); - if (u != null) { - try { - if (result == null) - result = new ArrayList<>(); - result.add(u.toURL()); - } catch (MalformedURLException | - IllegalArgumentException e) { - } - } - } - return (result != null) ? result : Collections.emptyList(); - } - }); - } catch (PrivilegedActionException pae) { - throw (IOException) pae.getCause(); + List urls = null; + for (ModuleReference mref : nameToModule.values()) { + URI u = moduleReaderFor(mref).find(name).orElse(null); + if (u != null) { + try { + if (urls == null) + urls = new ArrayList<>(); + urls.add(u.toURL()); + } catch (MalformedURLException | IllegalArgumentException e) { + } + } + } + if (urls == null) { + urls = List.of(); } // only cache resources after VM is fully initialized @@ -490,23 +469,8 @@ public List run() throws IOException { /** * Returns the URL to a resource in a module or {@code null} if not found. */ - @SuppressWarnings("removal") private URL findResource(ModuleReference mref, String name) throws IOException { - URI u; - if (System.getSecurityManager() == null) { - u = moduleReaderFor(mref).find(name).orElse(null); - } else { - try { - u = AccessController.doPrivileged(new PrivilegedExceptionAction<> () { - @Override - public URI run() throws IOException { - return moduleReaderFor(mref).find(name).orElse(null); - } - }); - } catch (PrivilegedActionException pae) { - throw (IOException) pae.getCause(); - } - } + URI u = moduleReaderFor(mref).find(name).orElse(null); if (u != null) { try { return u.toURL(); @@ -515,30 +479,12 @@ public URI run() throws IOException { return null; } - /** - * Returns the URL to a resource in a module. Returns {@code null} if not found - * or an I/O error occurs. - */ - private URL findResourceOrNull(ModuleReference mref, String name) { - try { - return findResource(mref, name); - } catch (IOException ignore) { - return null; - } - } - /** * Returns a URL to a resource on the class path. */ - @SuppressWarnings("removal") private URL findResourceOnClassPath(String name) { if (hasClassPath()) { - if (System.getSecurityManager() == null) { - return ucp.findResource(name, false); - } else { - PrivilegedAction pa = () -> ucp.findResource(name, false); - return AccessController.doPrivileged(pa); - } + return ucp.findResource(name); } else { // no class path return null; @@ -548,16 +494,9 @@ private URL findResourceOnClassPath(String name) { /** * Returns the URLs of all resources of the given name on the class path. */ - @SuppressWarnings("removal") private Enumeration findResourcesOnClassPath(String name) { if (hasClassPath()) { - if (System.getSecurityManager() == null) { - return ucp.findResources(name, false); - } else { - PrivilegedAction> pa; - pa = () -> ucp.findResources(name, false); - return AccessController.doPrivileged(pa); - } + return ucp.findResources(name); } else { // no class path return Collections.emptyEnumeration(); @@ -735,14 +674,8 @@ private LoadedModule findLoadedModule(String mn, String cn) { * * @return the resulting Class or {@code null} if not found */ - @SuppressWarnings("removal") private Class findClassInModuleOrNull(LoadedModule loadedModule, String cn) { - if (System.getSecurityManager() == null) { - return defineClass(cn, loadedModule); - } else { - PrivilegedAction> pa = () -> defineClass(cn, loadedModule); - return AccessController.doPrivileged(pa); - } + return defineClass(cn, loadedModule); } /** @@ -750,36 +683,17 @@ private Class findClassInModuleOrNull(LoadedModule loadedModule, String cn) { * * @return the resulting Class or {@code null} if not found */ - @SuppressWarnings("removal") private Class findClassOnClassPathOrNull(String cn) { String path = cn.replace('.', '/').concat(".class"); - if (System.getSecurityManager() == null) { - Resource res = ucp.getResource(path, false); - if (res != null) { - try { - return defineClass(cn, res); - } catch (IOException ioe) { - // TBD on how I/O errors should be propagated - } + Resource res = ucp.getResource(path); + if (res != null) { + try { + return defineClass(cn, res); + } catch (IOException ioe) { + // TBD on how I/O errors should be propagated } - return null; - } else { - // avoid use of lambda here - PrivilegedAction> pa = new PrivilegedAction<>() { - public Class run() { - Resource res = ucp.getResource(path, false); - if (res != null) { - try { - return defineClass(cn, res); - } catch (IOException ioe) { - // TBD on how I/O errors should be propagated - } - } - return null; - } - }; - return AccessController.doPrivileged(pa); } + return null; } /** @@ -998,16 +912,6 @@ private boolean isSealed(String pn, Manifest man) { return "true".equalsIgnoreCase(sealed); } - // -- permissions - - /** - * Returns the permissions for the given CodeSource. - */ - @Override - protected PermissionCollection getPermissions(CodeSource cs) { - return new LazyCodeSourcePermissionCollection(super.getPermissions(cs), cs); - } - // -- miscellaneous supporting methods /** @@ -1072,14 +976,6 @@ private boolean isOpen(ModuleReference mref, String pn) { return false; } - /** - * Checks access to the given URL. We use URLClassPath for consistent - * checking with java.net.URLClassLoader. - */ - private static URL checkURL(URL url) { - return URLClassPath.checkURL(url); - } - // Called from VM only, during -Xshare:dump private void resetArchivedStates() { ucp = null; diff --git a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java index ab4aa3fb907..1a61d4b1522 100644 --- a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java +++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,6 @@ import java.net.URL; import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.security.CodeSource; -import java.security.PermissionCollection; import java.util.jar.Manifest; import jdk.internal.access.JavaLangAccess; @@ -170,31 +168,6 @@ private static class AppClassLoader extends BuiltinClassLoader { super("app", parent, ucp); } - @Override - protected Class loadClass(String cn, boolean resolve) - throws ClassNotFoundException - { - // for compatibility reasons, say where restricted package list has - // been updated to list API packages in the unnamed module. - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - int i = cn.lastIndexOf('.'); - if (i != -1) { - sm.checkPackageAccess(cn.substring(0, i)); - } - } - - return super.loadClass(cn, resolve); - } - - @Override - protected PermissionCollection getPermissions(CodeSource cs) { - PermissionCollection perms = super.getPermissions(cs); - perms.add(new RuntimePermission("exitVM")); - return perms; - } - /** * Called by the VM to support dynamic additions to the class path * @@ -207,6 +180,7 @@ void appendToClassPathForInstrumentation(String path) { /** * Called by the VM to support define package for AppCDS */ + @Override protected Package defineOrCheckPackage(String pn, Manifest man, URL url) { return super.defineOrCheckPackage(pn, man, url); } diff --git a/src/java.base/share/classes/jdk/internal/loader/Loader.java b/src/java.base/share/classes/jdk/internal/loader/Loader.java index fbd16467da7..c4f9023482d 100644 --- a/src/java.base/share/classes/jdk/internal/loader/Loader.java +++ b/src/java.base/share/classes/jdk/internal/loader/Loader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package jdk.internal.loader; -import java.io.File; -import java.io.FilePermission; import java.io.IOException; import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; @@ -37,15 +35,8 @@ import java.net.URI; import java.net.URL; import java.nio.ByteBuffer; -import java.security.AccessControlContext; -import java.security.AccessController; import java.security.CodeSigner; import java.security.CodeSource; -import java.security.Permission; -import java.security.PermissionCollection; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.security.SecureClassLoader; import java.util.ArrayList; import java.util.Collection; @@ -110,16 +101,11 @@ public final class Loader extends SecureClassLoader { private final Map moduleToReader = new ConcurrentHashMap<>(); - // ACC used when loading classes and resources - @SuppressWarnings("removal") - private final AccessControlContext acc; - /** * A module defined/loaded to a {@code Loader}. */ private static class LoadedModule { private final ModuleReference mref; - private final URL url; // may be null private final CodeSource cs; LoadedModule(ModuleReference mref) { @@ -130,13 +116,11 @@ private static class LoadedModule { } catch (MalformedURLException | IllegalArgumentException e) { } } this.mref = mref; - this.url = url; this.cs = new CodeSource(url, (CodeSigner[]) null); } ModuleReference mref() { return mref; } String name() { return mref.descriptor().name(); } - URL location() { return url; } CodeSource codeSource() { return cs; } } @@ -145,7 +129,6 @@ private static class LoadedModule { * Creates a {@code Loader} in a loader pool that loads classes/resources * from one module. */ - @SuppressWarnings("removal") public Loader(ResolvedModule resolvedModule, LoaderPool pool, ClassLoader parent) @@ -164,8 +147,6 @@ public Loader(ResolvedModule resolvedModule, LoadedModule lm = new LoadedModule(mref); descriptor.packages().forEach(pn -> localPackageToModule.put(pn, lm)); this.localPackageToModule = localPackageToModule; - - this.acc = AccessController.getContext(); } /** @@ -175,7 +156,6 @@ public Loader(ResolvedModule resolvedModule, * @throws IllegalArgumentException * If two or more modules have the same package */ - @SuppressWarnings("removal") public Loader(Collection modules, ClassLoader parent) { super(parent); @@ -197,8 +177,6 @@ public Loader(Collection modules, ClassLoader parent) { } this.nameToModule = nameToModule; this.localPackageToModule = localPackageToModule; - - this.acc = AccessController.getContext(); } /** @@ -326,7 +304,6 @@ public LoaderPool pool() { * Returns a URL to a resource of the given name in a module defined to * this class loader. */ - @SuppressWarnings("removal") @Override protected URL findResource(String mn, String name) throws IOException { ModuleReference mref = (mn != null) ? nameToModule.get(mn) : null; @@ -335,41 +312,12 @@ protected URL findResource(String mn, String name) throws IOException { // locate resource URL url = null; - try { - url = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - @Override - public URL run() throws IOException { - Optional ouri = moduleReaderFor(mref).find(name); - if (ouri.isPresent()) { - try { - return ouri.get().toURL(); - } catch (MalformedURLException | - IllegalArgumentException e) { } - } - return null; - } - }); - } catch (PrivilegedActionException pae) { - throw (IOException) pae.getCause(); - } - - // check access with permissions restricted by ACC - if (url != null && System.getSecurityManager() != null) { + Optional ouri = moduleReaderFor(mref).find(name); + if (ouri.isPresent()) { try { - URL urlToCheck = url; - url = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - @Override - public URL run() throws IOException { - return URLClassPath.checkURL(urlToCheck); - } - }, acc); - } catch (PrivilegedActionException pae) { - url = null; - } + url = ouri.get().toURL(); + } catch (MalformedURLException | IllegalArgumentException e) { } } - return url; } @@ -525,15 +473,6 @@ protected Class findClass(String mn, String cn) { protected Class loadClass(String cn, boolean resolve) throws ClassNotFoundException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - String pn = packageName(cn); - if (!pn.isEmpty()) { - sm.checkPackageAccess(pn); - } - } - synchronized (getClassLoadingLock(cn)) { // check if already loaded Class c = findLoadedClass(cn); @@ -584,19 +523,7 @@ protected Class loadClass(String cn, boolean resolve) * * @return the resulting Class or {@code null} if not found */ - @SuppressWarnings("removal") private Class findClassInModuleOrNull(LoadedModule loadedModule, String cn) { - PrivilegedAction> pa = () -> defineClass(cn, loadedModule); - return AccessController.doPrivileged(pa, acc); - } - - /** - * Defines the given binary class name to the VM, loading the class - * bytes from the given module. - * - * @return the resulting Class or {@code null} if an I/O error occurs - */ - private Class defineClass(String cn, LoadedModule loadedModule) { ModuleReader reader = moduleReaderFor(loadedModule.mref()); try { @@ -620,40 +547,6 @@ private Class defineClass(String cn, LoadedModule loadedModule) { } } - - // -- permissions - - /** - * Returns the permissions for the given CodeSource. - */ - @Override - protected PermissionCollection getPermissions(CodeSource cs) { - PermissionCollection perms = super.getPermissions(cs); - - URL url = cs.getLocation(); - if (url == null) - return perms; - - // add the permission to access the resource - try { - Permission p = url.openConnection().getPermission(); - if (p != null) { - // for directories then need recursive access - if (p instanceof FilePermission) { - String path = p.getName(); - if (path.endsWith(File.separator)) { - path += "-"; - p = new FilePermission(path, "read"); - } - } - perms.add(p); - } - } catch (IOException ioe) { } - - return perms; - } - - // -- miscellaneous supporting methods /** diff --git a/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java b/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java index 64a3813a914..02dc79f0288 100644 --- a/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java +++ b/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,25 +114,17 @@ public long find(String name) { * @param file the path of the native library * @throws UnsatisfiedLinkError if any error in loading the native library */ - @SuppressWarnings("removal") public NativeLibrary loadLibrary(Class fromClass, File file) { // Check to see if we're attempting to access a static library String name = findBuiltinLib(file.getName()); boolean isBuiltin = (name != null); if (!isBuiltin) { - name = AccessController.doPrivileged(new PrivilegedAction<>() { - public String run() { - try { - if (loadLibraryOnlyIfPresent && !file.exists()) { - return null; - } - return file.getCanonicalPath(); - } catch (IOException e) { - return null; - } - } - }); - if (name == null) { + try { + if (loadLibraryOnlyIfPresent && !file.exists()) { + return null; + } + name = file.getCanonicalPath(); + } catch (IOException e) { return null; } } diff --git a/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java b/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java index 35ed4701c99..fa4c1390c1a 100644 --- a/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java +++ b/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,6 @@ import java.io.IOException; import java.lang.invoke.MethodHandles; import java.nio.file.Path; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -78,18 +76,11 @@ public static RawNativeLibraries newInstance(MethodHandles.Lookup trustedCaller) * * @param path the path of the native library */ - @SuppressWarnings("removal") public NativeLibrary load(Path path) { - String name = AccessController.doPrivileged(new PrivilegedAction<>() { - public String run() { - try { - return path.toRealPath().toString(); - } catch (IOException e) { - return null; - } - } - }); - if (name == null) { + String name; + try { + name = path.toRealPath().toString(); + } catch (IOException e) { return null; } return load(name); diff --git a/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java b/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java index 297c77bc106..75418111f74 100644 --- a/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java +++ b/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java @@ -39,13 +39,7 @@ import java.net.URLConnection; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; -import java.security.AccessControlContext; -import java.security.AccessControlException; -import java.security.AccessController; import java.security.CodeSigner; -import java.security.Permission; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.security.cert.Certificate; import java.util.ArrayDeque; import java.util.ArrayList; @@ -70,7 +64,6 @@ import jdk.internal.access.SharedSecrets; import sun.net.util.URLUtil; import sun.net.www.ParseUtil; -import sun.security.action.GetPropertyAction; /** * This class is used to maintain a search path of URLs for loading classes @@ -83,20 +76,16 @@ public class URLClassPath { private static final String JAVA_VERSION; private static final boolean DEBUG; private static final boolean DISABLE_JAR_CHECKING; - private static final boolean DISABLE_ACC_CHECKING; private static final boolean DISABLE_CP_URL_CHECK; private static final boolean DEBUG_CP_URL_CHECK; static { - Properties props = GetPropertyAction.privilegedGetProperties(); + Properties props = System.getProperties(); JAVA_VERSION = props.getProperty("java.version"); DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null); String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking"); DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.isEmpty() : false; - p = props.getProperty("jdk.net.URLClassPath.disableRestrictedPermissions"); - DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.isEmpty() : false; - // This property will be removed in a later release p = props.getProperty("jdk.net.URLClassPath.disableClassPathURLCheck"); DISABLE_CP_URL_CHECK = p != null ? p.equals("true") || p.isEmpty() : false; @@ -125,12 +114,6 @@ public class URLClassPath { /* Whether this URLClassLoader has been closed yet */ private boolean closed = false; - /* The context to be used when loading classes and resources. If non-null - * this is the context that was captured during the creation of the - * URLClassLoader. null implies no additional security restrictions. */ - @SuppressWarnings("removal") - private final AccessControlContext acc; - /** * Creates a new URLClassPath for the given URLs. The URLs will be * searched in the order specified for classes and resources. A URL @@ -140,12 +123,9 @@ public class URLClassPath { * @param urls the directory and JAR file URLs to search for classes * and resources * @param factory the URLStreamHandlerFactory to use when creating new URLs - * @param acc the context to be used when loading classes and resources, may - * be null */ public URLClassPath(URL[] urls, - URLStreamHandlerFactory factory, - @SuppressWarnings("removal") AccessControlContext acc) { + URLStreamHandlerFactory factory) { ArrayList path = new ArrayList<>(urls.length); ArrayDeque unopenedUrls = new ArrayDeque<>(urls.length); for (URL url : urls) { @@ -160,14 +140,10 @@ public URLClassPath(URL[] urls, } else { jarHandler = null; } - if (DISABLE_ACC_CHECKING) - this.acc = null; - else - this.acc = acc; } - public URLClassPath(URL[] urls, @SuppressWarnings("removal") AccessControlContext acc) { - this(urls, null, acc); + public URLClassPath(URL[] urls) { + this(urls, null); } /** @@ -209,7 +185,6 @@ public URLClassPath(URL[] urls, @SuppressWarnings("removal") AccessControlContex // the application class loader uses the built-in protocol handler to avoid protocol // handler lookup when opening JAR files on the class path. this.jarHandler = new sun.net.www.protocol.jar.Handler(); - this.acc = null; } public synchronized List closeLoaders() { @@ -279,17 +254,16 @@ public URL[] getURLs() { /** * Finds the resource with the specified name on the URL search path - * or null if not found or security check fails. + * or null if not found. * * @param name the name of the resource - * @param check whether to perform a security check * @return a {@code URL} for the resource, or {@code null} * if the resource could not be found. */ - public URL findResource(String name, boolean check) { + public URL findResource(String name) { Loader loader; for (int i = 0; (loader = getLoader(i)) != null; i++) { - URL url = loader.findResource(name, check); + URL url = loader.findResource(name); if (url != null) { return url; } @@ -297,29 +271,6 @@ public URL findResource(String name, boolean check) { return null; } - /** - * Finds the first Resource on the URL search path which has the specified - * name. Returns null if no Resource could be found. - * - * @param name the name of the Resource - * @param check whether to perform a security check - * @return the Resource, or null if not found - */ - public Resource getResource(String name, boolean check) { - if (DEBUG) { - System.err.println("URLClassPath.getResource(\"" + name + "\")"); - } - - Loader loader; - for (int i = 0; (loader = getLoader(i)) != null; i++) { - Resource res = loader.getResource(name, check); - if (res != null) { - return res; - } - } - return null; - } - /** * Finds all resources on the URL search path with the given name. * Returns an enumeration of the URL objects. @@ -327,8 +278,7 @@ public Resource getResource(String name, boolean check) { * @param name the resource name * @return an Enumeration of all the urls having the specified name */ - public Enumeration findResources(final String name, - final boolean check) { + public Enumeration findResources(final String name) { return new Enumeration<>() { private int index = 0; private URL url = null; @@ -339,7 +289,7 @@ private boolean next() { } else { Loader loader; while ((loader = getLoader(index++)) != null) { - url = loader.findResource(name, check); + url = loader.findResource(name); if (url != null) { return true; } @@ -363,8 +313,26 @@ public URL nextElement() { }; } + /** + * Finds the first Resource on the URL search path which has the specified + * name. Returns null if no Resource could be found. + * + * @param name the name of the Resource + * @return the Resource, or null if not found + */ public Resource getResource(String name) { - return getResource(name, true); + if (DEBUG) { + System.err.println("URLClassPath.getResource(\"" + name + "\")"); + } + + Loader loader; + for (int i = 0; (loader = getLoader(i)) != null; i++) { + Resource res = loader.getResource(name); + if (res != null) { + return res; + } + } + return null; } /** @@ -374,8 +342,7 @@ public Resource getResource(String name) { * @param name the resource name * @return an Enumeration of all the resources having the specified name */ - public Enumeration getResources(final String name, - final boolean check) { + public Enumeration getResources(final String name) { return new Enumeration<>() { private int index = 0; private Resource res = null; @@ -386,7 +353,7 @@ private boolean next() { } else { Loader loader; while ((loader = getLoader(index++)) != null) { - res = loader.getResource(name, check); + res = loader.getResource(name); if (res != null) { return true; } @@ -410,10 +377,6 @@ public Resource nextElement() { }; } - public Enumeration getResources(final String name) { - return getResources(name, true); - } - /* * Returns the Loader at the specified position in the URL search * path. The URLs are opened and expanded as needed. Returns null @@ -455,17 +418,6 @@ private synchronized Loader getLoader(int index) { closeQuietly(loader); } continue; - } catch (SecurityException se) { - // log the error and close the unusable loader (if any). - // The context, if there is one, that this URLClassPath was - // given during construction will never have permission to access the URL. - if (DEBUG) { - System.err.println("Failed to access " + url + ", " + se ); - } - if (loader != null) { - closeQuietly(loader); - } - continue; } if (loaderClassPathURLs != null) { push(loaderClassPathURLs); @@ -491,34 +443,24 @@ private static void closeQuietly(final Loader loader) { /* * Returns the Loader for the specified base URL. */ - @SuppressWarnings("removal") private Loader getLoader(final URL url) throws IOException { - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction<>() { - public Loader run() throws IOException { - String protocol = url.getProtocol(); // lower cased in URL - String file = url.getFile(); - if (file != null && file.endsWith("/")) { - if ("file".equals(protocol)) { - return new FileLoader(url); - } else if ("jar".equals(protocol) && - isDefaultJarHandler(url) && - file.endsWith("!/")) { - // extract the nested URL - @SuppressWarnings("deprecation") - URL nestedUrl = new URL(file.substring(0, file.length() - 2)); - return new JarLoader(nestedUrl, jarHandler, acc); - } else { - return new Loader(url); - } - } else { - return new JarLoader(url, jarHandler, acc); - } - } - }, acc); - } catch (PrivilegedActionException pae) { - throw (IOException)pae.getException(); + String protocol = url.getProtocol(); // lower cased in URL + String file = url.getFile(); + if (file != null && file.endsWith("/")) { + if ("file".equals(protocol)) { + return new FileLoader(url); + } else if ("jar".equals(protocol) && + isDefaultJarHandler(url) && + file.endsWith("!/")) { + // extract the nested URL + @SuppressWarnings("deprecation") + URL nestedUrl = new URL(file.substring(0, file.length() - 2)); + return new JarLoader(nestedUrl, jarHandler); + } else { + return new Loader(url); + } + } else { + return new JarLoader(url, jarHandler); } } @@ -541,59 +483,6 @@ private void push(URL[] urls) { } } - /* - * Checks whether the resource URL should be returned. - * Returns null on security check failure. - * Called by java.net.URLClassLoader. - */ - public static URL checkURL(URL url) { - if (url != null) { - try { - check(url); - } catch (Exception e) { - return null; - } - } - return url; - } - - /* - * Checks whether the resource URL should be returned. - * Throws exception on failure. - * Called internally within this file. - */ - public static void check(URL url) throws IOException { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - URLConnection urlConnection = url.openConnection(); - Permission perm = urlConnection.getPermission(); - if (perm != null) { - try { - security.checkPermission(perm); - } catch (SecurityException se) { - // fallback to checkRead/checkConnect for pre 1.2 - // security managers - if ((perm instanceof java.io.FilePermission) && - perm.getActions().contains("read")) { - security.checkRead(perm.getName()); - } else if ((perm instanceof - java.net.SocketPermission) && - perm.getActions().contains("connect")) { - URL locUrl = url; - if (urlConnection instanceof JarURLConnection) { - locUrl = ((JarURLConnection)urlConnection).getJarFileURL(); - } - security.checkConnect(locUrl.getHost(), - locUrl.getPort()); - } else { - throw se; - } - } - } - } - } - /** * Nested class used to represent a loader of resources and classes * from a base URL. @@ -616,7 +505,7 @@ final URL getBaseURL() { return base; } - URL findResource(final String name, boolean check) { + URL findResource(final String name) { URL url; try { @SuppressWarnings("deprecation") @@ -626,10 +515,6 @@ URL findResource(final String name, boolean check) { } try { - if (check) { - URLClassPath.check(url); - } - /* * For a HTTP connection we use the HEAD method to * check if the resource exists. @@ -653,7 +538,11 @@ URL findResource(final String name, boolean check) { } } - Resource getResource(final String name, boolean check) { + /* + * Returns the Resource for the specified name, or null if not + * found. + */ + Resource getResource(final String name) { final URL url; try { @SuppressWarnings("deprecation") @@ -663,9 +552,6 @@ Resource getResource(final String name, boolean check) { } final URLConnection uc; try { - if (check) { - URLClassPath.check(url); - } uc = url.openConnection(); if (uc instanceof JarURLConnection) { @@ -693,15 +579,6 @@ public int getContentLength() throws IOException { }; } - /* - * Returns the Resource for the specified name, or null if not - * found or the caller does not have the permission to get the - * resource. - */ - Resource getResource(final String name) { - return getResource(name, true); - } - /* * Closes this loader and release all resources. * Method overridden in sub-classes. @@ -727,8 +604,6 @@ URL[] getClassPath() throws IOException { private static class JarLoader extends Loader { private JarFile jar; private final URL csu; - @SuppressWarnings("removal") - private final AccessControlContext acc; private boolean closed = false; private static final JavaUtilZipFileAccess zipAccess = SharedSecrets.getJavaUtilZipFileAccess(); @@ -737,14 +612,11 @@ private static class JarLoader extends Loader { * Creates a new JarLoader for the specified URL referring to * a JAR file. */ - private JarLoader(URL url, URLStreamHandler jarHandler, - @SuppressWarnings("removal") AccessControlContext acc) + private JarLoader(URL url, URLStreamHandler jarHandler) throws IOException { super(newURL("jar", "", -1, url + "!/", jarHandler)); csu = url; - this.acc = acc; - ensureOpen(); } @@ -770,24 +642,13 @@ private boolean isOptimizable(URL url) { return "file".equals(url.getProtocol()); } - @SuppressWarnings("removal") private void ensureOpen() throws IOException { if (jar == null) { - try { - AccessController.doPrivileged( - new PrivilegedExceptionAction<>() { - public Void run() throws IOException { - if (DEBUG) { - System.err.println("Opening " + csu); - Thread.dumpStack(); - } - jar = getJarFile(csu); - return null; - } - }, acc); - } catch (PrivilegedActionException pae) { - throw (IOException)pae.getException(); + if (DEBUG) { + System.err.println("Opening " + csu); + Thread.dumpStack(); } + jar = getJarFile(csu); } } @@ -826,11 +687,9 @@ private JarFile getJarFile(URL url) throws IOException { } /* - * Creates the resource and if the check flag is set to true, checks if - * is its okay to return the resource. + * Creates and returns the Resource. Returns null if the Resource couldn't be created. */ - Resource checkResource(final String name, boolean check, - final JarEntry entry) { + Resource createResource(final String name, final JarEntry entry) { final URL url; try { @@ -842,10 +701,7 @@ Resource checkResource(final String name, boolean check, } @SuppressWarnings("deprecation") var _unused = url = new URL(getBaseURL(), ParseUtil.encodePath(nm, false)); - if (check) { - URLClassPath.check(url); - } - } catch (@SuppressWarnings("removal") AccessControlException | IOException e) { + } catch (IOException e) { return null; } @@ -885,8 +741,8 @@ public byte[] getBytes() throws IOException { * Returns the URL for a resource with the specified name */ @Override - URL findResource(final String name, boolean check) { - Resource rsc = getResource(name, check); + URL findResource(final String name) { + Resource rsc = getResource(name); if (rsc != null) { return rsc.getURL(); } @@ -897,17 +753,16 @@ URL findResource(final String name, boolean check) { * Returns the JAR Resource for the specified name. */ @Override - Resource getResource(final String name, boolean check) { + Resource getResource(final String name) { try { ensureOpen(); } catch (IOException e) { throw new InternalError(e); } final JarEntry entry = jar.getJarEntry(name); - if (entry != null) - return checkResource(name, check, entry); - - + if (entry != null) { + return createResource(name, entry); + } return null; } @@ -1058,8 +913,8 @@ private FileLoader(URL url) throws IOException { * Returns the URL for a resource with the specified name */ @Override - URL findResource(final String name, boolean check) { - Resource rsc = getResource(name, check); + URL findResource(final String name) { + Resource rsc = getResource(name); if (rsc != null) { return rsc.getURL(); } @@ -1067,7 +922,7 @@ URL findResource(final String name, boolean check) { } @Override - Resource getResource(final String name, boolean check) { + Resource getResource(final String name) { final URL url; try { @SuppressWarnings("deprecation") @@ -1077,10 +932,6 @@ Resource getResource(final String name, boolean check) { // requested resource had ../..'s in path return null; } - - if (check) - URLClassPath.check(url); - final File file; if (name.contains("..")) { file = (new File(dir, name.replace('/', File.separatorChar))) diff --git a/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java b/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java index f6d868dfcc2..90113a4a271 100644 --- a/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java +++ b/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -217,7 +217,7 @@ private FDBigInteger(int[] data, int offset) { @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9'); @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1))); @*/ - public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) { + public FDBigInteger(long lValue, byte[] digits, int kDigits, int nDigits) { int n = Math.max((nDigits + 8) / 9, 2); // estimate size needed. data = new int[n]; // allocate enough space data[0] = (int) lValue; // starting value diff --git a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java index 408b98ac55a..dcfa9e88da2 100644 --- a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java +++ b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -1034,10 +1034,10 @@ public float floatValue() { static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter { boolean isNegative; int decExponent; - char digits[]; + byte[] digits; int nDigits; - ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n) + ASCIIToBinaryBuffer( boolean negSign, int decExponent, byte[] digits, int n) { this.isNegative = negSign; this.decExponent = decExponent; @@ -1872,7 +1872,7 @@ static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFor } } // look for and process decimal floating-point string - char[] digits = new char[ len ]; + byte[] digits = new byte[ len ]; boolean decSeen = false; int nDigits = 0; int decPt = 0; @@ -1903,10 +1903,10 @@ static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFor while (i < len) { c = in.charAt(i); if (c >= '1' && c <= '9') { - digits[nDigits++] = c; + digits[nDigits++] = (byte) c; nTrailZero = 0; } else if (c == '0') { - digits[nDigits++] = c; + digits[nDigits++] = (byte) c; nTrailZero++; } else if (c == '.') { if (decSeen) { diff --git a/src/java.base/share/classes/jdk/internal/misc/InternalLock.java b/src/java.base/share/classes/jdk/internal/misc/InternalLock.java deleted file mode 100644 index 822b64f74ca..00000000000 --- a/src/java.base/share/classes/jdk/internal/misc/InternalLock.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.internal.misc; - -import java.util.concurrent.locks.ReentrantLock; - -/** - * A reentrant mutual exclusion lock for internal use. The lock does not - * implement {@link java.util.concurrent.locks.Lock} or extend {@link - * java.util.concurrent.locks.ReentrantLock} so that it can be distinguished - * from lock objects accessible to subclasses of {@link java.io.Reader} and - * {@link java.io.Writer} (it is possible to create a Reader that uses a - * lock object of type ReentrantLock for example). - */ -public class InternalLock { - private static final boolean CAN_USE_INTERNAL_LOCK; - static { - String s = System.getProperty("jdk.io.useMonitors"); - if (s != null && s.equals("false")) { - CAN_USE_INTERNAL_LOCK = true; - } else { - CAN_USE_INTERNAL_LOCK = false; - } - } - - private final ReentrantLock lock; - - private InternalLock() { - this.lock = new ReentrantLock(); - } - - /** - * Returns a new InternalLock or null. - */ - public static InternalLock newLockOrNull() { - return (CAN_USE_INTERNAL_LOCK) ? new InternalLock() : null; - } - - /** - * Returns a new InternalLock or the given object. - */ - public static Object newLockOr(Object obj) { - return (CAN_USE_INTERNAL_LOCK) ? new InternalLock() : obj; - } - - public boolean tryLock() { - return lock.tryLock(); - } - - public void lock() { - lock.lock(); - } - - public void unlock() { - lock.unlock(); - } - - public boolean isHeldByCurrentThread() { - return lock.isHeldByCurrentThread(); - } -} 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 ec6b7591282..e69690f876f 100644 --- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -57,6 +57,11 @@ public final class Unsafe { private static native void registerNatives(); static { + runtimeSetup(); + } + + // Called from JVM when loading an AOT cache + private static void runtimeSetup() { registerNatives(); } diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java index 26cb12f484a..75b3b8fc993 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; +import java.lang.classfile.ClassFile; import java.lang.module.InvalidModuleDescriptorException; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Builder; @@ -189,6 +190,7 @@ private Attributes doRead(DataInput input) throws IOException { int minor_version = in.readUnsignedShort(); int major_version = in.readUnsignedShort(); + boolean isPreview = minor_version == ClassFile.PREVIEW_MINOR_VERSION; if (!VM.isSupportedModuleDescriptorVersion(major_version, minor_version)) { throw invalidModuleDescriptor("Unsupported major.minor version " + major_version + "." + minor_version); @@ -248,7 +250,7 @@ private Attributes doRead(DataInput input) throws IOException { switch (attribute_name) { case MODULE : - builder = readModuleAttribute(in, cpool, major_version); + builder = readModuleAttribute(in, cpool, major_version, isPreview); break; case MODULE_PACKAGES : @@ -344,7 +346,8 @@ private Attributes doRead(DataInput input) throws IOException { * Reads the Module attribute, returning the ModuleDescriptor.Builder to * build the corresponding ModuleDescriptor. */ - private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major) + private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major, + boolean isPreview) throws IOException { // module_name @@ -405,14 +408,23 @@ private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major) throw invalidModuleDescriptor("The requires entry for java.base" + " has ACC_SYNTHETIC set"); } + // requires transitive java.base is illegal unless: + // - the major version is 53 (JDK 9), or: + // - the classfile is a preview classfile, or: + // - the module is deemed to be participating in preview + // (i.e. the module is a java.* module) + // requires static java.base is illegal unless: + // - the major version is 53 (JDK 9), or: if (major >= 54 - && (mods.contains(Requires.Modifier.TRANSITIVE) + && ((mods.contains(Requires.Modifier.TRANSITIVE) + && !isPreview + && !"java.se".equals(mn)) || mods.contains(Requires.Modifier.STATIC))) { String flagName; - if (mods.contains(Requires.Modifier.TRANSITIVE)) { - flagName = "ACC_TRANSITIVE"; - } else { + if (mods.contains(Requires.Modifier.STATIC)) { flagName = "ACC_STATIC_PHASE"; + } else { + flagName = "ACC_TRANSITIVE"; } throw invalidModuleDescriptor("The requires entry for java.base" + " has " + flagName + " set"); diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java b/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java index a5ad79eb7c6..c87c039c133 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -370,14 +370,6 @@ static class ExplodedModuleReader implements ModuleReader { ExplodedModuleReader(Path dir) { this.dir = dir; - - // when running with a security manager then check that the caller - // has access to the directory. - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - boolean unused = Files.isDirectory(dir); - } } /** diff --git a/src/java.base/share/classes/jdk/internal/module/Modules.java b/src/java.base/share/classes/jdk/internal/module/Modules.java index 11ca2d5e521..3c3d148e196 100644 --- a/src/java.base/share/classes/jdk/internal/module/Modules.java +++ b/src/java.base/share/classes/jdk/internal/module/Modules.java @@ -32,8 +32,6 @@ import java.lang.module.ModuleReference; import java.lang.module.ResolvedModule; import java.net.URI; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collection; import java.util.List; import java.util.Map; @@ -155,10 +153,7 @@ public static void addUses(Module m, Class service) { public static void addProvides(Module m, Class service, Class impl) { ModuleLayer layer = m.getLayer(); - PrivilegedAction pa = m::getClassLoader; - @SuppressWarnings("removal") - ClassLoader loader = AccessController.doPrivileged(pa); - + ClassLoader loader = m.getClassLoader(); ClassLoader platformClassLoader = ClassLoaders.platformClassLoader(); if (layer == null || loader == null || loader == platformClassLoader) { // update ClassLoader catalog diff --git a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java index 74af7570d57..c520e6e636a 100644 --- a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java +++ b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,6 @@ import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Path; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayDeque; import java.util.Collections; import java.util.Deque; @@ -208,21 +206,7 @@ public static ModuleFinder ofSystem() { Path dir = Path.of(home, "modules"); if (!Files.isDirectory(dir)) throw new InternalError("Unable to detect the run-time image"); - ModuleFinder f = ModulePath.of(ModuleBootstrap.patcher(), dir); - return new ModuleFinder() { - @SuppressWarnings("removal") - @Override - public Optional find(String name) { - PrivilegedAction> pa = () -> f.find(name); - return AccessController.doPrivileged(pa); - } - @SuppressWarnings("removal") - @Override - public Set findAll() { - PrivilegedAction> pa = f::findAll; - return AccessController.doPrivileged(pa); - } - }; + return ModulePath.of(ModuleBootstrap.patcher(), dir); } /** @@ -314,7 +298,7 @@ static ModuleReference toModuleReference(ModuleDescriptor descriptor, Supplier readerSupplier = new Supplier<>() { @Override public ModuleReader get() { - return new SystemModuleReader(mn, uri); + return new SystemModuleReader(mn); } }; @@ -377,9 +361,7 @@ public byte[] generate(String algorithm) { } /** - * Holder class for the ImageReader - * - * @apiNote This class must be loaded before a security manager is set. + * Holder class for the ImageReader. */ private static class SystemImage { static final ImageReader READER = ImageReaderFactory.getImageReader(); @@ -396,25 +378,7 @@ private static class SystemModuleReader implements ModuleReader { private final String module; private volatile boolean closed; - /** - * If there is a security manager set then check permission to - * connect to the run-time image. - */ - private static void checkPermissionToConnect(URI uri) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - URLConnection uc = uri.toURL().openConnection(); - sm.checkPermission(uc.getPermission()); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - } - } - - SystemModuleReader(String module, URI uri) { - checkPermissionToConnect(uri); + SystemModuleReader(String module) { this.module = module; } diff --git a/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java b/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java index b0d9c7154cd..687e32cdf61 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java +++ b/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java @@ -29,6 +29,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; +import java.io.ObjectStreamField; import java.io.OptionalDataException; import java.io.Serializable; import java.lang.invoke.MethodHandle; @@ -39,14 +40,14 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; import java.security.PrivilegedAction; -import java.util.Properties; +import java.util.Set; + import jdk.internal.access.JavaLangReflectAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.VM; import jdk.internal.vm.annotation.Stable; -import sun.security.action.GetPropertyAction; -import sun.security.util.SecurityConstants; /**

The master factory for all reflective objects, both those in java.lang.reflect (Fields, Methods, Constructors) as well as their @@ -69,6 +70,7 @@ public class ReflectionFactory { private static volatile Method hasStaticInitializerMethod; private final JavaLangReflectAccess langReflectAccess; + private ReflectionFactory() { this.langReflectAccess = SharedSecrets.getJavaLangReflectAccess(); } @@ -93,27 +95,12 @@ public ReflectionFactory run() { * Provides the caller with the capability to instantiate reflective * objects. * - *

First, if there is a security manager, its - * checkPermission method is called with a {@link - * java.lang.RuntimePermission} with target - * "reflectionFactoryAccess". This may result in a - * security exception. - * *

The returned ReflectionFactory object should be * carefully guarded by the caller, since it can be used to read and * write private data and invoke private methods, as well as to load * unverified bytecodes. It must never be passed to untrusted code. - * - * @exception SecurityException if a security manager exists and its - * checkPermission method doesn't allow - * access to the RuntimePermission "reflectionFactoryAccess". */ + */ public static ReflectionFactory getReflectionFactory() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission( - SecurityConstants.REFLECTION_FACTORY_ACCESS_PERMISSION); - } return soleInstance; } @@ -381,6 +368,46 @@ private final MethodHandle findReadWriteObjectForSerialization(Class cl, } } + public final MethodHandle defaultReadObjectForSerialization(Class cl) { + if (hasDefaultOrNoSerialization(cl)) { + return null; + } + + return SharedSecrets.getJavaObjectStreamReflectionAccess().defaultReadObject(cl); + } + + public final MethodHandle defaultWriteObjectForSerialization(Class cl) { + if (hasDefaultOrNoSerialization(cl)) { + return null; + } + + return SharedSecrets.getJavaObjectStreamReflectionAccess().defaultWriteObject(cl); + } + + /** + * These are specific leaf classes which appear to be Serializable, but which + * have special semantics according to the serialization specification. We + * could theoretically include array classes here, but it is easier and clearer + * to just use `Class#isArray` instead. + */ + private static final Set> nonSerializableLeafClasses = Set.of( + Class.class, + String.class, + ObjectStreamClass.class + ); + + private static boolean hasDefaultOrNoSerialization(Class cl) { + return ! Serializable.class.isAssignableFrom(cl) + || cl.isInterface() + || cl.isArray() + || Proxy.isProxyClass(cl) + || Externalizable.class.isAssignableFrom(cl) + || cl.isEnum() + || cl.isRecord() + || cl.isHidden() + || nonSerializableLeafClasses.contains(cl); + } + /** * Returns a MethodHandle for {@code writeReplace} on the serializable class * or null if no match found. @@ -486,6 +513,28 @@ public final Constructor newOptionalDataExceptionForSeria } } + public final ObjectStreamField[] serialPersistentFields(Class cl) { + if (! Serializable.class.isAssignableFrom(cl) || cl.isInterface() || cl.isEnum()) { + return null; + } + + try { + Field field = cl.getDeclaredField("serialPersistentFields"); + int mods = field.getModifiers(); + if (! (Modifier.isStatic(mods) && Modifier.isPrivate(mods) && Modifier.isFinal(mods))) { + return null; + } + if (field.getType() != ObjectStreamField[].class) { + return null; + } + field.setAccessible(true); + ObjectStreamField[] array = (ObjectStreamField[]) field.get(null); + return array != null && array.length > 0 ? array.clone() : array; + } catch (ReflectiveOperationException e) { + return null; + } + } + //-------------------------------------------------------------------------- // // Internals only below this point @@ -549,11 +598,10 @@ private static Config config() { private static Config loadConfig() { assert VM.isModuleSystemInited(); - Properties props = GetPropertyAction.privilegedGetProperties(); boolean useNativeAccessorOnly = - "true".equals(props.getProperty("jdk.reflect.useNativeAccessorOnly")); + "true".equals(System.getProperty("jdk.reflect.useNativeAccessorOnly")); boolean disableSerialConstructorChecks = - "true".equals(props.getProperty("jdk.disableSerialConstructorChecks")); + "true".equals(System.getProperty("jdk.disableSerialConstructorChecks")); return new Config(useNativeAccessorOnly, disableSerialConstructorChecks); } @@ -575,5 +623,4 @@ private static boolean packageEquals(Class cl1, Class cl2) { return cl1.getClassLoader() == cl2.getClassLoader() && cl1.getPackageName() == cl2.getPackageName(); } - } diff --git a/src/java.base/share/classes/jdk/internal/util/ClassFileDumper.java b/src/java.base/share/classes/jdk/internal/util/ClassFileDumper.java index b104b56ac0e..83dafb6b49c 100644 --- a/src/java.base/share/classes/jdk/internal/util/ClassFileDumper.java +++ b/src/java.base/share/classes/jdk/internal/util/ClassFileDumper.java @@ -29,8 +29,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HexFormat; import java.util.Objects; import java.util.Set; @@ -79,10 +77,6 @@ public static ClassFileDumper getInstance(String key, String path) { private final AtomicInteger counter = new AtomicInteger(); private ClassFileDumper(String key, String path) { - /* - * GetPropertyAction.privilegedGetProperty cannot be used here, Using VM.getSavedProperty to avoid a bootstrap - * circularity issue in the java/lang/String/concat/WithSecurityManager.java test - */ String value = VM.getSavedProperty(key); this.key = key; boolean enabled = value != null && value.isEmpty() ? true : Boolean.parseBoolean(value); @@ -132,50 +126,39 @@ public void dumpFailedClass(String name, byte[] bytes) { write(pathname(name + ".failed-" + counter.incrementAndGet()), bytes); } - @SuppressWarnings("removal") private void write(Path path, byte[] bytes) { - AccessController.doPrivileged(new PrivilegedAction<>() { - @Override public Void run() { - try { - Files.createDirectories(path.getParent()); - Files.write(path, bytes); - } catch (Exception ex) { - if (VM.isModuleSystemInited()) { - // log only when lambda is ready to use - System.getLogger(ClassFileDumper.class.getName()) - .log(System.Logger.Level.WARNING, "Exception writing to " + - path + " " + ex.getMessage()); - } - // simply don't care if this operation failed - } - return null; - }}); + try { + Files.createDirectories(path.getParent()); + Files.write(path, bytes); + } catch (Exception ex) { + if (VM.isModuleSystemInited()) { + // log only when lambda is ready to use + System.getLogger(ClassFileDumper.class.getName()) + .log(System.Logger.Level.WARNING, "Exception writing to " + + path + " " + ex.getMessage()); + } + // simply don't care if this operation failed + } } /* * Validate if the given dir is a writeable directory if exists. */ - @SuppressWarnings("removal") private static Path validateDumpDir(String dir) { - return AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Path run() { - Path path = Path.of(dir); - if (Files.notExists(path)) { - try { - Files.createDirectories(path); - } catch (IOException ex) { - throw new IllegalArgumentException("Fail to create " + path, ex); - } - } - if (!Files.isDirectory(path)) { - throw new IllegalArgumentException("Path " + path + " is not a directory"); - } else if (!Files.isWritable(path)) { - throw new IllegalArgumentException("Directory " + path + " is not writable"); - } - return path; + Path path = Path.of(dir); + if (Files.notExists(path)) { + try { + Files.createDirectories(path); + } catch (IOException ex) { + throw new IllegalArgumentException("Fail to create " + path, ex); } - }); + } + if (!Files.isDirectory(path)) { + throw new IllegalArgumentException("Path " + path + " is not a directory"); + } else if (!Files.isWritable(path)) { + throw new IllegalArgumentException("Directory " + path + " is not writable"); + } + return path; } private static final HexFormat HEX = HexFormat.of().withUpperCase(); diff --git a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java index 9dcebeca470..abe2dafa3b7 100644 --- a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java +++ b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java @@ -32,14 +32,11 @@ * Read-only access to System property values initialized during Phase 1 * are cached. Setting, clearing, or modifying the value using * {@link System#setProperty} or {@link System#getProperties()} is ignored. - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in these access methods. The caller of these methods should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public final class StaticProperty { // The class static initialization is triggered to initialize these final - // fields during init Phase 1 and before a security manager is set. + // fields during init Phase 1. private static final String JAVA_HOME; private static final String USER_HOME; private static final String USER_DIR; @@ -143,10 +140,6 @@ private static String getProperty(Properties props, String key, /** * {@return the {@code java.home} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String javaHome() { return JAVA_HOME; @@ -154,10 +147,6 @@ public static String javaHome() { /** * {@return the {@code user.home} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String userHome() { return USER_HOME; @@ -165,10 +154,6 @@ public static String userHome() { /** * {@return the {@code user.dir} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String userDir() { return USER_DIR; @@ -176,10 +161,6 @@ public static String userDir() { /** * {@return the {@code user.name} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String userName() { return USER_NAME; @@ -187,10 +168,6 @@ public static String userName() { /** * {@return the {@code java.library.path} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String javaLibraryPath() { return JAVA_LIBRARY_PATH; @@ -198,10 +175,6 @@ public static String javaLibraryPath() { /** * {@return the {@code java.io.tmpdir} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String javaIoTmpDir() { return JAVA_IO_TMPDIR; @@ -209,10 +182,6 @@ public static String javaIoTmpDir() { /** * {@return the {@code sun.boot.library.path} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String sunBootLibraryPath() { return SUN_BOOT_LIBRARY_PATH; @@ -221,10 +190,6 @@ public static String sunBootLibraryPath() { /** * {@return the {@code jdk.serialFilter} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String jdkSerialFilter() { return JDK_SERIAL_FILTER; @@ -233,10 +198,6 @@ public static String jdkSerialFilter() { /** * {@return the {@code jdk.serialFilterFactory} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String jdkSerialFilterFactory() { return JDK_SERIAL_FILTER_FACTORY; @@ -244,10 +205,6 @@ public static String jdkSerialFilterFactory() { /** * {@return the {@code native.encoding} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String nativeEncoding() { return NATIVE_ENCODING; @@ -255,10 +212,6 @@ public static String nativeEncoding() { /** * {@return the {@code file.encoding} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String fileEncoding() { return FILE_ENCODING; @@ -266,9 +219,6 @@ public static String fileEncoding() { /** * {@return the {@code java.properties.date} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. */ public static String javaPropertiesDate() { return JAVA_PROPERTIES_DATE; @@ -276,10 +226,6 @@ public static String javaPropertiesDate() { /** * {@return the {@code sun.jnu.encoding} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String jnuEncoding() { return SUN_JNU_ENCODING; @@ -287,10 +233,6 @@ public static String jnuEncoding() { /** * {@return the {@code java.locale.useOldISOCodes} system property} - * - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. The caller of this method should take care to ensure - * that the returned property is not made accessible to untrusted code. */ public static String javaLocaleUseOldISOCodes() { return JAVA_LOCALE_USE_OLD_ISO_CODES; @@ -298,8 +240,6 @@ public static String javaLocaleUseOldISOCodes() { /** * {@return the {@code os.name} system property} - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. This property is not considered security sensitive. */ public static String osName() { return OS_NAME; @@ -307,8 +247,6 @@ public static String osName() { /** * {@return the {@code os.arch} system property} - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. This property is not considered security sensitive. */ public static String osArch() { return OS_ARCH; @@ -316,8 +254,6 @@ public static String osArch() { /** * {@return the {@code os.version} system property} - * {@link SecurityManager#checkPropertyAccess} is NOT checked - * in this method. This property is not considered security sensitive. */ public static String osVersion() { return OS_VERSION; diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java index 402be6b5dfe..71c4c8fbbbb 100644 --- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java @@ -725,11 +725,7 @@ public static float boundedNextFloat(RandomGenerator rng, float bound) { // The following decides which of two strategies initialSeed() will use. private static boolean secureRandomSeedRequested() { - @SuppressWarnings("removal") - String pp = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "java.util.secureRandomSeed")); - return (pp != null && pp.equalsIgnoreCase("true")); + return Boolean.getBoolean("java.util.secureRandomSeed"); } private static final boolean useSecureRandomSeed = secureRandomSeedRequested(); diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index f3b62c37fa8..828e0d41504 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -146,6 +146,8 @@ jdk.compiler; exports com.sun.security.ntlm to java.security.sasl; + exports jdk.internal to + jdk.incubator.vector; // Note: all modules in the exported list participate in preview features // and therefore if they use preview features they do not need to be // compiled with "--enable-preview". @@ -154,6 +156,7 @@ exports jdk.internal.javac to java.compiler, java.desktop, // for ScopedValue + java.se, // for ParticipatesInPreview jdk.compiler, jdk.incubator.vector, // participates in preview features jdk.jartool, // participates in preview features @@ -312,7 +315,6 @@ java.desktop; exports sun.reflect.misc to java.desktop, - java.datatransfer, java.management, java.management.rmi, java.rmi, 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 076d04632c9..850da5ef83d 100644 --- a/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java +++ b/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java @@ -311,8 +311,6 @@ public static boolean ensureTypeVisible(Class type, Class refc) { // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary // will record the first successful result. Unsuccessful results are not stored. // - // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary - // class loader about the binding of the proposed name (type.getName()). // The looked up type ("res") is compared for equality against the proposed // type ("type") and then is discarded. Thus, the worst that can happen to // the "child" class loader is that it is bothered to load and report a class @@ -320,17 +318,12 @@ public static boolean ensureTypeVisible(Class type, Class refc) { // memoization. And the caller never gets to look at the alternate type binding // ("res"), whether it exists or not. final String name = type.getName(); - @SuppressWarnings("removal") - Class res = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public Class run() { - try { - return Class.forName(name, false, refcLoader); - } catch (ClassNotFoundException | LinkageError e) { - return null; // Assume the class is not found - } - } - }); + Class res = null; + try { + res = Class.forName(name, false, refcLoader); + } catch (ClassNotFoundException | LinkageError e) { + // Assume the class is not found + } return (type == res); } diff --git a/src/java.base/share/classes/sun/net/ftp/FtpClient.java b/src/java.base/share/classes/sun/net/ftp/FtpClient.java index da0cffd3f20..970d095242c 100644 --- a/src/java.base/share/classes/sun/net/ftp/FtpClient.java +++ b/src/java.base/share/classes/sun/net/ftp/FtpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -234,8 +234,6 @@ public static FtpClient create(String dest) throws FtpProtocolException, IOExcep * @param dest the address of the destination server * @return this FtpClient * @throws IOException if connection failed. - * @throws SecurityException if there is a SecurityManager installed and it - * denied the authorization to connect to the destination. * @throws FtpProtocolException */ public abstract FtpClient connect(SocketAddress dest) throws FtpProtocolException, IOException; @@ -247,8 +245,6 @@ public static FtpClient create(String dest) throws FtpProtocolException, IOExcep * @param timeout the value, in milliseconds, to use as a connection timeout * @return this FtpClient * @throws IOException if connection failed. - * @throws SecurityException if there is a SecurityManager installed and it - * denied the authorization to connect to the destination. * @throws FtpProtocolException */ public abstract FtpClient connect(SocketAddress dest, int timeout) throws FtpProtocolException, IOException; diff --git a/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java b/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java index ad5d092aab1..94136d85f1d 100644 --- a/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java +++ b/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,6 @@ */ package sun.net.ftp; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ServiceConfigurationError; //import java.util.ServiceLoader; @@ -50,16 +48,8 @@ public abstract class FtpClientProvider { /** * Initializes a new instance of this class. - * - * @throws SecurityException if a security manager is installed and it denies - * {@link RuntimePermission}{@code ("ftpClientProvider")} */ protected FtpClientProvider() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("ftpClientProvider")); - } } private static boolean loadProviderFromProperty() { @@ -74,8 +64,7 @@ private static boolean loadProviderFromProperty() { return true; } catch (ClassNotFoundException | IllegalAccessException | - InstantiationException | - SecurityException x) { + InstantiationException x) { throw new ServiceConfigurationError(x.toString()); } } @@ -135,26 +124,19 @@ private static boolean loadProviderAsService() { * * @return The system-wide default FtpClientProvider */ - @SuppressWarnings("removal") public static FtpClientProvider provider() { synchronized (lock) { if (provider != null) { return provider; } - return (FtpClientProvider) AccessController.doPrivileged( - new PrivilegedAction() { - - public Object run() { - if (loadProviderFromProperty()) { - return provider; - } - if (loadProviderAsService()) { - return provider; - } - provider = new sun.net.ftp.impl.DefaultFtpClientProvider(); - return provider; - } - }); + if (loadProviderFromProperty()) { + return provider; + } + if (loadProviderAsService()) { + return provider; + } + provider = new sun.net.ftp.impl.DefaultFtpClientProvider(); + return provider; } } } diff --git a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java index 8b6dd9c5ec7..bfc10028ae0 100644 --- a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java +++ b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java @@ -44,9 +44,6 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; import java.text.DateFormat; import java.time.ZoneOffset; import java.time.ZonedDateTime; @@ -133,31 +130,17 @@ public class FtpClient extends sun.net.ftp.FtpClient { private DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, java.util.Locale.US); private static final boolean acceptPasvAddressVal; static { - final int vals[] = {0, 0}; - final String acceptPasvAddress[] = {null}; - @SuppressWarnings("removal") - final String enc = AccessController.doPrivileged( - new PrivilegedAction() { - public String run() { - acceptPasvAddress[0] = System.getProperty("jdk.net.ftp.trustPasvAddress", "false"); - vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 300_000).intValue(); - vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 300_000).intValue(); - return System.getProperty("file.encoding", "ISO8859_1"); - } - }); - if (vals[0] == 0) { + defaultSoTimeout = Integer.getInteger("sun.net.client.defaultReadTimeout", 300_000).intValue(); + if (defaultSoTimeout == 0) { defaultSoTimeout = -1; - } else { - defaultSoTimeout = vals[0]; } - if (vals[1] == 0) { + defaultConnectTimeout = Integer.getInteger("sun.net.client.defaultConnectTimeout", 300_000).intValue(); + if (defaultConnectTimeout == 0) { defaultConnectTimeout = -1; - } else { - defaultConnectTimeout = vals[1]; } - encoding = enc; + encoding = System.getProperty("file.encoding", "ISO8859_1"); try { if (!isASCIISuperset(encoding)) { encoding = "ISO8859_1"; @@ -171,7 +154,7 @@ public String run() { patterns[i] = Pattern.compile(patStrings[i]); } - acceptPasvAddressVal = Boolean.parseBoolean(acceptPasvAddress[0]); + acceptPasvAddressVal = Boolean.getBoolean("jdk.net.ftp.trustPasvAddress"); } /** @@ -662,10 +645,7 @@ private Socket openPassiveDataConnection(String cmd) throws sun.net.ftp.FtpProto Socket s; if (proxy != null) { if (proxy.type() == Proxy.Type.SOCKS) { - PrivilegedAction pa = () -> new Socket(proxy); - @SuppressWarnings("removal") - var tmp = AccessController.doPrivileged(pa); - s = tmp; + s = new Socket(proxy); } else { s = new Socket(Proxy.NO_PROXY); } @@ -673,9 +653,7 @@ private Socket openPassiveDataConnection(String cmd) throws sun.net.ftp.FtpProto s = new Socket(); } - PrivilegedAction pa = () -> server.getLocalAddress(); - @SuppressWarnings("removal") - InetAddress serverAddress = AccessController.doPrivileged(pa); + InetAddress serverAddress = server.getLocalAddress(); // Bind the socket to the same address as the control channel. This // is needed in case of multi-homed systems. @@ -761,11 +739,8 @@ private InetSocketAddress validatePasvAddress(int port, String s, InetAddress ad } private static InetAddress privilegedLocalHost() throws FtpProtocolException { - PrivilegedExceptionAction action = InetAddress::getLocalHost; try { - @SuppressWarnings("removal") - var tmp = AccessController.doPrivileged(action); - return tmp; + return InetAddress.getLocalHost(); } catch (Exception e) { var ftpEx = new FtpProtocolException(ERROR_MSG); ftpEx.initCause(e); @@ -774,11 +749,8 @@ private static InetAddress privilegedLocalHost() throws FtpProtocolException { } private static InetAddress[] privilegedGetAllByName(String hostName) throws FtpProtocolException { - PrivilegedExceptionAction pAction = () -> InetAddress.getAllByName(hostName); try { - @SuppressWarnings("removal") - var tmp =AccessController.doPrivileged(pAction); - return tmp; + return InetAddress.getAllByName(hostName); } catch (Exception e) { var ftpEx = new FtpProtocolException(ERROR_MSG); ftpEx.initCause(e); @@ -1021,10 +993,7 @@ private Socket doConnect(InetSocketAddress dest, int timeout) throws IOException Socket s; if (proxy != null) { if (proxy.type() == Proxy.Type.SOCKS) { - PrivilegedAction pa = () -> new Socket(proxy); - @SuppressWarnings("removal") - var tmp = AccessController.doPrivileged(pa); - s = tmp; + s = new Socket(proxy); } else { s = new Socket(Proxy.NO_PROXY); } diff --git a/src/java.base/share/classes/sun/net/smtp/SmtpClient.java b/src/java.base/share/classes/sun/net/smtp/SmtpClient.java index 59c60ce70dc..494bcf19987 100644 --- a/src/java.base/share/classes/sun/net/smtp/SmtpClient.java +++ b/src/java.base/share/classes/sun/net/smtp/SmtpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, 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,7 +28,6 @@ import java.io.*; import java.net.*; import sun.net.TransferProtocolClient; -import sun.security.action.GetPropertyAction; /** * This class implements the SMTP client. @@ -167,7 +166,7 @@ public SmtpClient (String host) throws IOException { } try { String s; - mailhost = GetPropertyAction.privilegedGetProperty("mail.host"); + mailhost = System.getProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return; @@ -193,7 +192,7 @@ public SmtpClient(int to) throws IOException { setConnectTimeout(to); try { String s; - mailhost = GetPropertyAction.privilegedGetProperty("mail.host"); + mailhost = System.getProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return; diff --git a/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java b/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java index c944bef91e7..763b176331e 100644 --- a/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java +++ b/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -33,8 +33,6 @@ import java.util.Collections; import java.util.List; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Locale; import java.util.StringJoiner; import java.util.regex.Pattern; @@ -93,26 +91,15 @@ public class DefaultProxySelector extends ProxySelector { static { final String key = "java.net.useSystemProxies"; - @SuppressWarnings("removal") - Boolean b = AccessController.doPrivileged( - new PrivilegedAction() { - public Boolean run() { - return NetProperties.getBoolean(key); - }}); + Boolean b = NetProperties.getBoolean(key); if (b != null && b.booleanValue()) { jdk.internal.loader.BootLoader.loadLibrary("net"); hasSystemProxies = init(); } } - @SuppressWarnings("removal") public static int socksProxyVersion() { - return AccessController.doPrivileged( - new PrivilegedAction() { - @Override public Integer run() { - return NetProperties.getInteger(SOCKS_PROXY_VERSION, 5); - } - }); + return NetProperties.getInteger(SOCKS_PROXY_VERSION, 5); } /** @@ -187,148 +174,133 @@ public java.util.List select(URI uri) { throw new IllegalArgumentException("protocol = "+protocol+" host = "+host); } - NonProxyInfo pinfo = null; + NonProxyInfo nonProxyInfo = null; if ("http".equalsIgnoreCase(protocol)) { - pinfo = NonProxyInfo.httpNonProxyInfo; + nonProxyInfo = NonProxyInfo.httpNonProxyInfo; } else if ("https".equalsIgnoreCase(protocol)) { // HTTPS uses the same property as HTTP, for backward // compatibility - pinfo = NonProxyInfo.httpNonProxyInfo; + nonProxyInfo = NonProxyInfo.httpNonProxyInfo; } else if ("ftp".equalsIgnoreCase(protocol)) { - pinfo = NonProxyInfo.ftpNonProxyInfo; + nonProxyInfo = NonProxyInfo.ftpNonProxyInfo; } else if ("socket".equalsIgnoreCase(protocol)) { - pinfo = NonProxyInfo.socksNonProxyInfo; + nonProxyInfo = NonProxyInfo.socksNonProxyInfo; } - - /** - * Let's check the System properties for that protocol - */ - final String proto = protocol; - final NonProxyInfo nprop = pinfo; final String urlhost = host.toLowerCase(Locale.ROOT); - - /** - * This is one big doPrivileged call, but we're trying to optimize - * the code as much as possible. Since we're checking quite a few - * System properties it does help having only 1 call to doPrivileged. - * Be mindful what you do in here though! - */ - @SuppressWarnings("removal") - Proxy[] proxyArray = AccessController.doPrivileged( - new PrivilegedAction() { - public Proxy[] run() { - int i, j; - String phost = null; - int pport = 0; - String nphosts = null; - InetSocketAddress saddr = null; - - // Then let's walk the list of protocols in our array - for (i=0; i extensionMap = new Hashtable<>(); // Will be reset if in the platform-specific data file - @SuppressWarnings("removal") private static String tempFileTemplate = - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public String run() { - return System.getProperty("content.types.temp.file.template", - "/tmp/%s"); - } - }); + System.getProperty("content.types.temp.file.template", "/tmp/%s"); private static final String filePreamble = "sun.net.www MIME content-types table"; @@ -70,16 +63,10 @@ public String run() { private static class DefaultInstanceHolder { static final MimeTable defaultInstance = getDefaultInstance(); - @SuppressWarnings("removal") static MimeTable getDefaultInstance() { - return java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public MimeTable run() { - MimeTable instance = new MimeTable(); - URLConnection.setFileNameMap(instance); - return instance; - } - }); + final MimeTable instance = new MimeTable(); + URLConnection.setFileNameMap(instance); + return instance; } } @@ -235,20 +222,14 @@ public synchronized Enumeration elements() { // For backward compatibility -- mailcap format files // This is not currently used, but may in the future when we add ability // to read BOTH the properties format and the mailcap format. - @SuppressWarnings("removal") protected static String[] mailcapLocations = - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public String[] run() { - return new String[]{ - System.getProperty("user.mailcap"), - StaticProperty.userHome() + "/.mailcap", - "/etc/mailcap", - "/usr/etc/mailcap", - "/usr/local/etc/mailcap", - }; - } - }); + new String[]{ + System.getProperty("user.mailcap"), + StaticProperty.userHome() + "/.mailcap", + "/etc/mailcap", + "/usr/etc/mailcap", + "/usr/local/etc/mailcap" + }; public synchronized void load() { Properties entries = new Properties(); @@ -402,12 +383,6 @@ protected boolean saveAsProperties(File file) { Properties properties = getAsProperties(); properties.put("temp.file.template", tempFileTemplate); String tag; - // Perform the property security check for user.name - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPropertyAccess("user.name"); - } String user = StaticProperty.userName(); if (user != null) { tag = "; customized for " + user; diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java index 8083fb36f39..8bccc53cafc 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import java.util.Set; import sun.net.www.*; -import sun.security.action.GetPropertyAction; /** * This class is used to parse the information in WWW-Authenticate: and Proxy-Authenticate: @@ -98,7 +97,7 @@ public String toString() { } static { - String pref = GetPropertyAction.privilegedGetProperty("http.auth.preference"); + String pref = System.getProperty("http.auth.preference"); // http.auth.preference can be set to SPNEGO or Kerberos. // In fact they means "Negotiate with SPNEGO" and "Negotiate with diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java index 4a2b5b628c6..f567d7bd643 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package sun.net.www.protocol.http; -import java.io.IOException; -import java.io.ObjectInputStream; import java.net.PasswordAuthentication; import java.net.URL; import java.util.HashMap; @@ -67,10 +65,7 @@ public abstract class AuthenticationInfo extends AuthCacheValue implements Clone * repeatedly, via the Authenticator. Default is false, which means that this * behavior is switched off. */ - @SuppressWarnings("removal") - static final boolean serializeAuth = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "http.auth.serializeRequests")).booleanValue(); + static final boolean serializeAuth = Boolean.getBoolean("http.auth.serializeRequests"); /* AuthCacheValue: */ diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java index 73d5ff98b3a..f008c185b5d 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,11 +32,8 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; -import java.io.IOException; -import java.io.OutputStream; import java.util.Arrays; import java.util.Base64; -import java.util.Objects; import sun.net.www.HeaderParser; import sun.nio.cs.ISO_8859_1; import sun.nio.cs.UTF_8; @@ -49,10 +46,7 @@ */ -class BasicAuthentication extends AuthenticationInfo { - - @java.io.Serial - private static final long serialVersionUID = 100L; +final class BasicAuthentication extends AuthenticationInfo { /** The authentication string for this host, port, and realm. This is a simple BASE64 encoding of "login:password". */ diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java index faee05b4dfd..28d7bc5cf4e 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -35,17 +35,13 @@ import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; -import java.security.AccessController; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.PrivilegedAction; import java.security.Security; import java.text.Normalizer; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.Locale; -import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.function.BiConsumer; @@ -65,10 +61,7 @@ * @author Bill Foote */ -class DigestAuthentication extends AuthenticationInfo { - - @java.io.Serial - private static final long serialVersionUID = 100L; +final class DigestAuthentication extends AuthenticationInfo { private String authMethod; @@ -110,26 +103,15 @@ private static void processPropValue(String input, HttpURLConnection.getHttpLogger(); static { - @SuppressWarnings("removal") - Boolean b = AccessController.doPrivileged( - (PrivilegedAction) () -> NetProperties.getBoolean(compatPropName) - ); + Boolean b = NetProperties.getBoolean(compatPropName); delimCompatFlag = (b == null) ? false : b.booleanValue(); - @SuppressWarnings("removal") - String secprops = AccessController.doPrivileged( - (PrivilegedAction) () -> Security.getProperty(secPropName) - ); - + String secprops = Security.getProperty(secPropName); Set algs = new HashSet<>(); - // add the default insecure algorithms to set processPropValue(secprops, algs, (set, elem) -> set.add(elem)); - @SuppressWarnings("removal") - String netprops = AccessController.doPrivileged( - (PrivilegedAction) () -> NetProperties.get(enabledAlgPropName) - ); + String netprops = NetProperties.get(enabledAlgPropName); // remove any algorithms from disabled set that were opted-in by user processPropValue(netprops, algs, (set, elem) -> set.remove(elem)); disabledDigests = Set.copyOf(algs); diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 83511853502..602f798448c 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -25,7 +25,6 @@ package sun.net.www.protocol.http; -import java.security.PrivilegedAction; import java.util.Arrays; import java.net.URL; import java.net.URLConnection; @@ -37,7 +36,6 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.net.SocketTimeoutException; -import java.net.SocketPermission; import java.net.Proxy; import java.net.ProxySelector; import java.net.URI; @@ -47,11 +45,7 @@ import java.net.CacheResponse; import java.net.SecureCacheResponse; import java.net.CacheRequest; -import java.net.URLPermission; import java.net.Authenticator.RequestorType; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.security.PrivilegedActionException; import java.io.*; import java.util.ArrayList; import java.util.Collections; @@ -81,7 +75,6 @@ import java.net.MalformedURLException; import java.nio.ByteBuffer; import java.util.Objects; -import java.util.Properties; import java.util.concurrent.locks.ReentrantLock; import static sun.net.www.protocol.http.AuthScheme.BASIC; @@ -90,8 +83,6 @@ import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; import static sun.net.www.protocol.http.AuthScheme.KERBEROS; import static sun.net.www.protocol.http.AuthScheme.UNKNOWN; -import sun.security.action.GetIntegerAction; -import sun.security.action.GetPropertyAction; /** * A class to represent an HTTP connection to a remote object. @@ -178,8 +169,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * Restrict setting of request headers through the public api * consistent with JavaScript XMLHttpRequest2 with a few * exceptions. Disallowed headers are silently ignored for - * backwards compatibility reasons rather than throwing a - * SecurityException. For example, some applets set the + * backwards compatibility reasons. For example, some applets set the * Host header since old JREs did not implement HTTP 1.1. * Additionally, any header starting with Sec- is * disallowed. @@ -222,12 +212,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection { "Via" }; - @SuppressWarnings("removal") - private static String getNetProperty(String name) { - PrivilegedAction pa = () -> NetProperties.get(name); - return AccessController.doPrivileged(pa); - } - private static Set schemesListToSet(String list) { if (list == null || list.isEmpty()) return Collections.emptySet(); @@ -240,11 +224,9 @@ private static Set schemesListToSet(String list) { } static { - Properties props = GetPropertyAction.privilegedGetProperties(); - maxRedirects = GetIntegerAction.privilegedGetProperty( - "http.maxRedirects", defaultmaxRedirects); - version = props.getProperty("java.version"); - String agent = props.getProperty("http.agent"); + maxRedirects = Integer.getInteger("http.maxRedirects", defaultmaxRedirects); + version = System.getProperty("java.version"); + String agent = System.getProperty("http.agent"); if (agent == null) { agent = "Java/"+version; } else { @@ -254,34 +236,30 @@ private static Set schemesListToSet(String list) { // A set of net properties to control the use of authentication schemes // when proxying/tunneling. - String p = getNetProperty("jdk.http.auth.tunneling.disabledSchemes"); + String p = NetProperties.get("jdk.http.auth.tunneling.disabledSchemes"); disabledTunnelingSchemes = schemesListToSet(p); - p = getNetProperty("jdk.http.auth.proxying.disabledSchemes"); + p = NetProperties.get("jdk.http.auth.proxying.disabledSchemes"); disabledProxyingSchemes = schemesListToSet(p); - validateProxy = Boolean.parseBoolean( - props.getProperty("http.auth.digest.validateProxy")); - validateServer = Boolean.parseBoolean( - props.getProperty("http.auth.digest.validateServer")); + validateProxy = Boolean.getBoolean("http.auth.digest.validateProxy"); + validateServer = Boolean.getBoolean("http.auth.digest.validateServer"); - enableESBuffer = Boolean.parseBoolean( - props.getProperty("sun.net.http.errorstream.enableBuffering")); - int esBufferTimeout = GetIntegerAction.privilegedGetProperty( + enableESBuffer = Boolean.getBoolean("sun.net.http.errorstream.enableBuffering"); + int esBufferTimeout = Integer.getInteger( "sun.net.http.errorstream.timeout", 300); if (esBufferTimeout <= 0) { esBufferTimeout = 300; // use the default } timeout4ESBuffer = esBufferTimeout; - int esBufSize = GetIntegerAction.privilegedGetProperty( + int esBufSize = Integer.getInteger( "sun.net.http.errorstream.bufferSize", 4096); if (esBufSize <= 0) { esBufSize = 4096; // use the default } bufSize4ES = esBufSize; - allowRestrictedHeaders = Boolean.parseBoolean( - props.getProperty("sun.net.http.allowRestrictedHeaders")); + allowRestrictedHeaders = Boolean.getBoolean("sun.net.http.allowRestrictedHeaders"); if (!allowRestrictedHeaders) { restrictedHeaderSet = HashSet.newHashSet(restrictedHeaders.length); for (int i=0; i < restrictedHeaders.length; i++) { @@ -292,7 +270,7 @@ private static Set schemesListToSet(String list) { } int defMaxHeaderSize = 384 * 1024; - String maxHeaderSizeStr = getNetProperty("jdk.http.maxHeaderSize"); + String maxHeaderSizeStr = NetProperties.get("jdk.http.maxHeaderSize"); int maxHeaderSizeVal = defMaxHeaderSize; if (maxHeaderSizeStr != null) { try { @@ -439,9 +417,6 @@ public enum TunnelState { private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT; private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT; - /* A permission converted from a URLPermission */ - private SocketPermission socketPermission; - /* Logging support */ private static final PlatformLogger logger = PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); @@ -462,36 +437,30 @@ public final boolean isLockHeldByCurrentThread() { } /* - * privileged request password authentication + * Calls Authenticator.requestPasswordAuthentication * */ - @SuppressWarnings("removal") - private static PasswordAuthentication - privilegedRequestPasswordAuthentication( - final Authenticator authenticator, - final String host, - final InetAddress addr, - final int port, - final String protocol, - final String prompt, - final String scheme, - final URL url, - final RequestorType authType) { - return java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public PasswordAuthentication run() { - if (logger.isLoggable(PlatformLogger.Level.FINEST)) { - logger.finest("Requesting Authentication: host =" + host + " url = " + url); - } - PasswordAuthentication pass = Authenticator.requestPasswordAuthentication( - authenticator, host, addr, port, protocol, - prompt, scheme, url, authType); - if (logger.isLoggable(PlatformLogger.Level.FINEST)) { - logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null")); - } - return pass; - } - }); + private static PasswordAuthentication requestPassword( + final Authenticator authenticator, + final String host, + final InetAddress addr, + final int port, + final String protocol, + final String prompt, + final String scheme, + final URL url, + final RequestorType authType) { + + if (logger.isLoggable(PlatformLogger.Level.FINEST)) { + logger.finest("Requesting Authentication: host =" + host + " url = " + url); + } + PasswordAuthentication pass = Authenticator.requestPasswordAuthentication( + authenticator, host, addr, port, protocol, + prompt, scheme, url, authType); + if (logger.isLoggable(PlatformLogger.Level.FINEST)) { + logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null")); + } + return pass; } private boolean isRestrictedHeader(String key, String value) { @@ -640,7 +609,6 @@ private void writeRequests() throws IOException { if (requestLineIndex != 0) { // we expect the request line to be at index 0. we set it here // if we don't find the request line at that index. - checkURLFile(); requests.prepend(requestLine, null); } if (!getUseCaches()) { @@ -654,9 +622,7 @@ private void writeRequests() throws IOException { host += ":" + String.valueOf(port); } String reqHost = requests.findValue("Host"); - if (reqHost == null || - (!reqHost.equalsIgnoreCase(host) && !checkSetHost())) - { + if (reqHost == null || !reqHost.equalsIgnoreCase(host)) { requests.set("Host", host); } requests.setIfNotSet("Accept", acceptString); @@ -776,47 +742,6 @@ private void writeRequests() throws IOException { } } - private boolean checkSetHost() { - @SuppressWarnings("removal") - SecurityManager s = System.getSecurityManager(); - if (s != null) { - String name = s.getClass().getName(); - if (name.equals("sun.plugin2.applet.AWTAppletSecurityManager") || - name.equals("sun.plugin2.applet.FXAppletSecurityManager") || - name.equals("com.sun.javaws.security.JavaWebStartSecurity") || - name.equals("sun.plugin.security.ActivatorSecurityManager")) - { - int CHECK_SET_HOST = -2; - try { - s.checkConnect(url.toExternalForm(), CHECK_SET_HOST); - } catch (SecurityException ex) { - return false; - } - } - } - return true; - } - - private void checkURLFile() { - @SuppressWarnings("removal") - SecurityManager s = System.getSecurityManager(); - if (s != null) { - String name = s.getClass().getName(); - if (name.equals("sun.plugin2.applet.AWTAppletSecurityManager") || - name.equals("sun.plugin2.applet.FXAppletSecurityManager") || - name.equals("com.sun.javaws.security.JavaWebStartSecurity") || - name.equals("sun.plugin.security.ActivatorSecurityManager")) - { - int CHECK_SUBPATH = -3; - try { - s.checkConnect(url.toExternalForm(), CHECK_SUBPATH); - } catch (SecurityException ex) { - throw new SecurityException("denied access outside a permitted URL subpath", ex); - } - } - } - } - /** * Create a new HttpClient object, bypassing the cache of * HTTP client objects/connections. @@ -922,7 +847,6 @@ private static URL checkURL(URL u) throws IOException { return u; } - @SuppressWarnings("removal") protected HttpURLConnection(URL u, Proxy p, Handler handler) throws IOException { super(checkURL(u)); @@ -931,119 +855,8 @@ protected HttpURLConnection(URL u, Proxy p, Handler handler) userHeaders = new MessageHeader(); this.handler = handler; instProxy = p; - if (instProxy instanceof sun.net.ApplicationProxy) { - /* Application set Proxies should not have access to cookies - * in a secure environment unless explicitly allowed. */ - try { - cookieHandler = CookieHandler.getDefault(); - } catch (SecurityException se) { /* swallow exception */ } - } else { - cookieHandler = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public CookieHandler run() { - return CookieHandler.getDefault(); - } - }); - } - cacheHandler = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public ResponseCache run() { - return ResponseCache.getDefault(); - } - }); - } - - /** - * opens a stream allowing redirects only to the same host. - */ - public static InputStream openConnectionCheckRedirects(URLConnection c) - throws IOException - { - boolean redir; - int redirects = 0; - InputStream in; - Authenticator a = null; - - do { - if (c instanceof HttpURLConnection) { - ((HttpURLConnection) c).setInstanceFollowRedirects(false); - if (a == null) { - a = ((HttpURLConnection) c).authenticator; - } - } - - // We want to open the input stream before - // getting headers, because getHeaderField() - // et al swallow IOExceptions. - in = c.getInputStream(); - redir = false; - - if (c instanceof HttpURLConnection) { - HttpURLConnection http = (HttpURLConnection) c; - int stat = http.getResponseCode(); - if (stat >= 300 && stat <= 307 && stat != 306 && - stat != HttpURLConnection.HTTP_NOT_MODIFIED) { - URL base = http.getURL(); - String loc = http.getHeaderField("Location"); - URL target = null; - if (loc != null) { - target = newURL(base, loc); - } - http.disconnect(); - if (target == null - || !base.getProtocol().equals(target.getProtocol()) - || base.getPort() != target.getPort() - || !hostsEqual(base, target) - || redirects >= 5) - { - throw new SecurityException("illegal URL redirect"); - } - redir = true; - c = target.openConnection(); - if (a != null && c instanceof HttpURLConnection) { - ((HttpURLConnection)c).setAuthenticator(a); - } - redirects++; - } - } - } while (redir); - return in; - } - - - // - // Same as java.net.URL.hostsEqual - // - @SuppressWarnings("removal") - private static boolean hostsEqual(URL u1, URL u2) { - final String h1 = u1.getHost(); - final String h2 = u2.getHost(); - - if (h1 == null) { - return h2 == null; - } else if (h2 == null) { - return false; - } else if (h1.equalsIgnoreCase(h2)) { - return true; - } - // Have to resolve addresses before comparing, otherwise - // names like tachyon and tachyon.eng would compare different - final boolean result[] = {false}; - - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public Void run() { - try { - InetAddress a1 = InetAddress.getByName(h1); - InetAddress a2 = InetAddress.getByName(h2); - result[0] = a1.equals(a2); - } catch(UnknownHostException | SecurityException e) { - } - return null; - } - }); - - return result[0]; + cookieHandler = CookieHandler.getDefault(); + cacheHandler = ResponseCache.getDefault(); } // overridden in HTTPS subclass @@ -1073,34 +886,6 @@ private boolean checkReuseConnection () { return false; } - @SuppressWarnings("removal") - private String getHostAndPort(URL url) { - String host = url.getHost(); - final String hostarg = host; - try { - // lookup hostname and use IP address if available - host = AccessController.doPrivileged( - new PrivilegedExceptionAction<>() { - public String run() throws IOException { - InetAddress addr = InetAddress.getByName(hostarg); - return addr.getHostAddress(); - } - } - ); - } catch (PrivilegedActionException e) {} - int port = url.getPort(); - if (port == -1) { - String scheme = url.getProtocol(); - if ("http".equals(scheme)) { - return host + ":80"; - } else { // scheme must be https - return host + ":443"; - } - } - return host + ":" + Integer.toString(port); - } - - @SuppressWarnings("removal") protected void plainConnect() throws IOException { lock(); try { @@ -1110,66 +895,7 @@ protected void plainConnect() throws IOException { } finally { unlock(); } - SocketPermission p = URLtoSocketPermission(this.url); - if (p != null) { - try { - AccessController.doPrivilegedWithCombiner( - new PrivilegedExceptionAction<>() { - public Void run() throws IOException { - plainConnect0(); - return null; - } - }, null, p - ); - } catch (PrivilegedActionException e) { - throw (IOException) e.getException(); - } - } else { - // run without additional permission - plainConnect0(); - } - } - - /** - * if the caller has a URLPermission for connecting to the - * given URL, then return a SocketPermission which permits - * access to that destination. Return null otherwise. The permission - * is cached in a field (which can only be changed by redirects) - */ - SocketPermission URLtoSocketPermission(URL url) throws IOException { - - if (socketPermission != null) { - return socketPermission; - } - - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - - if (sm == null) { - return null; - } - - // the permission, which we might grant - - SocketPermission newPerm = new SocketPermission( - getHostAndPort(url), "connect" - ); - - String actions = getRequestMethod()+":" + - getUserSetHeaders().getHeaderNamesInList(); - - String urlstring = url.getProtocol() + "://" + url.getAuthority() - + url.getPath(); - - URLPermission p = new URLPermission(urlstring, actions); - try { - sm.checkPermission(p); - socketPermission = newPerm; - return socketPermission; - } catch (SecurityException e) { - // fall thru - } - return null; + plainConnect0(); } protected void plainConnect0() throws IOException { @@ -1215,14 +941,7 @@ protected void plainConnect0() throws IOException { /** * Do we have to use a proxy? */ - @SuppressWarnings("removal") - ProxySelector sel = - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public ProxySelector run() { - return ProxySelector.getDefault(); - } - }); + final ProxySelector sel = ProxySelector.getDefault(); if (sel != null) { URI uri = sun.net.www.ParseUtil.toURI(url); if (logger.isLoggable(PlatformLogger.Level.FINEST)) { @@ -1399,29 +1118,12 @@ private void expect100Continue() throws IOException { * - get input, [read input,] get output, [write output] */ - @SuppressWarnings("removal") @Override public OutputStream getOutputStream() throws IOException { lock(); try { connecting = true; - SocketPermission p = URLtoSocketPermission(this.url); - - if (p != null) { - try { - return AccessController.doPrivilegedWithCombiner( - new PrivilegedExceptionAction<>() { - public OutputStream run() throws IOException { - return getOutputStream0(); - } - }, null, p - ); - } catch (PrivilegedActionException e) { - throw (IOException) e.getException(); - } - } else { - return getOutputStream0(); - } + return getOutputStream0(); } finally { unlock(); } @@ -1591,29 +1293,12 @@ private void setCookieHeader() throws IOException { } // end of getting cookies } - @SuppressWarnings("removal") @Override public InputStream getInputStream() throws IOException { lock(); try { connecting = true; - SocketPermission p = URLtoSocketPermission(this.url); - - if (p != null) { - try { - return AccessController.doPrivilegedWithCombiner( - new PrivilegedExceptionAction<>() { - public InputStream run() throws IOException { - return getInputStream0(); - } - }, null, p - ); - } catch (PrivilegedActionException e) { - throw (IOException) e.getException(); - } - } else { - return getInputStream0(); - } + return getInputStream0(); } finally { unlock(); } @@ -2060,17 +1745,9 @@ private InputStream getInputStream0() throws IOException { private IOException getChainedException(final IOException rememberedException) { try { final Object[] args = { rememberedException.getMessage() }; - @SuppressWarnings("removal") - IOException chainedException = - java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction<>() { - public IOException run() throws Exception { - return (IOException) - rememberedException.getClass() - .getConstructor(new Class[] { String.class }) - .newInstance(args); - } - }); + IOException chainedException = rememberedException.getClass() + .getConstructor(new Class[] { String.class }) + .newInstance(args); chainedException.initCause(rememberedException); return chainedException; } catch (Exception ignored) { @@ -2392,7 +2069,7 @@ private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOE * Gets the authentication for an HTTP proxy, and applies it to * the connection. */ - @SuppressWarnings({"removal","fallthrough"}) + @SuppressWarnings("fallthrough") private AuthenticationInfo getHttpProxyAuthentication(AuthenticationHeader authhdr) throws IOException { @@ -2430,44 +2107,40 @@ private AuthenticationInfo getHttpProxyAuthentication(AuthenticationHeader authh proxyAuthKey = AuthenticationInfo.getProxyAuthKey(host, port, realm, authScheme); ret = AuthenticationInfo.getProxyAuth(proxyAuthKey, authCache); if (ret == null) { - switch (authScheme) { - case BASIC: - InetAddress addr = null; - try { - final String finalHost = host; - addr = java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction<>() { - public InetAddress run() - throws java.net.UnknownHostException { - return InetAddress.getByName(finalHost); - } - }); - } catch (java.security.PrivilegedActionException ignored) { - // User will have an unknown host. - } - PasswordAuthentication a = - privilegedRequestPasswordAuthentication( - authenticator, - host, addr, port, "http", - realm, scheme, url, RequestorType.PROXY); - if (a != null) { - ret = new BasicAuthentication(true, host, port, realm, a, isUTF8); + ret = switch (authScheme) { + case BASIC -> { + InetAddress addr = null; + try { + addr = InetAddress.getByName(host); + } catch (UnknownHostException uhe) { + // Ignore the exception. The Authenticator instance will + // be passed a null InetAddress when requesting a password from the + // Authenticator. + } + final PasswordAuthentication a = requestPassword(authenticator, + host, addr, port, "http", + realm, scheme, url, RequestorType.PROXY); + if (a != null) { + yield new BasicAuthentication(true, host, port, realm, a, isUTF8); + } + yield null; } - break; - case DIGEST: - a = privilegedRequestPasswordAuthentication( - authenticator, - host, null, port, url.getProtocol(), - realm, scheme, url, RequestorType.PROXY); - if (a != null) { - DigestAuthentication.Parameters params = - new DigestAuthentication.Parameters(); - ret = new DigestAuthentication(true, host, port, realm, - scheme, a, params); + case DIGEST -> { + final PasswordAuthentication a = requestPassword(authenticator, + host, null, port, url.getProtocol(), + realm, scheme, url, RequestorType.PROXY); + if (a != null) { + DigestAuthentication.Parameters params = + new DigestAuthentication.Parameters(); + yield new DigestAuthentication(true, host, port, realm, + scheme, a, params); + } + yield null; } - break; - case NTLM: - if (NTLMAuthenticationProxy.supported) { + case NTLM -> { + if (!NTLMAuthenticationProxy.supported) { + yield null; + } /* tryTransparentNTLMProxy will always be true the first * time around, but verify that the platform supports it * otherwise don't try. */ @@ -2484,14 +2157,14 @@ public InetAddress run() } } - a = null; + PasswordAuthentication a = null; if (tryTransparentNTLMProxy) { logger.finest("Trying Transparent NTLM authentication"); } else { - a = privilegedRequestPasswordAuthentication( - authenticator, - host, null, port, url.getProtocol(), - "", scheme, url, RequestorType.PROXY); + a = requestPassword( + authenticator, + host, null, port, url.getProtocol(), + "", scheme, url, RequestorType.PROXY); validateNTLMCredentials(a); } /* If we are not trying transparent authentication then @@ -2500,29 +2173,27 @@ public InetAddress run() * and password will be picked up from the current logged * on users credentials. */ + AuthenticationInfo authInfo = null; if (tryTransparentNTLMProxy || - (!tryTransparentNTLMProxy && a != null)) { - ret = NTLMAuthenticationProxy.proxy.create(true, host, port, a); + (!tryTransparentNTLMProxy && a != null)) { + authInfo = NTLMAuthenticationProxy.proxy.create(true, host, port, a); } /* set to false so that we do not try again */ tryTransparentNTLMProxy = false; + yield authInfo; } - break; - case NEGOTIATE: - ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate")); - break; - case KERBEROS: - ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos")); - break; - case UNKNOWN: - if (logger.isLoggable(PlatformLogger.Level.FINEST)) { - logger.finest("Unknown/Unsupported authentication scheme: " + scheme); + case NEGOTIATE -> + new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate")); + case KERBEROS -> + new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos")); + case UNKNOWN -> { + if (logger.isLoggable(PlatformLogger.Level.FINEST)) { + logger.finest("Unknown/Unsupported authentication scheme: " + scheme); + } + yield null; } - /*fall through*/ - default: - throw new AssertionError("should not reach here"); - } + }; } if (ret != null) { if (!ret.setHeaders(this, p, raw)) { @@ -2604,7 +2275,7 @@ private AuthenticationInfo getServerAuthentication(AuthenticationHeader authhdr) break; case BASIC: PasswordAuthentication a = - privilegedRequestPasswordAuthentication( + requestPassword( authenticator, url.getHost(), addr, port, url.getProtocol(), realm, scheme, url, RequestorType.SERVER); @@ -2613,7 +2284,7 @@ private AuthenticationInfo getServerAuthentication(AuthenticationHeader authhdr) } break; case DIGEST: - a = privilegedRequestPasswordAuthentication( + a = requestPassword( authenticator, url.getHost(), addr, port, url.getProtocol(), realm, scheme, url, RequestorType.SERVER); @@ -2650,7 +2321,7 @@ private AuthenticationInfo getServerAuthentication(AuthenticationHeader authhdr) if (tryTransparentNTLMServer) { logger.finest("Trying Transparent NTLM authentication"); } else { - a = privilegedRequestPasswordAuthentication( + a = requestPassword( authenticator, url.getHost(), addr, port, url.getProtocol(), "", scheme, url, RequestorType.SERVER); @@ -2753,7 +2424,6 @@ String getRequestURI() throws IOException { * resets the url, re-connects, and resets the request * property. */ - @SuppressWarnings("removal") private boolean followRedirect() throws IOException { if (!getInstanceFollowRedirects()) { return false; @@ -2783,27 +2453,7 @@ private boolean followRedirect() throws IOException { // treat loc as a relative URI to conform to popular browsers locUrl = newURL(url, loc); } - - final URL locUrl0 = locUrl; - socketPermission = null; // force recalculation - SocketPermission p = URLtoSocketPermission(locUrl); - - if (p != null) { - try { - return AccessController.doPrivilegedWithCombiner( - new PrivilegedExceptionAction<>() { - public Boolean run() throws IOException { - return followRedirect0(loc, stat, locUrl0); - } - }, null, p - ); - } catch (PrivilegedActionException e) { - throw (IOException) e.getException(); - } - } else { - // run without additional permission - return followRedirect0(loc, stat, locUrl); - } + return followRedirect0(loc, stat, locUrl); } /* Tells us whether to follow a redirect. If so, it @@ -2838,12 +2488,6 @@ private boolean followRedirect0(String loc, int stat, URL locUrl) String proxyHost = locUrl.getHost(); int proxyPort = locUrl.getPort(); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkConnect(proxyHost, proxyPort); - } - setProxiedClient (url, proxyHost, proxyPort); requests.set(0, method + " " + getRequestURI()+" " + httpVersion, null); diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java index 27442382ec7..c27d866f5ef 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java @@ -36,7 +36,6 @@ import sun.net.www.HeaderParser; import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; import static sun.net.www.protocol.http.AuthScheme.KERBEROS; -import sun.security.action.GetPropertyAction; /** * NegotiateAuthentication: @@ -45,10 +44,7 @@ * @since 1.6 */ -class NegotiateAuthentication extends AuthenticationInfo { - - @java.io.Serial - private static final long serialVersionUID = 100L; +final class NegotiateAuthentication extends AuthenticationInfo { private final HttpCallerInfo hci; @@ -61,14 +57,6 @@ class NegotiateAuthentication extends AuthenticationInfo { static ThreadLocal > cache = null; private static final ReentrantLock negotiateLock = new ReentrantLock(); - /* Whether cache is enabled for Negotiate/Kerberos */ - private static final boolean cacheSPNEGO; - static { - String spnegoCacheProp = - GetPropertyAction.privilegedGetProperty("jdk.spnego.cache", "true"); - cacheSPNEGO = Boolean.parseBoolean(spnegoCacheProp); - } - // The HTTP Negotiate Helper private Negotiator negotiator = null; diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java index 9bc28a353ab..fb2dfe6fff3 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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,7 +30,6 @@ import java.io.UnsupportedEncodingException; import java.io.PrintStream; import java.io.BufferedOutputStream; -import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; import java.net.URL; @@ -48,7 +47,6 @@ import sun.net.www.http.HttpClient; import sun.net.www.protocol.http.AuthCacheImpl; import sun.net.www.protocol.http.HttpURLConnection; -import sun.security.action.*; import sun.security.util.HostnameChecker; import sun.security.ssl.SSLSocketImpl; @@ -138,10 +136,8 @@ final class HttpsClient extends HttpClient // // If ciphers are assigned, sort them into an array. // - String ciphers []; - String cipherString = - GetPropertyAction.privilegedGetProperty("https.cipherSuites"); - + String[] ciphers; + String cipherString = System.getProperty("https.cipherSuites"); if (cipherString == null || cipherString.isEmpty()) { ciphers = null; } else { @@ -162,10 +158,8 @@ final class HttpsClient extends HttpClient // // If protocols are assigned, sort them into an array. // - String protocols []; - String protocolString = - GetPropertyAction.privilegedGetProperty("https.protocols"); - + String[] protocols; + String protocolString = System.getProperty("https.protocols"); if (protocolString == null || protocolString.isEmpty()) { protocols = null; } else { @@ -183,65 +177,12 @@ final class HttpsClient extends HttpClient return protocols; } - private String getUserAgent() { - String userAgent = - GetPropertyAction.privilegedGetProperty("https.agent"); - if (userAgent == null || userAgent.isEmpty()) { - userAgent = "JSSE"; - } - return userAgent; - } - // CONSTRUCTOR, FACTORY - - /** - * Create an HTTPS client URL. Traffic will be tunneled through any - * intermediate nodes rather than proxied, so that confidentiality - * of data exchanged can be preserved. However, note that all the - * anonymous SSL flavors are subject to "person-in-the-middle" - * attacks against confidentiality. If you enable use of those - * flavors, you may be giving up the protection you get through - * SSL tunneling. - * - * Use New to get new HttpsClient. This constructor is meant to be - * used only by New method. New properly checks for URL spoofing. - * - * @param url https URL with which a connection must be established - */ - private HttpsClient(SSLSocketFactory sf, URL url) - throws IOException - { - // HttpClient-level proxying is always disabled, - // because we override doConnect to do tunneling instead. - this(sf, url, (String)null, -1); - } - /** - * Create an HTTPS client URL. Traffic will be tunneled through - * the specified proxy server. - */ - HttpsClient(SSLSocketFactory sf, URL url, String proxyHost, int proxyPort) - throws IOException { - this(sf, url, proxyHost, proxyPort, -1); - } - - /** - * Create an HTTPS client URL. Traffic will be tunneled through + * Create an HTTPS client URL. Traffic will be tunneled through * the specified proxy server, with a connect timeout */ - HttpsClient(SSLSocketFactory sf, URL url, String proxyHost, int proxyPort, - int connectTimeout) - throws IOException { - this(sf, url, - (proxyHost == null? null: - HttpClient.newHttpProxy(proxyHost, proxyPort, "https")), - connectTimeout); - } - - /** - * Same as previous constructor except using a Proxy - */ HttpsClient(SSLSocketFactory sf, URL url, Proxy proxy, int connectTimeout) throws IOException { @@ -268,37 +209,6 @@ private HttpsClient(SSLSocketFactory sf, URL url) // This code largely ripped off from HttpClient.New, and // it uses the same keepalive cache. - static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv, - HttpURLConnection httpuc) - throws IOException { - return HttpsClient.New(sf, url, hv, true, httpuc); - } - - /** See HttpClient for the model for this method. */ - static HttpClient New(SSLSocketFactory sf, URL url, - HostnameVerifier hv, boolean useCache, - HttpURLConnection httpuc) throws IOException { - return HttpsClient.New(sf, url, hv, (String)null, -1, useCache, httpuc); - } - - /** - * Get a HTTPS client to the URL. Traffic will be tunneled through - * the specified proxy server. - */ - static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv, - String proxyHost, int proxyPort, - HttpURLConnection httpuc) throws IOException { - return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, true, httpuc); - } - - static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv, - String proxyHost, int proxyPort, boolean useCache, - HttpURLConnection httpuc) - throws IOException { - return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, useCache, -1, - httpuc); - } - static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv, String proxyHost, int proxyPort, boolean useCache, int connectTimeout, HttpURLConnection httpuc) @@ -379,15 +289,6 @@ static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv, ret.authcache = httpuc.getAuthCache(); } } else { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - if (ret.proxy == Proxy.NO_PROXY || ret.proxy == null) { - security.checkConnect(InetAddress.getByName(url.getHost()).getHostAddress(), url.getPort()); - } else { - security.checkConnect(url.getHost(), url.getPort()); - } - } ret.url = url; } ret.setHostnameVerifier(hv); @@ -395,22 +296,17 @@ static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv, return ret; } - // METHODS - void setHostnameVerifier(HostnameVerifier hv) { + private void setHostnameVerifier(HostnameVerifier hv) { this.hv = hv; } - void setSSLSocketFactory(SSLSocketFactory sf) { + private void setSSLSocketFactory(SSLSocketFactory sf) { sslSocketFactory = sf; } - SSLSocketFactory getSSLSocketFactory() { - return sslSocketFactory; - } - /** * The following method, createSocket, is defined in NetworkClient - * and overridden here so that the socket facroty is used to create + * and overridden here so that the socket factory is used to create * new sockets. */ @Override diff --git a/src/java.base/share/classes/sun/net/www/protocol/jar/JarFileFactory.java b/src/java.base/share/classes/sun/net/www/protocol/jar/JarFileFactory.java index 17ca43d4ace..9afbea8bf76 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/src/java.base/share/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -31,7 +31,6 @@ import java.net.URLConnection; import java.util.HashMap; import java.util.jar.JarFile; -import java.security.Permission; import jdk.internal.util.OperatingSystem; import sun.net.util.URLUtil; @@ -219,35 +218,7 @@ public void close(JarFile jarFile) { private JarFile getCachedJarFile(URL url) { assert Thread.holdsLock(instance); - JarFile result = fileCache.get(urlKey(url)); - - /* if the JAR file is cached, the permission will always be there */ - if (result != null) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - Permission perm = getPermission(result); - if (perm != null) { - try { - sm.checkPermission(perm); - } catch (SecurityException se) { - // fallback to checkRead/checkConnect for pre 1.2 - // security managers - if ((perm instanceof java.io.FilePermission) && - perm.getActions().contains("read")) { - sm.checkRead(perm.getName()); - } else if ((perm instanceof - java.net.SocketPermission) && - perm.getActions().contains("connect")) { - sm.checkConnect(url.getHost(), url.getPort()); - } else { - throw se; - } - } - } - } - } - return result; + return fileCache.get(urlKey(url)); } private String urlKey(URL url) { @@ -255,16 +226,4 @@ private String urlKey(URL url) { if ("runtime".equals(url.getRef())) urlstr += "#runtime"; return urlstr; } - - private Permission getPermission(JarFile jarFile) { - try { - URLConnection uc = getConnection(jarFile); - if (uc != null) - return uc.getPermission(); - } catch (IOException ioe) { - // gulp - } - - return null; - } } diff --git a/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java index b4cd98870ca..4e67c962a46 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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,15 +30,11 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedAction; import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReaderFactory; -import jdk.internal.loader.URLClassPath; import jdk.internal.loader.Resource; import sun.net.www.ParseUtil; import sun.net.www.URLConnection; @@ -47,15 +43,10 @@ * URLConnection implementation that can be used to connect to resources * contained in the runtime image. */ -@SuppressWarnings("removal") public class JavaRuntimeURLConnection extends URLConnection { // ImageReader to access resources in jimage - private static final ImageReader reader; - static { - PrivilegedAction pa = ImageReaderFactory::getImageReader; - reader = AccessController.doPrivileged(pa); - } + private static final ImageReader reader = ImageReaderFactory.getImageReader(); // the module and resource name in the URL private final String module; @@ -92,7 +83,7 @@ private static Resource findResource(String module, String name) { if (reader != null) { URL url = toJrtURL(module, name); ImageLocation location = reader.findLocation(module, name); - if (location != null && URLClassPath.checkURL(url) != null) { + if (location != null) { return new Resource() { @Override public String getName() { @@ -158,11 +149,6 @@ public int getContentLength() { return len > Integer.MAX_VALUE ? -1 : (int)len; } - @Override - public Permission getPermission() { - return new RuntimePermission("accessSystemModules"); - } - /** * Returns a jrt URL for the given module and resource name. */ diff --git a/src/java.base/share/classes/sun/net/www/protocol/mailto/MailToURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/mailto/MailToURLConnection.java index 555279f71ee..7791d07a8ca 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/mailto/MailToURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/mailto/MailToURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -27,9 +27,7 @@ import java.net.URL; import java.net.InetAddress; -import java.net.SocketPermission; import java.io.*; -import java.security.Permission; import jdk.internal.util.StaticProperty; import sun.net.www.*; @@ -48,7 +46,6 @@ public class MailToURLConnection extends URLConnection { OutputStream os = null; SmtpClient client; - Permission permission; private int connectTimeout = -1; private int readTimeout = -1; @@ -67,12 +64,6 @@ public class MailToURLConnection extends URLConnection { String getFromAddress() { String str = System.getProperty("user.fromaddr"); if (str == null) { - // Perform the property security check for user.name - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPropertyAccess("user.name"); - } str = StaticProperty.userName(); if (str != null) { String host = System.getProperty("mail.host"); @@ -112,16 +103,6 @@ public synchronized OutputStream getOutputStream() throws IOException { return os; } - @Override - public Permission getPermission() throws IOException { - if (permission == null) { - connect(); - String host = client.getMailHost() + ":" + 25; - permission = new SocketPermission(host, "connect"); - } - return permission; - } - @Override public void setConnectTimeout(int timeout) { if (timeout < 0) diff --git a/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java b/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java index 0c15c1a6439..0b70a954e4c 100644 --- a/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java @@ -34,10 +34,6 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicBoolean; -import java.security.PrivilegedAction; -import java.security.AccessController; -import java.security.AccessControlContext; -import sun.security.action.GetIntegerAction; /** * Base implementation of AsynchronousChannelGroup @@ -48,9 +44,8 @@ abstract class AsynchronousChannelGroupImpl { // number of internal threads handling I/O events when using an unbounded // thread pool. Internal threads do not dispatch to completion handlers. - @SuppressWarnings("removal") - private static final int internalThreadCount = AccessController.doPrivileged( - new GetIntegerAction("sun.nio.ch.internalThreadPoolSize", 1)); + private static final int internalThreadCount = + Integer.getInteger("sun.nio.ch.internalThreadPoolSize", 1); // associated thread pool private final ThreadPool pool; @@ -115,17 +110,10 @@ public void run() { }; } - @SuppressWarnings("removal") private void startInternalThread(final Runnable task) { - AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Void run() { - // internal threads should not be visible to application so - // cannot use user-supplied thread factory - ThreadPool.defaultThreadFactory().newThread(task).start(); - return null; - } - }); + // internal threads should not be visible to application so + // cannot use user-supplied thread factory + ThreadPool.defaultThreadFactory().newThread(task).start(); } protected final void startThreads(Runnable task) { @@ -247,18 +235,9 @@ abstract Object attachForeignChannel(Channel channel, FileDescriptor fdo) */ abstract void shutdownHandlerTasks(); - @SuppressWarnings("removal") private void shutdownExecutors() { - AccessController.doPrivileged( - new PrivilegedAction<>() { - public Void run() { - pool.executor().shutdown(); - timeoutExecutor.shutdown(); - return null; - } - }, - null, - new RuntimePermission("modifyThread")); + pool.executor().shutdown(); + timeoutExecutor.shutdown(); } @Override @@ -320,28 +299,6 @@ public final boolean awaitTermination(long timeout, TimeUnit unit) */ @Override public final void execute(Runnable task) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // when a security manager is installed then the user's task - // must be run with the current calling context - @SuppressWarnings("removal") - final AccessControlContext acc = AccessController.getContext(); - final Runnable delegate = task; - task = new Runnable() { - @SuppressWarnings("removal") - @Override - public void run() { - AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Void run() { - delegate.run(); - return null; - } - }, acc); - } - }; - } executeOnPooledThread(task); } } diff --git a/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java index cdc3a883734..0e6ca6c3dcd 100644 --- a/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -150,10 +150,6 @@ public final AsynchronousServerSocketChannel bind(SocketAddress local, int backl { InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : Net.checkAddress(local); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkListen(isa.getPort()); try { begin(); @@ -175,7 +171,7 @@ public final AsynchronousServerSocketChannel bind(SocketAddress local, int backl public final SocketAddress getLocalAddress() throws IOException { if (!isOpen()) throw new ClosedChannelException(); - return Net.getRevealedLocalAddress(localAddress); + return localAddress; } @Override @@ -257,7 +253,7 @@ public final String toString() { if (localAddress == null) { sb.append("unbound"); } else { - sb.append(Net.getRevealedLocalAddressAsString(localAddress)); + sb.append(localAddress.toString()); } } sb.append(']'); diff --git a/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 9c07dc47cd2..e08a873d73d 100644 --- a/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -428,11 +428,6 @@ public final AsynchronousSocketChannel bind(SocketAddress local) throw new AlreadyBoundException(); InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : Net.checkAddress(local); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkListen(isa.getPort()); - } NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); Net.bind(fd, isa.getAddress(), isa.getPort()); localAddress = Net.localAddress(fd); @@ -447,7 +442,7 @@ public final AsynchronousSocketChannel bind(SocketAddress local) public final SocketAddress getLocalAddress() throws IOException { if (!isOpen()) throw new ClosedChannelException(); - return Net.getRevealedLocalAddress(localAddress); + return localAddress; } @Override @@ -591,8 +586,7 @@ public final String toString() { } if (localAddress != null) { sb.append(" local="); - sb.append( - Net.getRevealedLocalAddressAsString(localAddress)); + sb.append(localAddress.toString()); } if (remoteAddress != null) { sb.append(" remote="); diff --git a/src/java.base/share/classes/sun/nio/ch/CompletedFuture.java b/src/java.base/share/classes/sun/nio/ch/CompletedFuture.java index 60f5f1056bc..e008dd9357b 100644 --- a/src/java.base/share/classes/sun/nio/ch/CompletedFuture.java +++ b/src/java.base/share/classes/sun/nio/ch/CompletedFuture.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -49,8 +49,8 @@ static CompletedFuture withResult(V result) { } static CompletedFuture withFailure(Throwable exc) { - // exception must be IOException or SecurityException - if (!(exc instanceof IOException) && !(exc instanceof SecurityException)) + // exception must be IOException + if (!(exc instanceof IOException)) exc = new IOException(exc); return new CompletedFuture(null, exc); } diff --git a/src/java.base/share/classes/sun/nio/ch/Invoker.java b/src/java.base/share/classes/sun/nio/ch/Invoker.java index 475669a2b82..4c9d604a342 100644 --- a/src/java.base/share/classes/sun/nio/ch/Invoker.java +++ b/src/java.base/share/classes/sun/nio/ch/Invoker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -27,8 +27,6 @@ import java.nio.channels.*; import java.util.concurrent.*; -import java.security.AccessController; -import sun.security.action.GetIntegerAction; import jdk.internal.misc.InnocuousThread; /** @@ -41,9 +39,8 @@ private Invoker() { } // maximum number of completion handlers that may be invoked on the current // thread before it re-directs invocations to the thread pool. This helps // avoid stack overflow and lessens the risk of starvation. - @SuppressWarnings("removal") - private static final int maxHandlerInvokeCount = AccessController.doPrivileged( - new GetIntegerAction("sun.nio.ch.maxCompletionHandlersOnStack", 16)); + private static final int maxHandlerInvokeCount = + Integer.getInteger("sun.nio.ch.maxCompletionHandlersOnStack", 16); // Per-thread object with reference to channel group and a counter for // the number of completion handlers invoked. This should be reset to 0 @@ -115,7 +112,6 @@ static boolean mayInvokeDirect(GroupAndInvokeCount myGroupAndInvokeCount, * Invoke handler without checking the thread identity or number of handlers * on the thread stack. */ - @SuppressWarnings("removal") static void invokeUnchecked(CompletionHandler handler, A attachment, V value, @@ -129,18 +125,6 @@ static void invokeUnchecked(CompletionHandler handler, // clear interrupt Thread.interrupted(); - - // clear thread locals when in default thread pool - if (System.getSecurityManager() != null) { - Thread me = Thread.currentThread(); - if (me instanceof InnocuousThread) { - GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get(); - ((InnocuousThread)me).eraseThreadLocals(); - if (thisGroupAndInvokeCount != null) { - myGroupAndInvokeCount.set(thisGroupAndInvokeCount); - } - } - } } /** diff --git a/src/java.base/share/classes/sun/nio/ch/Net.java b/src/java.base/share/classes/sun/nio/ch/Net.java index 49814ae6bf2..03dcf04a50f 100644 --- a/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/src/java.base/share/classes/sun/nio/ch/Net.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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,14 +45,11 @@ import java.nio.channels.NotYetConnectedException; import java.nio.channels.UnresolvedAddressException; import java.nio.channels.UnsupportedAddressTypeException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Enumeration; import java.util.Objects; import sun.net.ext.ExtendedSocketOptions; import sun.net.util.IPAddressUtil; -import sun.security.action.GetPropertyAction; public class Net { private Net() { } @@ -215,34 +212,6 @@ static void translateException(Exception x) translateException(x, false); } - /** - * Returns the local address after performing a SecurityManager#checkConnect. - */ - static InetSocketAddress getRevealedLocalAddress(SocketAddress sa) { - InetSocketAddress isa = (InetSocketAddress) sa; - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (isa != null && sm != null) { - try { - sm.checkConnect(isa.getAddress().getHostAddress(), -1); - } catch (SecurityException e) { - // Return loopback address only if security check fails - isa = getLoopbackAddress(isa.getPort()); - } - } - return isa; - } - - @SuppressWarnings("removal") - static String getRevealedLocalAddressAsString(SocketAddress sa) { - InetSocketAddress isa = (InetSocketAddress) sa; - if (System.getSecurityManager() == null) { - return isa.toString(); - } else { - return getLoopbackAddress(isa.getPort()).toString(); - } - } - private static InetSocketAddress getLoopbackAddress(int port) { return new InetSocketAddress(InetAddress.getLoopbackAddress(), port); } @@ -302,20 +271,15 @@ static InetAddress anyLocalAddress(ProtocolFamily family) { * Returns any IPv4 address of the given network interface, or * null if the interface does not have any IPv4 addresses. */ - @SuppressWarnings("removal") static Inet4Address anyInet4Address(final NetworkInterface interf) { - return AccessController.doPrivileged(new PrivilegedAction() { - public Inet4Address run() { - Enumeration addrs = interf.getInetAddresses(); - while (addrs.hasMoreElements()) { - InetAddress addr = addrs.nextElement(); - if (addr instanceof Inet4Address inet4Address) { - return inet4Address; - } - } - return null; + Enumeration addrs = interf.getInetAddresses(); + while (addrs.hasMoreElements()) { + InetAddress addr = addrs.nextElement(); + if (addr instanceof Inet4Address inet4Address) { + return inet4Address; } - }); + } + return null; } /** @@ -500,8 +464,7 @@ static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, SocketOp } private static boolean isFastTcpLoopbackRequested() { - String loopbackProp = GetPropertyAction - .privilegedGetProperty("jdk.net.useFastTcpLoopback", "false"); + String loopbackProp = System.getProperty("jdk.net.useFastTcpLoopback", "false"); return loopbackProp.isEmpty() || Boolean.parseBoolean(loopbackProp); } @@ -827,8 +790,7 @@ static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group static { int availLevel = isExclusiveBindAvailable(); if (availLevel >= 0) { - String exclBindProp = GetPropertyAction - .privilegedGetProperty("sun.net.useExclusiveBind"); + String exclBindProp = System.getProperty("sun.net.useExclusiveBind"); if (exclBindProp != null) { EXCLUSIVE_BIND = exclBindProp.isEmpty() || Boolean.parseBoolean(exclBindProp); } else { diff --git a/src/java.base/share/classes/sun/nio/ch/PendingFuture.java b/src/java.base/share/classes/sun/nio/ch/PendingFuture.java index b2b3baceb62..67b526d8466 100644 --- a/src/java.base/share/classes/sun/nio/ch/PendingFuture.java +++ b/src/java.base/share/classes/sun/nio/ch/PendingFuture.java @@ -145,7 +145,7 @@ void setResult(V res) { * Sets the result, or a no-op if the result or exception is already set. */ void setFailure(Throwable x) { - if (!(x instanceof IOException) && !(x instanceof SecurityException)) + if (!(x instanceof IOException)) x = new IOException(x); synchronized (this) { if (haveResult) diff --git a/src/java.base/share/classes/sun/nio/ch/Reflect.java b/src/java.base/share/classes/sun/nio/ch/Reflect.java index 8090e0f0cc5..d1e564cce97 100644 --- a/src/java.base/share/classes/sun/nio/ch/Reflect.java +++ b/src/java.base/share/classes/sun/nio/ch/Reflect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -27,8 +27,6 @@ import java.io.*; import java.lang.reflect.*; -import java.security.AccessController; -import java.security.PrivilegedAction; class Reflect { // package-private @@ -43,22 +41,13 @@ private static class ReflectionError extends Error { } } - @SuppressWarnings("removal") - private static void setAccessible(final AccessibleObject ao) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - ao.setAccessible(true); - return null; - }}); - } - static Constructor lookupConstructor(String className, Class[] paramTypes) { try { Class cl = Class.forName(className); Constructor c = cl.getDeclaredConstructor(paramTypes); - setAccessible(c); + c.setAccessible(true); return c; } catch (ClassNotFoundException | NoSuchMethodException x) { throw new ReflectionError(x); @@ -82,7 +71,7 @@ static Method lookupMethod(String className, try { Class cl = Class.forName(className); Method m = cl.getDeclaredMethod(methodName, paramTypes); - setAccessible(m); + m.setAccessible(true); return m; } catch (ClassNotFoundException | NoSuchMethodException x) { throw new ReflectionError(x); @@ -115,7 +104,7 @@ static Field lookupField(String className, String fieldName) { try { Class cl = Class.forName(className); Field f = cl.getDeclaredField(fieldName); - setAccessible(f); + f.setAccessible(true); return f; } catch (ClassNotFoundException | NoSuchFieldException x) { throw new ReflectionError(x); diff --git a/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java b/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java index 1720801fbe9..3e1583693cc 100644 --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,9 +37,6 @@ import java.nio.channels.IllegalBlockingModeException; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Set; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -61,14 +58,8 @@ class ServerSocketAdaptor // package-private // Timeout "option" value for accepts private volatile int timeout; - @SuppressWarnings("removal") static ServerSocket create(ServerSocketChannelImpl ssc) { - PrivilegedExceptionAction pa = () -> new ServerSocketAdaptor(ssc); - try { - return AccessController.doPrivileged(pa); - } catch (PrivilegedActionException pae) { - throw new InternalError("Should not reach here", pae); - } + return new ServerSocketAdaptor(ssc); } private ServerSocketAdaptor(ServerSocketChannelImpl ssc) { @@ -98,7 +89,7 @@ public InetAddress getInetAddress() { if (local == null) { return null; } else { - return Net.getRevealedLocalAddress(local).getAddress(); + return ((InetSocketAddress)local).getAddress(); } } diff --git a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 0bd72bacf0b..f266b762b8b 100644 --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -202,11 +202,7 @@ public ServerSocket socket() { public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { ensureOpen(); - if (isUnixSocket()) { - return UnixDomainSockets.getRevealedLocalAddress(localAddress); - } else { - return Net.getRevealedLocalAddress(localAddress); - } + return localAddress; } } @@ -305,7 +301,6 @@ public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOExcep } private SocketAddress unixBind(SocketAddress local, int backlog) throws IOException { - UnixDomainSockets.checkPermission(); if (local == null) { // Attempt up to 10 times to find an unused name in temp directory. // If local address supplied then bind called only once @@ -336,10 +331,6 @@ private SocketAddress netBind(SocketAddress local, int backlog) throws IOExcepti } else { isa = Net.checkAddress(local, family); } - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkListen(isa.getPort()); NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); Net.bind(family, fd, isa.getAddress(), isa.getPort()); Net.listen(fd, backlog < 1 ? 50 : backlog); @@ -423,7 +414,6 @@ private int implAccept(FileDescriptor fd, FileDescriptor newfd, SocketAddress[] throws IOException { if (isUnixSocket()) { - UnixDomainSockets.checkPermission(); String[] pa = new String[1]; int n = UnixDomainSockets.accept(fd, newfd, pa); if (n > 0) @@ -495,16 +485,6 @@ private SocketChannel finishAccept(FileDescriptor newfd, SocketAddress sa) try { // newly accepted socket is initially in blocking mode IOUtil.configureBlocking(newfd, true); - - // check permitted to accept connections from the remote address - if (isNetSocket()) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - InetSocketAddress isa = (InetSocketAddress) sa; - sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort()); - } - } return new SocketChannelImpl(provider(), family, newfd, sa); } catch (Exception e) { nd.close(newfd); @@ -749,9 +729,7 @@ public String toString() { if (addr == null) { sb.append("unbound"); } else if (isUnixSocket()) { - sb.append(UnixDomainSockets.getRevealedLocalAddressAsString(addr)); - } else { - sb.append(Net.getRevealedLocalAddressAsString(addr)); + sb.append(addr); } } } diff --git a/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java index 5f3f91e7aff..440c254601d 100644 --- a/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java @@ -30,8 +30,6 @@ import java.nio.channels.*; import java.util.concurrent.*; import java.nio.ByteBuffer; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.io.FileDescriptor; import java.io.IOException; diff --git a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java index 076f817d5ce..cbcfd79378c 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -36,9 +36,6 @@ import java.net.SocketOption; import java.net.StandardSocketOptions; import java.nio.channels.SocketChannel; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Set; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -63,16 +60,10 @@ private SocketAdaptor(SocketChannelImpl sc) throws SocketException { this.sc = sc; } - @SuppressWarnings("removal") static Socket create(SocketChannelImpl sc) { try { - if (System.getSecurityManager() == null) { - return new SocketAdaptor(sc); - } else { - PrivilegedExceptionAction pa = () -> new SocketAdaptor(sc); - return AccessController.doPrivileged(pa); - } - } catch (SocketException | PrivilegedActionException e) { + return new SocketAdaptor(sc); + } catch (SocketException e) { throw new InternalError(e); } } @@ -132,7 +123,7 @@ public InetAddress getLocalAddress() { if (sc.isOpen()) { InetSocketAddress local = localAddress(); if (local != null) { - return Net.getRevealedLocalAddress(local).getAddress(); + return local.getAddress(); } } return new InetSocketAddress(0).getAddress(); @@ -165,7 +156,7 @@ public SocketAddress getRemoteSocketAddress() { @Override public SocketAddress getLocalSocketAddress() { - return Net.getRevealedLocalAddress(sc.localAddress()); + return sc.localAddress(); } @Override diff --git a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index ebbf55acd97..893bd17ceed 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -243,11 +243,7 @@ public Socket socket() { public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { ensureOpen(); - if (isUnixSocket()) { - return UnixDomainSockets.getRevealedLocalAddress(localAddress); - } else { - return Net.getRevealedLocalAddress(localAddress); - } + return localAddress; } } @@ -811,7 +807,6 @@ public SocketChannel bind(SocketAddress local) throws IOException { } private SocketAddress unixBind(SocketAddress local) throws IOException { - UnixDomainSockets.checkPermission(); if (local == null) { return UnixDomainSockets.unnamed(); } else { @@ -833,11 +828,6 @@ private SocketAddress netBind(SocketAddress local) throws IOException { } else { isa = Net.checkAddress(local, family); } - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkListen(isa.getPort()); - } NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); Net.bind(family, fd, isa.getAddress(), isa.getPort()); return Net.localAddress(fd); @@ -923,15 +913,9 @@ private void endConnect(boolean blocking, boolean completed) */ private SocketAddress checkRemote(SocketAddress sa) { if (isUnixSocket()) { - UnixDomainSockets.checkPermission(); return UnixDomainSockets.checkAddress(sa); } else { InetSocketAddress isa = Net.checkAddress(sa, family); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); - } InetAddress address = isa.getAddress(); if (address.isAnyLocalAddress()) { int port = isa.getPort(); @@ -1617,15 +1601,11 @@ public String toString() { SocketAddress addr = localAddress(); if (addr != null) { sb.append(" local="); - if (isUnixSocket()) { - sb.append(UnixDomainSockets.getRevealedLocalAddressAsString(addr)); - } else { - sb.append(Net.getRevealedLocalAddressAsString(addr)); - } + sb.append(addr); } if (remoteAddress() != null) { sb.append(" remote="); - sb.append(remoteAddress().toString()); + sb.append(remoteAddress()); } } } diff --git a/src/java.base/share/classes/sun/nio/ch/ThreadPool.java b/src/java.base/share/classes/sun/nio/ch/ThreadPool.java index f5a17361eba..b3157008fcb 100644 --- a/src/java.base/share/classes/sun/nio/ch/ThreadPool.java +++ b/src/java.base/share/classes/sun/nio/ch/ThreadPool.java @@ -26,10 +26,6 @@ package sun.nio.ch; import java.util.concurrent.*; -import java.security.AccessController; -import java.security.PrivilegedAction; -import sun.security.action.GetPropertyAction; -import sun.security.action.GetIntegerAction; import jdk.internal.misc.InnocuousThread; /** @@ -72,24 +68,12 @@ int poolSize() { return poolSize; } - @SuppressWarnings("removal") static ThreadFactory defaultThreadFactory() { - if (System.getSecurityManager() == null) { - return (Runnable r) -> { - Thread t = new Thread(r); - t.setDaemon(true); - return t; - }; - } else { - return (Runnable r) -> { - PrivilegedAction action = () -> { - Thread t = InnocuousThread.newThread(r); - t.setDaemon(true); - return t; - }; - return AccessController.doPrivileged(action); - }; - } + return (Runnable r) -> { + Thread t = new Thread(r); + t.setDaemon(true); + return t; + }; } private static class DefaultThreadPoolHolder { @@ -148,9 +132,7 @@ public static ThreadPool wrap(ExecutorService executor, int initialSize) { } private static int getDefaultThreadPoolInitialSize() { - @SuppressWarnings("removal") - String propValue = AccessController.doPrivileged(new - GetPropertyAction(DEFAULT_THREAD_POOL_INITIAL_SIZE)); + String propValue = System.getProperty(DEFAULT_THREAD_POOL_INITIAL_SIZE); if (propValue != null) { try { return Integer.parseInt(propValue); @@ -163,9 +145,7 @@ private static int getDefaultThreadPoolInitialSize() { } private static ThreadFactory getDefaultThreadPoolThreadFactory() { - @SuppressWarnings("removal") - String propValue = AccessController.doPrivileged(new - GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY)); + String propValue = System.getProperty(DEFAULT_THREAD_POOL_THREAD_FACTORY); if (propValue != null) { try { @SuppressWarnings("deprecation") diff --git a/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java b/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java index 251e79c6ecc..128694cb52d 100644 --- a/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java +++ b/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -59,25 +59,6 @@ static boolean isSupported() { return supported; } - static void checkPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(accessUnixDomainSocket); - } - - static UnixDomainSocketAddress getRevealedLocalAddress(SocketAddress sa) { - UnixDomainSocketAddress addr = (UnixDomainSocketAddress) sa; - try { - checkPermission(); - // Security check passed - } catch (SecurityException e) { - // Return unnamed address only if security check fails - addr = unnamed(); - } - return addr; - } - static UnixDomainSocketAddress localAddress(FileDescriptor fd) throws IOException { String path = new String(localAddress0(fd), UnixDomainSocketsUtil.getCharset()); return UnixDomainSocketAddress.of(path); @@ -85,11 +66,6 @@ static UnixDomainSocketAddress localAddress(FileDescriptor fd) throws IOExceptio private static native byte[] localAddress0(FileDescriptor fd) throws IOException; - @SuppressWarnings("removal") - static String getRevealedLocalAddressAsString(SocketAddress sa) { - return (System.getSecurityManager() != null) ? sa.toString() : ""; - } - static UnixDomainSocketAddress checkAddress(SocketAddress sa) { if (sa == null) throw new NullPointerException(); diff --git a/src/java.base/share/classes/sun/nio/ch/Util.java b/src/java.base/share/classes/sun/nio/ch/Util.java index bf9fc0c0f7c..cf411008e43 100644 --- a/src/java.base/share/classes/sun/nio/ch/Util.java +++ b/src/java.base/share/classes/sun/nio/ch/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,15 +32,12 @@ import java.lang.reflect.InvocationTargetException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collection; import java.util.Iterator; import java.util.Set; import jdk.internal.misc.TerminatingThreadLocal; import jdk.internal.misc.Unsafe; -import sun.security.action.GetPropertyAction; public class Util { @@ -75,7 +72,7 @@ protected void threadTerminated(BufferCache cache) { // will never be null * for potential future-proofing. */ private static long getMaxCachedBufferSize() { - String s = GetPropertyAction.privilegedGetProperty("jdk.nio.maxCachedBufferSize"); + String s = System.getProperty("jdk.nio.maxCachedBufferSize"); if (s != null) { try { long m = Long.parseLong(s); @@ -406,28 +403,23 @@ static int pageSize() { private static volatile Constructor directByteBufferConstructor; - @SuppressWarnings("removal") private static void initDBBConstructor() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - try { - Class cl = Class.forName("java.nio.DirectByteBuffer"); - Constructor ctor = cl.getDeclaredConstructor( - new Class[] { int.class, - long.class, - FileDescriptor.class, - Runnable.class, - boolean.class, MemorySegment.class}); - ctor.setAccessible(true); - directByteBufferConstructor = ctor; - } catch (ClassNotFoundException | - NoSuchMethodException | - IllegalArgumentException | - ClassCastException x) { - throw new InternalError(x); - } - return null; - }}); + try { + Class cl = Class.forName("java.nio.DirectByteBuffer"); + Constructor ctor = cl.getDeclaredConstructor( + new Class[] { int.class, + long.class, + FileDescriptor.class, + Runnable.class, + boolean.class, MemorySegment.class }); + ctor.setAccessible(true); + directByteBufferConstructor = ctor; + } catch (ClassNotFoundException | + NoSuchMethodException | + IllegalArgumentException | + ClassCastException x) { + throw new InternalError(x); + } } static MappedByteBuffer newMappedByteBuffer(int size, long addr, @@ -455,28 +447,23 @@ static MappedByteBuffer newMappedByteBuffer(int size, long addr, private static volatile Constructor directByteBufferRConstructor; - @SuppressWarnings("removal") private static void initDBBRConstructor() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - try { - Class cl = Class.forName("java.nio.DirectByteBufferR"); - Constructor ctor = cl.getDeclaredConstructor( - new Class[] { int.class, - long.class, - FileDescriptor.class, - Runnable.class, - boolean.class, MemorySegment.class }); - ctor.setAccessible(true); - directByteBufferRConstructor = ctor; - } catch (ClassNotFoundException | - NoSuchMethodException | - IllegalArgumentException | - ClassCastException x) { - throw new InternalError(x); - } - return null; - }}); + try { + Class cl = Class.forName("java.nio.DirectByteBufferR"); + Constructor ctor = cl.getDeclaredConstructor( + new Class[] { int.class, + long.class, + FileDescriptor.class, + Runnable.class, + boolean.class, MemorySegment.class }); + ctor.setAccessible(true); + directByteBufferRConstructor = ctor; + } catch (ClassNotFoundException | + NoSuchMethodException | + IllegalArgumentException | + ClassCastException x) { + throw new InternalError(x); + } } static MappedByteBuffer newMappedByteBufferR(int size, long addr, diff --git a/src/java.base/share/classes/sun/nio/cs/CharsetMapping.java b/src/java.base/share/classes/sun/nio/cs/CharsetMapping.java index d3e4e907805..eeafe87eb96 100644 --- a/src/java.base/share/classes/sun/nio/cs/CharsetMapping.java +++ b/src/java.base/share/classes/sun/nio/cs/CharsetMapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,7 +28,6 @@ import java.io.InputStream; import java.io.IOException; import java.util.*; -import java.security.*; public class CharsetMapping { public static final char UNMAPPABLE_DECODING = '\uFFFD'; @@ -129,13 +128,8 @@ public int encodeComposite(Entry comp) { } // init the CharsetMapping object from the .dat binary file - @SuppressWarnings("removal") public static CharsetMapping get(final InputStream is) { - return AccessController.doPrivileged(new PrivilegedAction<>() { - public CharsetMapping run() { - return new CharsetMapping().load(is); - } - }); + return new CharsetMapping().load(is); } public static class Entry { diff --git a/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java b/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java index a2026744f04..124e41b77c9 100644 --- a/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java +++ b/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -44,8 +44,6 @@ import java.nio.charset.UnsupportedCharsetException; import java.util.Arrays; -import jdk.internal.misc.InternalLock; - public class StreamDecoder extends Reader { private static final int MIN_BYTE_BUFFER_SIZE = 32; @@ -121,178 +119,109 @@ public int read() throws IOException { return read0(); } + @SuppressWarnings("fallthrough") private int read0() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return lockedRead0(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return lockedRead0(); + synchronized (lock) { + // Return the leftover char, if there is one + if (haveLeftoverChar) { + haveLeftoverChar = false; + return leftoverChar; } - } - } - - @SuppressWarnings("fallthrough") - private int lockedRead0() throws IOException { - // Return the leftover char, if there is one - if (haveLeftoverChar) { - haveLeftoverChar = false; - return leftoverChar; - } - // Convert more bytes - char[] cb = new char[2]; - int n = read(cb, 0, 2); - switch (n) { - case -1: - return -1; - case 2: - leftoverChar = cb[1]; - haveLeftoverChar = true; - // FALL THROUGH - case 1: - return cb[0]; - default: - assert false : n; - return -1; + // Convert more bytes + char[] cb = new char[2]; + int n = read(cb, 0, 2); + switch (n) { + case -1: + return -1; + case 2: + leftoverChar = cb[1]; + haveLeftoverChar = true; + // FALL THROUGH + case 1: + return cb[0]; + default: + assert false : n; + return -1; + } } } public int read(char[] cbuf, int offset, int length) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return lockedRead(cbuf, offset, length); - } finally { - locker.unlock(); + synchronized (lock) { + int off = offset; + int len = length; + + ensureOpen(); + if ((off < 0) || (off > cbuf.length) || (len < 0) || + ((off + len) > cbuf.length) || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); } - } else { - synchronized (lock) { - return lockedRead(cbuf, offset, length); + if (len == 0) + return 0; + + int n = 0; + + if (haveLeftoverChar) { + // Copy the leftover char into the buffer + cbuf[off] = leftoverChar; + off++; len--; + haveLeftoverChar = false; + n = 1; + if ((len == 0) || !implReady()) + // Return now if this is all we can produce w/o blocking + return n; } - } - } - private int lockedRead(char[] cbuf, int offset, int length) throws IOException { - int off = offset; - int len = length; + if (len == 1) { + // Treat single-character array reads just like read() + int c = read0(); + if (c == -1) + return (n == 0) ? -1 : n; + cbuf[off] = (char)c; + return n + 1; + } - ensureOpen(); - if ((off < 0) || (off > cbuf.length) || (len < 0) || - ((off + len) > cbuf.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } - if (len == 0) - return 0; - - int n = 0; - - if (haveLeftoverChar) { - // Copy the leftover char into the buffer - cbuf[off] = leftoverChar; - off++; len--; - haveLeftoverChar = false; - n = 1; - if ((len == 0) || !implReady()) - // Return now if this is all we can produce w/o blocking - return n; - } + // Read remaining characters + int nr = implRead(cbuf, off, off + len); - if (len == 1) { - // Treat single-character array reads just like read() - int c = read0(); - if (c == -1) - return (n == 0) ? -1 : n; - cbuf[off] = (char)c; - return n + 1; + // At this point, n is either 1 if a leftover character was read, + // or 0 if no leftover character was read. If n is 1 and nr is -1, + // indicating EOF, then we don't return their sum as this loses data. + return (nr < 0) ? (n == 1 ? 1 : nr) : (n + nr); } - - // Read remaining characters - int nr = implRead(cbuf, off, off + len); - - // At this point, n is either 1 if a leftover character was read, - // or 0 if no leftover character was read. If n is 1 and nr is -1, - // indicating EOF, then we don't return their sum as this loses data. - return (nr < 0) ? (n == 1 ? 1 : nr) : (n + nr); } public boolean ready() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return lockedReady(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return lockedReady(); - } + synchronized (lock) { + ensureOpen(); + return haveLeftoverChar || implReady(); } } - private boolean lockedReady() throws IOException { - ensureOpen(); - return haveLeftoverChar || implReady(); - } - public void close() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { + if (closed) + return; try { - lockedClose(); + implClose(); } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedClose(); + closed = true; } } } - private void lockedClose() throws IOException { - if (closed) - return; - try { - implClose(); - } finally { - closed = true; - } - } - private boolean isOpen() { return !closed; } public void fillZeroToPosition() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedFillZeroToPosition(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedFillZeroToPosition(); - } + synchronized (lock) { + Arrays.fill(bb.array(), bb.arrayOffset(), + bb.arrayOffset() + bb.position(), (byte)0); } } - private void lockedFillZeroToPosition() { - Arrays.fill(bb.array(), bb.arrayOffset(), bb.arrayOffset() + bb.position(), (byte)0); - } - // -- Charset-based stream decoder impl -- private final Charset cs; diff --git a/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java b/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java index 3a82030121a..b580ad2f921 100644 --- a/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java +++ b/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,6 @@ import java.nio.charset.CodingErrorAction; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; -import jdk.internal.misc.InternalLock; public final class StreamEncoder extends Writer { @@ -97,28 +96,14 @@ public String getEncoding() { } public void flushBuffer() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedFlushBuffer(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedFlushBuffer(); - } + synchronized (lock) { + if (isOpen()) + implFlushBuffer(); + else + throw new IOException("Stream closed"); } } - private void lockedFlushBuffer() throws IOException { - if (isOpen()) - implFlushBuffer(); - else - throw new IOException("Stream closed"); - } - public void write(int c) throws IOException { char[] cbuf = new char[1]; cbuf[0] = (char) c; @@ -126,30 +111,16 @@ public void write(int c) throws IOException { } public void write(char[] cbuf, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedWrite(cbuf, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedWrite(cbuf, off, len); - } - } - } - - private void lockedWrite(char[] cbuf, int off, int len) throws IOException { - ensureOpen(); - if ((off < 0) || (off > cbuf.length) || (len < 0) || + synchronized (lock) { + ensureOpen(); + if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return; + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return; + } + implWrite(cbuf, off, len); } - implWrite(cbuf, off, len); } public void write(String str, int off, int len) throws IOException { @@ -164,76 +135,34 @@ public void write(String str, int off, int len) throws IOException { public void write(CharBuffer cb) throws IOException { int position = cb.position(); try { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedWrite(cb); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedWrite(cb); - } + synchronized (lock) { + ensureOpen(); + implWrite(cb); } } finally { cb.position(position); } } - private void lockedWrite(CharBuffer cb) throws IOException { - ensureOpen(); - implWrite(cb); - } - public void flush() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedFlush(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedFlush(); - } + synchronized (lock) { + ensureOpen(); + implFlush(); } } - private void lockedFlush() throws IOException { - ensureOpen(); - implFlush(); - } - public void close() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { + if (closed) + return; try { - lockedClose(); + implClose(); } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedClose(); + closed = true; } } } - private void lockedClose() throws IOException { - if (closed) - return; - try { - implClose(); - } finally { - closed = true; - } - } - private boolean isOpen() { return !closed; } diff --git a/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java b/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java index d2cd7217942..e2ac950f01d 100644 --- a/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java +++ b/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,8 +26,6 @@ package sun.nio.fs; import java.nio.file.*; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.io.IOException; import java.util.*; @@ -54,22 +52,14 @@ protected AbstractPoller() { /** * Starts the poller thread */ - @SuppressWarnings("removal") public void start() { - final Runnable thisRunnable = this; - AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Object run() { - Thread thr = new Thread(null, - thisRunnable, - "FileSystemWatchService", - 0, - false); - thr.setDaemon(true); - thr.start(); - return null; - } - }); + Thread thr = new Thread(null, + this, + "FileSystemWatchService", + 0, + false); + thr.setDaemon(true); + thr.start(); } /** diff --git a/src/java.base/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java b/src/java.base/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java index c01cec55dfe..14c809d9f3f 100644 --- a/src/java.base/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java +++ b/src/java.base/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,9 @@ package sun.nio.fs; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.file.attribute.UserDefinedFileAttributeView; -import java.io.IOException; import java.util.*; /** @@ -39,22 +39,6 @@ abstract class AbstractUserDefinedFileAttributeView { protected AbstractUserDefinedFileAttributeView() { } - protected void checkAccess(String file, - boolean checkRead, - boolean checkWrite) - { - assert checkRead || checkWrite; - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (checkRead) - sm.checkRead(file); - if (checkWrite) - sm.checkWrite(file); - sm.checkPermission(new RuntimePermission("accessUserDefinedAttributes")); - } - } - @Override public final String name() { return "user"; diff --git a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java index 91b5471145c..0284156ca3b 100644 --- a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java +++ b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -36,10 +36,6 @@ import java.nio.file.WatchKey; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; -import java.security.PrivilegedActionException; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; @@ -86,7 +82,6 @@ public Thread newThread(Runnable r) { /** * Register the given file with this watch service */ - @SuppressWarnings("removal") @Override WatchKey register(final Path path, WatchEvent.Kind[] events, @@ -133,30 +128,9 @@ WatchKey register(final Path path, if (!isOpen()) throw new ClosedWatchServiceException(); - // registration is done in privileged block as it requires the - // attributes of the entries in the directory. - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - @Override - public PollingWatchKey run() throws IOException { - return doPrivilegedRegister(path, eventSet); - } - }); - } catch (PrivilegedActionException pae) { - Throwable cause = pae.getCause(); - if (cause instanceof IOException ioe) - throw ioe; - throw new AssertionError(pae); - } - } + // registers directory returning a new key if not already registered or + // existing key if already registered - // registers directory returning a new key if not already registered or - // existing key if already registered - private PollingWatchKey doPrivilegedRegister(Path path, - Set> events) - throws IOException - { // check file is a directory and get its file key if possible BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); if (!attrs.isDirectory()) { @@ -183,13 +157,12 @@ private PollingWatchKey doPrivilegedRegister(Path path, watchKey.disable(); } } - watchKey.enable(events); + watchKey.enable(eventSet); return watchKey; } } - @SuppressWarnings("removal") @Override void implClose() throws IOException { synchronized (map) { @@ -200,13 +173,7 @@ void implClose() throws IOException { } map.clear(); } - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - scheduledExecutor.shutdown(); - return null; - } - }); + scheduledExecutor.shutdown(); } /** diff --git a/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java b/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java index 540a9d64110..86eadc2b2ee 100644 --- a/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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,7 +23,6 @@ * questions. */ - package sun.reflect.misc; import java.lang.reflect.Member; @@ -31,16 +30,13 @@ import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import jdk.internal.reflect.Reflection; -import sun.security.util.SecurityConstants; public final class ReflectUtil { private ReflectUtil() { } - public static Class forName(String name) - throws ClassNotFoundException { - checkPackageAccess(name); + public static Class forName(String name) throws ClassNotFoundException { return Class.forName(name); } @@ -73,182 +69,48 @@ public static void ensureMemberAccess(Class currentClass, } /** - * Does a conservative approximation of member access check. Use this if - * you don't have an actual 'userland' caller Class/ClassLoader available. - * This might be more restrictive than a precise member access check where - * you have a caller, but should never allow a member access that is - * forbidden. - * - * @param m the {@code Member} about to be accessed + * Does nothing. */ - public static void conservativeCheckMemberAccess(Member m) throws SecurityException{ - @SuppressWarnings("removal") - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) - return; - - // Check for package access on the declaring class. - // - // In addition, unless the member and the declaring class are both - // public check for access declared member permissions. - // - // This is done regardless of ClassLoader relations between the {@code - // Member m} and any potential caller. - - final Class declaringClass = m.getDeclaringClass(); - - privateCheckPackageAccess(sm, declaringClass); - - if (Modifier.isPublic(m.getModifiers()) && - Modifier.isPublic(declaringClass.getModifiers())) - return; - - // Check for declared member access. - sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); + public static void conservativeCheckMemberAccess(Member m) { } /** - * Checks package access on the given class. - * - * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements - * a non-public interface (i.e. may be in a non-restricted package), - * also check the package access on the proxy interfaces. + * Does nothing. */ public static void checkPackageAccess(Class clazz) { - @SuppressWarnings("removal") - SecurityManager s = System.getSecurityManager(); - if (s != null) { - privateCheckPackageAccess(s, clazz); - } } /** - * NOTE: should only be called if a SecurityManager is installed + * Does nothing */ - private static void privateCheckPackageAccess(@SuppressWarnings("removal") SecurityManager s, Class clazz) { - String pkg = clazz.getPackageName(); - if (!pkg.isEmpty()) { - s.checkPackageAccess(pkg); - } - - if (isNonPublicProxyClass(clazz)) { - privateCheckProxyPackageAccess(s, clazz); - } + public static void checkPackageAccess(String name) { } /** - * Checks package access on the given classname. - * This method is typically called when the Class instance is not - * available and the caller attempts to load a class on behalf - * the true caller (application). + * Returns true. */ - public static void checkPackageAccess(String name) { - @SuppressWarnings("removal") - SecurityManager s = System.getSecurityManager(); - if (s != null) { - String cname = name.replace('/', '.'); - if (cname.startsWith("[")) { - int b = cname.lastIndexOf('[') + 2; - if (b > 1 && b < cname.length()) { - cname = cname.substring(b); - } - } - int i = cname.lastIndexOf('.'); - if (i != -1) { - s.checkPackageAccess(cname.substring(0, i)); - } - } - } - public static boolean isPackageAccessible(Class clazz) { - try { - checkPackageAccess(clazz); - } catch (SecurityException e) { - return false; - } return true; } - // Returns true if p is an ancestor of cl i.e. class loader 'p' can - // be found in the cl's delegation chain - private static boolean isAncestor(ClassLoader p, ClassLoader cl) { - ClassLoader acl = cl; - do { - acl = acl.getParent(); - if (p == acl) { - return true; - } - } while (acl != null); - return false; - } - /** - * Returns true if package access check is needed for reflective - * access from a class loader 'from' to classes or members in - * a class defined by class loader 'to'. This method returns true - * if 'from' is not the same as or an ancestor of 'to'. All code - * in a system domain are granted with all permission and so this - * method returns false if 'from' class loader is a class loader - * loading system classes. On the other hand, if a class loader - * attempts to access system domain classes, it requires package - * access check and this method will return true. + * Returns false. */ public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { - if (from == null || from == to) - return false; - - if (to == null) - return true; - - return !isAncestor(from, to); + return false; } /** - * Check package access on the proxy interfaces that the given proxy class - * implements. - * - * @param clazz Proxy class object + * Does nothing */ public static void checkProxyPackageAccess(Class clazz) { - @SuppressWarnings("removal") - SecurityManager s = System.getSecurityManager(); - if (s != null) { - privateCheckProxyPackageAccess(s, clazz); - } } /** - * NOTE: should only be called if a SecurityManager is installed - */ - private static void privateCheckProxyPackageAccess(@SuppressWarnings("removal") SecurityManager s, Class clazz) { - // check proxy interfaces if the given class is a proxy class - if (Proxy.isProxyClass(clazz)) { - for (Class intf : clazz.getInterfaces()) { - privateCheckPackageAccess(s, intf); - } - } - } - /** - * Access check on the interfaces that a proxy class implements and throw - * {@code SecurityException} if it accesses a restricted package from - * the caller's class loader. - * - * @param ccl the caller's class loader - * @param interfaces the list of interfaces that a proxy class implements + * Does nothing. */ public static void checkProxyPackageAccess(ClassLoader ccl, - Class... interfaces) - { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - for (Class intf : interfaces) { - ClassLoader cl = intf.getClassLoader(); - if (needsPackageAccessCheck(ccl, cl)) { - privateCheckPackageAccess(sm, intf); - } - } - } + Class... interfaces) { } // Note that bytecode instrumentation tools may exclude 'sun.*' diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java b/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java index f15b058014a..6ccb3823e0a 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -35,7 +35,7 @@ import java.security.interfaces.*; import java.util.Arrays; -import java.util.Hashtable; +import java.util.Map; import sun.security.util.*; import sun.security.jca.JCAUtil; @@ -81,21 +81,19 @@ private boolean isDigestEqual(String stdAlg, String givenAlg) { private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8]; - private static final Hashtable DIGEST_LENGTHS = - new Hashtable<>(); - static { - DIGEST_LENGTHS.put(KnownOIDs.SHA_1, 20); - DIGEST_LENGTHS.put(KnownOIDs.SHA_224, 28); - DIGEST_LENGTHS.put(KnownOIDs.SHA_256, 32); - DIGEST_LENGTHS.put(KnownOIDs.SHA_384, 48); - DIGEST_LENGTHS.put(KnownOIDs.SHA_512, 64); - DIGEST_LENGTHS.put(KnownOIDs.SHA_512$224, 28); - DIGEST_LENGTHS.put(KnownOIDs.SHA_512$256, 32); - DIGEST_LENGTHS.put(KnownOIDs.SHA3_224, 28); - DIGEST_LENGTHS.put(KnownOIDs.SHA3_256, 32); - DIGEST_LENGTHS.put(KnownOIDs.SHA3_384, 48); - DIGEST_LENGTHS.put(KnownOIDs.SHA3_512, 64); - } + private static final Map DIGEST_LENGTHS = Map.ofEntries( + Map.entry(KnownOIDs.SHA_1, 20), + Map.entry(KnownOIDs.SHA_224, 28), + Map.entry(KnownOIDs.SHA_256, 32), + Map.entry(KnownOIDs.SHA_384, 48), + Map.entry(KnownOIDs.SHA_512, 64), + Map.entry(KnownOIDs.SHA_512$224, 28), + Map.entry(KnownOIDs.SHA_512$256, 32), + Map.entry(KnownOIDs.SHA3_224, 28), + Map.entry(KnownOIDs.SHA3_256, 32), + Map.entry(KnownOIDs.SHA3_384, 48), + Map.entry(KnownOIDs.SHA3_512, 64) + ); // message digest implementation we use for hashing the data private MessageDigest md; diff --git a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index bc463d01faf..7612242733e 100644 --- a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, 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 @@ -42,21 +42,21 @@ import java.security.spec.PSSParameterSpec; import java.time.DateTimeException; import java.time.Instant; -import java.time.ZonedDateTime; import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.Collection; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Algorithm constraints for disabled algorithms property @@ -101,6 +101,7 @@ private static class JarHolder { } private final Set disabledAlgorithms; + private final List disabledPatterns; private final Constraints algorithmConstraints; private volatile SoftReference> cacheRef = new SoftReference<>(null); @@ -136,6 +137,13 @@ public DisabledAlgorithmConstraints(String propertyName, super(decomposer); disabledAlgorithms = getAlgorithms(propertyName); + // Support patterns only for jdk.tls.disabledAlgorithms + if (PROPERTY_TLS_DISABLED_ALGS.equals(propertyName)) { + disabledPatterns = getDisabledPatterns(); + } else { + disabledPatterns = null; + } + // Check for alias for (String s : disabledAlgorithms) { Matcher matcher = INCLUDE_PATTERN.matcher(s); @@ -967,11 +975,48 @@ private boolean cachedCheckAlgorithm(String algorithm) { if (result != null) { return result; } - result = checkAlgorithm(disabledAlgorithms, algorithm, decomposer); + // We won't check patterns if algorithm check fails. + result = checkAlgorithm(disabledAlgorithms, algorithm, decomposer) + && checkDisabledPatterns(algorithm); cache.put(algorithm, result); return result; } + private boolean checkDisabledPatterns(final String algorithm) { + return disabledPatterns == null || disabledPatterns.stream().noneMatch( + p -> p.matcher(algorithm).matches()); + } + + private List getDisabledPatterns() { + List ret = null; + List patternStrings = new ArrayList<>(4); + + for (String p : disabledAlgorithms) { + if (p.contains("*")) { + if (!p.startsWith("TLS_")) { + throw new IllegalArgumentException( + "Wildcard pattern must start with \"TLS_\""); + } + patternStrings.add(p); + } + } + + if (!patternStrings.isEmpty()) { + ret = new ArrayList<>(patternStrings.size()); + + for (String p : patternStrings) { + // Exclude patterns from algorithm code flow. + disabledAlgorithms.remove(p); + + // Ignore all regex characters but asterisk. + ret.add(Pattern.compile( + "^\\Q" + p.replace("*", "\\E.*\\Q") + "\\E$")); + } + } + + return ret; + } + /* * This constraint is used for the complete disabling of the algorithm. */ diff --git a/src/java.base/share/classes/sun/security/util/SecurityConstants.java b/src/java.base/share/classes/sun/security/util/SecurityConstants.java index df2861f3034..21ec592c766 100644 --- a/src/java.base/share/classes/sun/security/util/SecurityConstants.java +++ b/src/java.base/share/classes/sun/security/util/SecurityConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -72,30 +72,6 @@ private SecurityConstants () { public static final NetPermission SPECIFY_HANDLER_PERMISSION = new NetPermission("specifyStreamHandler"); - // java.net.ProxySelector - public static final NetPermission SET_PROXYSELECTOR_PERMISSION = - new NetPermission("setProxySelector"); - - // java.net.ProxySelector - public static final NetPermission GET_PROXYSELECTOR_PERMISSION = - new NetPermission("getProxySelector"); - - // java.net.CookieHandler - public static final NetPermission SET_COOKIEHANDLER_PERMISSION = - new NetPermission("setCookieHandler"); - - // java.net.CookieHandler - public static final NetPermission GET_COOKIEHANDLER_PERMISSION = - new NetPermission("getCookieHandler"); - - // java.net.ResponseCache - public static final NetPermission SET_RESPONSECACHE_PERMISSION = - new NetPermission("setResponseCache"); - - // java.net.ResponseCache - public static final NetPermission GET_RESPONSECACHE_PERMISSION = - new NetPermission("getResponseCache"); - // java.net.ServerSocket, java.net.Socket public static final NetPermission SET_SOCKETIMPL_PERMISSION = new NetPermission("setSocketImpl"); diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 1d329df0cfb..6374c1951bd 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -729,7 +729,11 @@ http.auth.digest.disabledAlgorithms = MD5, SHA-1 # This is in addition to the jdk.certpath.disabledAlgorithms property above. # # See the specification of "jdk.certpath.disabledAlgorithms" for the -# syntax of the disabled algorithm string. +# syntax of the disabled algorithm string. Additionally, TLS cipher suites +# can be disabled with this property using one or more "*" wildcard characters. +# For example, "TLS_RSA_*" disables all cipher suites that start with +# "TLS_RSA_". Only cipher suites starting with "TLS_" are allowed to have +# wildcard characters. # # Note: The algorithm restrictions do not apply to trust anchors or # self-signed certificates. @@ -739,7 +743,7 @@ http.auth.digest.disabledAlgorithms = MD5, SHA-1 # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \ -# rsa_pkcs1_sha1, secp224r1 +# rsa_pkcs1_sha1, secp224r1, TLS_RSA_* jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \ MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ ECDH diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 deleted file mode 100644 index da7fb86099f..00000000000 --- a/src/java.base/share/man/java.1 +++ /dev/null @@ -1,5409 +0,0 @@ -.\" Copyright (c) 1994, 2024, 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. -.\" -'\" t -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JAVA" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -java - launch a Java application -.SH SYNOPSIS -.PP -To launch a class file: -.PP -\f[V]java\f[R] [\f[I]options\f[R]] \f[I]mainclass\f[R] [\f[I]args\f[R] -\&...] -.PP -To launch the main class in a JAR file: -.PP -\f[V]java\f[R] [\f[I]options\f[R]] \f[V]-jar\f[R] \f[I]jarfile\f[R] -[\f[I]args\f[R] ...] -.PP -To launch the main class in a module: -.PP -\f[V]java\f[R] [\f[I]options\f[R]] \f[V]-m\f[R] -\f[I]module\f[R][\f[V]/\f[R]\f[I]mainclass\f[R]] [\f[I]args\f[R] ...] -.PP -or -.PP -\f[V]java\f[R] [\f[I]options\f[R]] \f[V]--module\f[R] -\f[I]module\f[R][\f[V]/\f[R]\f[I]mainclass\f[R]] [\f[I]args\f[R] ...] -.PP -To launch a source-file program: -.PP -\f[V]java\f[R] [\f[I]options\f[R]] \f[I]source-file\f[R] [\f[I]args\f[R] -\&...] -.TP -\f[I]options\f[R] -Optional: Specifies command-line options separated by spaces. -See \f[B]Overview of Java Options\f[R] for a description of available -options. -.TP -\f[I]mainclass\f[R] -Specifies the name of the class to be launched. -Command-line entries following \f[V]classname\f[R] are the arguments for -the main method. -.TP -\f[V]-jar\f[R] \f[I]jarfile\f[R] -Executes a program encapsulated in a JAR file. -The \f[I]jarfile\f[R] argument is the name of a JAR file with a manifest -that contains a line in the form -\f[V]Main-Class:\f[R]\f[I]classname\f[R] that defines the class with the -\f[V]public static void main(String[] args)\f[R] method that serves as -your application\[aq]s starting point. -When you use \f[V]-jar\f[R], the specified JAR file is the source of all -user classes, and other class path settings are ignored. -If you\[aq]re using JAR files, then see \f[B]jar\f[R]. -.TP -\f[V]-m\f[R] or \f[V]--module\f[R] \f[I]module\f[R][\f[V]/\f[R]\f[I]mainclass\f[R]] -Executes the main class in a module specified by \f[I]mainclass\f[R] if -it is given, or, if it is not given, the value in the \f[I]module\f[R]. -In other words, \f[I]mainclass\f[R] can be used when it is not specified -by the module, or to override the value when it is specified. -.RS -.PP -See \f[B]Standard Options for Java\f[R]. -.RE -.TP -\f[I]source-file\f[R] -Only used to launch a source-file program. -Specifies the source file that contains the main class when using -source-file mode. -See \f[B]Using Source-File Mode to Launch Source-Code Programs\f[R] -.TP -\f[I]args\f[R] ... -Optional: Arguments following \f[I]mainclass\f[R], -\f[I]source-file\f[R], \f[V]-jar\f[R] \f[I]jarfile\f[R], and -\f[V]-m\f[R] or \f[V]--module\f[R] -\f[I]module\f[R]\f[V]/\f[R]\f[I]mainclass\f[R] are passed as arguments -to the main class. -.SH DESCRIPTION -.PP -The \f[V]java\f[R] command starts a Java application. -It does this by starting the Java Virtual Machine (JVM), loading the -specified class, and calling that class\[aq]s \f[V]main()\f[R] method. -The method must be declared \f[V]public\f[R] and \f[V]static\f[R], it -must not return any value, and it must accept a \f[V]String\f[R] array -as a parameter. -The method declaration has the following form: -.RS -.PP -\f[V]public static void main(String[] args)\f[R] -.RE -.PP -In source-file mode, the \f[V]java\f[R] command can launch a class -declared in a source file. -See \f[B]Using Source-File Mode to Launch Source-Code Programs\f[R] for -a description of using the source-file mode. -.RS -.PP -\f[B]Note:\f[R] You can use the \f[V]JDK_JAVA_OPTIONS\f[R] launcher -environment variable to prepend its content to the actual command line -of the \f[V]java\f[R] launcher. -See \f[B]Using the JDK_JAVA_OPTIONS Launcher Environment Variable\f[R]. -.RE -.PP -By default, the first argument that isn\[aq]t an option of the -\f[V]java\f[R] command is the fully qualified name of the class to be -called. -If \f[V]-jar\f[R] is specified, then its argument is the name of the JAR -file containing class and resource files for the application. -The startup class must be indicated by the \f[V]Main-Class\f[R] manifest -header in its manifest file. -.PP -Arguments after the class file name or the JAR file name are passed to -the \f[V]main()\f[R] method. -.SS \f[V]javaw\f[R] -.PP -\f[B]Windows:\f[R] The \f[V]javaw\f[R] command is identical to -\f[V]java\f[R], except that with \f[V]javaw\f[R] there\[aq]s no -associated console window. -Use \f[V]javaw\f[R] when you don\[aq]t want a command prompt window to -appear. -The \f[V]javaw\f[R] launcher will, however, display a dialog box with -error information if a launch fails. -.SH USING SOURCE-FILE MODE TO LAUNCH SOURCE-CODE PROGRAMS -.PP -To launch a class declared in a source file, run the \f[V]java\f[R] -launcher in source-file mode. -Entering source-file mode is determined by two items on the -\f[V]java\f[R] command line: -.IP \[bu] 2 -The first item on the command line that is not an option or part of an -option. -In other words, the item in the command line that would otherwise be the -main class name. -.IP \[bu] 2 -The \f[V]--source\f[R] \f[I]version\f[R] option, if present. -.PP -If the class identifies an existing file that has a \f[V].java\f[R] -extension, or if the \f[V]--source\f[R] option is specified, then -source-file mode is selected. -The source file is then compiled and run. -The \f[V]--source\f[R] option can be used to specify the source -\f[I]version\f[R] or \f[I]N\f[R] of the source code. -This determines the API that can be used. -When you set \f[V]--source\f[R] \f[I]N\f[R], you can only use the public -API that was defined in JDK \f[I]N\f[R]. -.RS -.PP -\f[B]Note:\f[R] The valid values of \f[I]N\f[R] change for each release, -with new values added and old values removed. -You\[aq]ll get an error message if you use a value of \f[I]N\f[R] that -is no longer supported. -The supported values of \f[I]N\f[R] are the current Java SE release -(\f[V]24\f[R]) and a limited number of previous releases, detailed in -the command-line help for \f[V]javac\f[R], under the \f[V]--source\f[R] -and \f[V]--release\f[R] options. -.RE -.PP -If the file does not have the \f[V].java\f[R] extension, the -\f[V]--source\f[R] option must be used to tell the \f[V]java\f[R] -command to use the source-file mode. -The \f[V]--source\f[R] option is used for cases when the source file is -a \[dq]script\[dq] to be executed and the name of the source file does -not follow the normal naming conventions for Java source files. -.PP -In source-file mode, the effect is as though the source file is compiled -into memory, and the first class found in the source file is executed. -Any arguments placed after the name of the source file in the original -command line are passed to the compiled class when it is executed. -.PP -For example, if a file were named \f[V]HelloWorld.java\f[R] and -contained a class named \f[V]HelloWorld\f[R], then the source-file mode -command to launch the class would be: -.RS -.PP -\f[V]java HelloWorld.java\f[R] -.RE -.PP -This use of source-file mode is informally equivalent to using the -following two commands: -.IP -.nf -\f[CB] -javac -d --source-path HelloWorld.java -java --class-path HelloWorld -\f[R] -.fi -.PP -where \f[V]\f[R] is computed -.PP -\f[B]In source-file mode, any additional command-line options are -processed as follows:\f[R] -.IP \[bu] 2 -The launcher scans the options specified before the source file for any -that are relevant in order to compile the source file. -.RS 2 -.PP -This includes: \f[V]--class-path\f[R], \f[V]--module-path\f[R], -\f[V]--add-exports\f[R], \f[V]--add-modules\f[R], -\f[V]--limit-modules\f[R], \f[V]--patch-module\f[R], -\f[V]--upgrade-module-path\f[R], and any variant forms of those options. -It also includes the new \f[V]--enable-preview\f[R] option, described in -JEP 12. -.RE -.IP \[bu] 2 -No provision is made to pass any additional options to the compiler, -such as \f[V]-processor\f[R] or \f[V]-Werror\f[R]. -.IP \[bu] 2 -Command-line argument files (\f[V]\[at]\f[R]-files) may be used in the -standard way. -Long lists of arguments for either the VM or the program being invoked -may be placed in files specified on the command-line by prefixing the -filename with an \f[V]\[at]\f[R] character. -.PP -\f[B]In source-file mode, compilation proceeds as follows:\f[R] -.IP \[bu] 2 -Any command-line options that are relevant to the compilation -environment are taken into account. -These include: -\f[V]--class-path\f[R]/\f[V]-classpath\f[R]/\f[V]-cp\f[R], -\f[V]--module-path\f[R]/\f[V]-p\f[R], \f[V]--add-exports\f[R], -\f[V]--add-modules\f[R], \f[V]--limit-modules\f[R], -\f[V]--patch-module\f[R], \f[V]--upgrade-module-path\f[R], -\f[V]--enable-preview\f[R]. -.IP \[bu] 2 -The root of the source tree, \f[V]\f[R] is computed from -the package of the class being launched. -For example, if \f[V]HelloWorld.java\f[R] declared its classes to be in -the \f[V]hello\f[R] package, then the file \f[V]HelloWorld.java\f[R] is -expected to reside in the directory \f[V]somedir/hello/\f[R]. -In this case, \f[V]somedir\f[R] is computed to be the root of the source -tree. -.IP \[bu] 2 -The root of the source tree serves as the source-path for compilation, -so that other source files found in that tree and are needed by -\f[V]HelloWorld\f[R] could be compiled. -.IP \[bu] 2 -Annotation processing is disabled, as if \f[V]-proc:none\f[R] is in -effect. -.IP \[bu] 2 -If a version is specified, via the \f[V]--source\f[R] option, the value -is used as the argument for an implicit \f[V]--release\f[R] option for -the compilation. -This sets both the source version accepted by compiler and the system -API that may be used by the code in the source file. -.IP \[bu] 2 -If \f[V]--enable-preview\f[R] is specified, the \f[V]--source N\f[R] -arguments can be omitted. -If the Java runtime version is \f[V]N\f[R], then \f[V]--release N\f[R] -is implied when compiling source files. -.IP \[bu] 2 -If a \f[V]module-info.java\f[R] file exists in the -\f[V]\f[R] directory, its module declaration is used to -define a named module that will contain all the classes compiled from -\f[V].java\f[R] files in the source tree. -If \f[V]module-info.java\f[R] does not exist, all the classes compiled -from source files will be compiled in the context of the unnamed module. -.IP \[bu] 2 -The source file that is launched should contain one or more top-level -classes, the first of which is taken as the class to be executed. -.IP \[bu] 2 -For the source file that is launched, the compiler does not enforce the -optional restriction defined at the end of JLS 7.6, that a type in a -named package should exist in a file whose name is composed from the -type name followed by the \f[V].java\f[R] extension. -.IP \[bu] 2 -If a source file contains errors, appropriate error messages are written -to the standard error stream, and the launcher exits with a non-zero -exit code. -.PP -\f[B]In source-file mode, execution proceeds as follows:\f[R] -.IP \[bu] 2 -The class to be executed is the first top-level class found in the -source file. -It must contain a declaration of an entry \f[V]main\f[R] method. -.IP \[bu] 2 -The compiled classes are loaded by a custom class loader, that delegates -to the application class loader. -This implies that classes appearing on the application class path cannot -refer to any classes declared in source files. -.IP \[bu] 2 -If a \f[V]module-info.java\f[R] file exists in the -\f[V]\f[R] directory, then all the classes compiled from -\f[V].java\f[R] files in the source tree will be in that module, which -will serve as the root module for the execution of the program. -If \f[V]module-info.java\f[R] does not exist, the compiled classes are -executed in the context of an unnamed module, as though -\f[V]--add-modules=ALL-DEFAULT\f[R] is in effect. -This is in addition to any other \f[V]--add-module\f[R] options that may -be have been specified on the command line. -.IP \[bu] 2 -Any arguments appearing after the name of the file on the command line -are passed to the main method in the obvious way. -.IP \[bu] 2 -It is an error if there is a class on the application class path whose -name is the same as that of the class to be executed. -.PP -See \f[B]JEP 458: Launch Multi-File Source-Code Programs\f[R] -[https://openjdk.org/jeps/458] for complete details. -.SH USING THE JDK_JAVA_OPTIONS LAUNCHER ENVIRONMENT VARIABLE -.PP -\f[V]JDK_JAVA_OPTIONS\f[R] prepends its content to the options parsed -from the command line. -The content of the \f[V]JDK_JAVA_OPTIONS\f[R] environment variable is a -list of arguments separated by white-space characters (as determined by -\f[V]isspace()\f[R]). -These are prepended to the command line arguments passed to -\f[V]java\f[R] launcher. -The encoding requirement for the environment variable is the same as the -\f[V]java\f[R] command line on the system. -\f[V]JDK_JAVA_OPTIONS\f[R] environment variable content is treated in -the same manner as that specified in the command line. -.PP -Single (\f[V]\[aq]\f[R]) or double (\f[V]\[dq]\f[R]) quotes can be used -to enclose arguments that contain whitespace characters. -All content between the open quote and the first matching close quote -are preserved by simply removing the pair of quotes. -In case a matching quote is not found, the launcher will abort with an -error message. -\f[V]\[at]\f[R]-files are supported as they are specified in the command -line. -However, as in \f[V]\[at]\f[R]-files, use of a wildcard is not -supported. -In order to mitigate potential misuse of \f[V]JDK_JAVA_OPTIONS\f[R] -behavior, options that specify the main class (such as \f[V]-jar\f[R]) -or cause the \f[V]java\f[R] launcher to exit without executing the main -class (such as \f[V]-h\f[R]) are disallowed in the environment variable. -If any of these options appear in the environment variable, the launcher -will abort with an error message. -When \f[V]JDK_JAVA_OPTIONS\f[R] is set, the launcher prints a message to -stderr as a reminder. -.PP -\f[B]Example:\f[R] -.IP -.nf -\f[CB] -$ export JDK_JAVA_OPTIONS=\[aq]-g \[at]file1 -Dprop=value \[at]file2 -Dws.prop=\[dq]white spaces\[dq]\[aq] -$ java -Xint \[at]file3 -\f[R] -.fi -.PP -is equivalent to the command line: -.IP -.nf -\f[CB] -java -g \[at]file1 -Dprop=value \[at]file2 -Dws.prop=\[dq]white spaces\[dq] -Xint \[at]file3 -\f[R] -.fi -.SH OVERVIEW OF JAVA OPTIONS -.PP -The \f[V]java\f[R] command supports a wide range of options in the -following categories: -.IP \[bu] 2 -\f[B]Standard Options for Java\f[R]: Options guaranteed to be supported -by all implementations of the Java Virtual Machine (JVM). -They\[aq]re used for common actions, such as checking the version of the -JRE, setting the class path, enabling verbose output, and so on. -.IP \[bu] 2 -\f[B]Extra Options for Java\f[R]: General purpose options that are -specific to the Java HotSpot Virtual Machine. -They aren\[aq]t guaranteed to be supported by all JVM implementations, -and are subject to change. -These options start with \f[V]-X\f[R]. -.PP -The advanced options aren\[aq]t recommended for casual use. -These are developer options used for tuning specific areas of the Java -HotSpot Virtual Machine operation that often have specific system -requirements and may require privileged access to system configuration -parameters. -Several examples of performance tuning are provided in \f[B]Performance -Tuning Examples\f[R]. -These options aren\[aq]t guaranteed to be supported by all JVM -implementations and are subject to change. -Advanced options start with \f[V]-XX\f[R]. -.IP \[bu] 2 -\f[B]Advanced Runtime Options for Java\f[R]: Control the runtime -behavior of the Java HotSpot VM. -.IP \[bu] 2 -\f[B]Advanced JIT Compiler Options for java\f[R]: Control the dynamic -just-in-time (JIT) compilation performed by the Java HotSpot VM. -.IP \[bu] 2 -\f[B]Advanced Serviceability Options for Java\f[R]: Enable gathering -system information and performing extensive debugging. -.IP \[bu] 2 -\f[B]Advanced Garbage Collection Options for Java\f[R]: Control how -garbage collection (GC) is performed by the Java HotSpot -.PP -Boolean options are used to either enable a feature that\[aq]s disabled -by default or disable a feature that\[aq]s enabled by default. -Such options don\[aq]t require a parameter. -Boolean \f[V]-XX\f[R] options are enabled using the plus sign -(\f[V]-XX:+\f[R]\f[I]OptionName\f[R]) and disabled using the minus sign -(\f[V]-XX:-\f[R]\f[I]OptionName\f[R]). -.PP -For options that require an argument, the argument may be separated from -the option name by a space, a colon (:), or an equal sign (=), or the -argument may directly follow the option (the exact syntax differs for -each option). -If you\[aq]re expected to specify the size in bytes, then you can use no -suffix, or use the suffix \f[V]k\f[R] or \f[V]K\f[R] for kilobytes (KB), -\f[V]m\f[R] or \f[V]M\f[R] for megabytes (MB), or \f[V]g\f[R] or -\f[V]G\f[R] for gigabytes (GB). -For example, to set the size to 8 GB, you can specify either -\f[V]8g\f[R], \f[V]8192m\f[R], \f[V]8388608k\f[R], or -\f[V]8589934592\f[R] as the argument. -If you are expected to specify the percentage, then use a number from 0 -to 1. -For example, specify \f[V]0.25\f[R] for 25%. -.PP -The following sections describe the options that are deprecated, -obsolete, and removed: -.IP \[bu] 2 -\f[B]Deprecated Java Options\f[R]: Accepted and acted upon --- a warning -is issued when they\[aq]re used. -.IP \[bu] 2 -\f[B]Obsolete Java Options\f[R]: Accepted but ignored --- a warning is -issued when they\[aq]re used. -.IP \[bu] 2 -\f[B]Removed Java Options\f[R]: Removed --- using them results in an -error. -.SH STANDARD OPTIONS FOR JAVA -.PP -These are the most commonly used options supported by all -implementations of the JVM. -.RS -.PP -\f[B]Note:\f[R] To specify an argument for a long option, you can use -either \f[V]--\f[R]\f[I]name\f[R]\f[V]=\f[R]\f[I]value\f[R] or -\f[V]--\f[R]\f[I]name\f[R] \f[I]value\f[R]. -.RE -.TP -\f[V]-agentlib:\f[R]\f[I]libname\f[R][\f[V]=\f[R]\f[I]options\f[R]] -Loads the specified native agent library. -After the library name, a comma-separated list of options specific to -the library can be used. -If the option \f[V]-agentlib:foo\f[R] is specified, then the JVM -attempts to load the library named \f[V]foo\f[R] using the platform -specific naming conventions and locations: -.RS -.IP \[bu] 2 -\f[B]Linux and other POSIX-like platforms:\f[R] The JVM attempts to load -the library named \f[V]libfoo.so\f[R] in the location specified by the -\f[V]LD_LIBRARY_PATH\f[R] system variable. -.IP \[bu] 2 -\f[B]macOS:\f[R] The JVM attempts to load the library named -\f[V]libfoo.dylib\f[R] in the location specified by the -\f[V]DYLD_LIBRARY_PATH\f[R] system variable. -.IP \[bu] 2 -\f[B]Windows:\f[R] The JVM attempts to load the library named -\f[V]foo.dll\f[R] in the location specified by the \f[V]PATH\f[R] system -variable. -.RS 2 -.PP -The following example shows how to load the Java Debug Wire Protocol -(JDWP) library and listen for the socket connection on port 8000, -suspending the JVM before the main class loads: -.RS -.PP -\f[V]-agentlib:jdwp=transport=dt_socket,server=y,address=8000\f[R] -.RE -.RE -.RE -.TP -\f[V]-agentpath:\f[R]\f[I]pathname\f[R][\f[V]=\f[R]\f[I]options\f[R]] -Loads the native agent library specified by the absolute path name. -This option is equivalent to \f[V]-agentlib\f[R] but uses the full path -and file name of the library. -.TP -\f[V]--class-path\f[R] \f[I]classpath\f[R], \f[V]-classpath\f[R] \f[I]classpath\f[R], or \f[V]-cp\f[R] \f[I]classpath\f[R] -Specifies a list of directories, JAR files, and ZIP archives to search -for class files. -.RS -.PP -On Windows, semicolons (\f[V];\f[R]) separate entities in this list; on -other platforms it is a colon (\f[V]:\f[R]). -.PP -Specifying \f[I]classpath\f[R] overrides any setting of the -\f[V]CLASSPATH\f[R] environment variable. -If the class path option isn\[aq]t used and \f[I]classpath\f[R] -isn\[aq]t set, then the user class path consists of the current -directory (.). -.PP -As a special convenience, a class path element that contains a base name -of an asterisk (*) is considered equivalent to specifying a list of all -the files in the directory with the extension \f[V].jar\f[R] or -\f[V].JAR\f[R] . -A Java program can\[aq]t tell the difference between the two -invocations. -For example, if the directory mydir contains \f[V]a.jar\f[R] and -\f[V]b.JAR\f[R], then the class path element mydir/* is expanded to -\f[V]A.jar:b.JAR\f[R], except that the order of JAR files is -unspecified. -All \f[V].jar\f[R] files in the specified directory, even hidden ones, -are included in the list. -A class path entry consisting of an asterisk (*) expands to a list of -all the jar files in the current directory. -The \f[V]CLASSPATH\f[R] environment variable, where defined, is -similarly expanded. -Any class path wildcard expansion that occurs before the Java VM is -started. -Java programs never see wildcards that aren\[aq]t expanded except by -querying the environment, such as by calling -\f[V]System.getenv(\[dq]CLASSPATH\[dq])\f[R]. -.RE -.TP -\f[V]--disable-\[at]files\f[R] -Can be used anywhere on the command line, including in an argument file, -to prevent further \f[V]\[at]filename\f[R] expansion. -This option stops expanding \f[V]\[at]\f[R]-argfiles after the option. -.TP -\f[V]--enable-preview\f[R] -Allows classes to depend on \f[B]preview features\f[R] -[https://docs.oracle.com/en/java/javase/12/language/index.html#JSLAN-GUID-5A82FE0E-0CA4-4F1F-B075-564874FE2823] -of the release. -.TP -\f[V]--enable-native-access\f[R] \f[I]module\f[R][\f[V],\f[R]\f[I]module\f[R]...] -Native access involves access to code or data outside the Java runtime. -This is generally unsafe and, if done incorrectly, might crash the JVM -or result in memory corruption. -Native access can occur as a result of calling a method that is either -\f[B]restricted\f[R] [https://openjdk.org/jeps/454#Safety], or -\f[V]native\f[R]. -This option allows code in the specified modules to perform native -access. -Native access occurring in a module that has not been explicitly enabled -is deemed \f[I]illegal\f[R]. -.RS -.PP -\f[I]module\f[R] can be a module name, or \f[V]ALL-UNNAMED\f[R] to -indicate code on the class path. -.RE -.TP --\f[V]--illegal-native-access=\f[R]\f[I]parameter\f[R] -This option specifies a mode for how illegal native access is handled: -.RS -.RS -.PP -\f[B]Note:\f[R] This option will be removed in a future release. -.RE -.IP \[bu] 2 -\f[V]allow\f[R]: This mode allows illegal native access in all modules, -without any warings. -.IP \[bu] 2 -\f[V]warn\f[R]: This mode is identical to \f[V]allow\f[R] except that a -warning message is issued for the first illegal native access found in a -module. -This mode is the default for the current JDK but will change in a future -release. -.IP \[bu] 2 -\f[V]deny\f[R]: This mode disables illegal native access. -That is, any illegal native access causes an -\f[V]IllegalCallerException\f[R]. -This mode will become the default in a future release. -.PP -To verify that your application is ready for a future version of the -JDK, run it with \f[V]--illegal-native-access=deny\f[R] along with any -necessary \f[V]--enable-native-access\f[R] options. -.RE -.TP -\f[V]--finalization=\f[R]\f[I]value\f[R] -Controls whether the JVM performs finalization of objects. -Valid values are \[dq]enabled\[dq] and \[dq]disabled\[dq]. -Finalization is enabled by default, so the value \[dq]enabled\[dq] does -nothing. -The value \[dq]disabled\[dq] disables finalization, so that no -finalizers are invoked. -.TP -\f[V]--module-path\f[R] \f[I]modulepath\f[R]... or \f[V]-p\f[R] \f[I]modulepath\f[R] -Specifies where to find application modules with a list of path -elements. -The elements of a module path can be a file path to a module or a -directory containing modules. -Each module is either a modular JAR or an exploded-module directory. -.RS -.PP -On Windows, semicolons (\f[V];\f[R]) separate path elements in this -list; on other platforms it is a colon (\f[V]:\f[R]). -.RE -.TP -\f[V]--upgrade-module-path\f[R] \f[I]modulepath\f[R]... -Specifies where to find module replacements of upgradeable modules in -the runtime image with a list of path elements. -The elements of a module path can be a file path to a module or a -directory containing modules. -Each module is either a modular JAR or an exploded-module directory. -.RS -.PP -On Windows, semicolons (\f[V];\f[R]) separate path elements in this -list; on other platforms it is a colon (\f[V]:\f[R]). -.RE -.TP -\f[V]--add-modules\f[R] \f[I]module\f[R][\f[V],\f[R]\f[I]module\f[R]...] -Specifies the root modules to resolve in addition to the initial module. -\f[I]module\f[R] can also be \f[V]ALL-DEFAULT\f[R], -\f[V]ALL-SYSTEM\f[R], and \f[V]ALL-MODULE-PATH\f[R]. -.TP -\f[V]--list-modules\f[R] -Lists the observable modules and then exits. -.TP -\f[V]-d\f[R] \f[I]module_name\f[R] or \f[V]--describe-module\f[R] \f[I]module_name\f[R] -Describes a specified module and then exits. -.TP -\f[V]--dry-run\f[R] -Creates the VM but doesn\[aq]t execute the main method. -This \f[V]--dry-run\f[R] option might be useful for validating the -command-line options such as the module system configuration. -.TP -\f[V]--validate-modules\f[R] -Validates all modules and exit. -This option is helpful for finding conflicts and other errors with -modules on the module path. -.TP -\f[V]-D\f[R]\f[I]property\f[R]\f[V]=\f[R]\f[I]value\f[R] -Sets a system property value. -The \f[I]property\f[R] variable is a string with no spaces that -represents the name of the property. -The \f[I]value\f[R] variable is a string that represents the value of -the property. -If \f[I]value\f[R] is a string with spaces, then enclose it in quotation -marks (for example \f[V]-Dfoo=\[dq]foo bar\[dq]\f[R]). -.TP -\f[V]-disableassertions\f[R][\f[V]:\f[R][\f[I]packagename\f[R]]...|\f[V]:\f[R]\f[I]classname\f[R]] or \f[V]-da\f[R][\f[V]:\f[R][\f[I]packagename\f[R]]...|\f[V]:\f[R]\f[I]classname\f[R]] -Disables assertions. -By default, assertions are disabled in all packages and classes. -With no arguments, \f[V]-disableassertions\f[R] (\f[V]-da\f[R]) disables -assertions in all packages and classes. -With the \f[I]packagename\f[R] argument ending in \f[V]...\f[R], the -switch disables assertions in the specified package and any subpackages. -If the argument is simply \f[V]...\f[R], then the switch disables -assertions in the unnamed package in the current working directory. -With the \f[I]classname\f[R] argument, the switch disables assertions in -the specified class. -.RS -.PP -The \f[V]-disableassertions\f[R] (\f[V]-da\f[R]) option applies to all -class loaders and to system classes (which don\[aq]t have a class -loader). -There\[aq]s one exception to this rule: If the option is provided with -no arguments, then it doesn\[aq]t apply to system classes. -This makes it easy to disable assertions in all classes except for -system classes. -The \f[V]-disablesystemassertions\f[R] option enables you to disable -assertions in all system classes. -To explicitly enable assertions in specific packages or classes, use the -\f[V]-enableassertions\f[R] (\f[V]-ea\f[R]) option. -Both options can be used at the same time. -For example, to run the \f[V]MyClass\f[R] application with assertions -enabled in the package \f[V]com.wombat.fruitbat\f[R] (and any -subpackages) but disabled in the class -\f[V]com.wombat.fruitbat.Brickbat\f[R], use the following command: -.RS -.PP -\f[V]java -ea:com.wombat.fruitbat... -da:com.wombat.fruitbat.Brickbat MyClass\f[R] -.RE -.RE -.TP -\f[V]-disablesystemassertions\f[R] or \f[V]-dsa\f[R] -Disables assertions in all system classes. -.TP -\f[V]-enableassertions\f[R][\f[V]:\f[R][\f[I]packagename\f[R]]...|\f[V]:\f[R]\f[I]classname\f[R]] or \f[V]-ea\f[R][\f[V]:\f[R][\f[I]packagename\f[R]]...|\f[V]:\f[R]\f[I]classname\f[R]] -Enables assertions. -By default, assertions are disabled in all packages and classes. -With no arguments, \f[V]-enableassertions\f[R] (\f[V]-ea\f[R]) enables -assertions in all packages and classes. -With the \f[I]packagename\f[R] argument ending in \f[V]...\f[R], the -switch enables assertions in the specified package and any subpackages. -If the argument is simply \f[V]...\f[R], then the switch enables -assertions in the unnamed package in the current working directory. -With the \f[I]classname\f[R] argument, the switch enables assertions in -the specified class. -.RS -.PP -The \f[V]-enableassertions\f[R] (\f[V]-ea\f[R]) option applies to all -class loaders and to system classes (which don\[aq]t have a class -loader). -There\[aq]s one exception to this rule: If the option is provided with -no arguments, then it doesn\[aq]t apply to system classes. -This makes it easy to enable assertions in all classes except for system -classes. -The \f[V]-enablesystemassertions\f[R] option provides a separate switch -to enable assertions in all system classes. -To explicitly disable assertions in specific packages or classes, use -the \f[V]-disableassertions\f[R] (\f[V]-da\f[R]) option. -If a single command contains multiple instances of these switches, then -they\[aq]re processed in order, before loading any classes. -For example, to run the \f[V]MyClass\f[R] application with assertions -enabled only in the package \f[V]com.wombat.fruitbat\f[R] (and any -subpackages) but disabled in the class -\f[V]com.wombat.fruitbat.Brickbat\f[R], use the following command: -.RS -.PP -\f[V]java -ea:com.wombat.fruitbat... -da:com.wombat.fruitbat.Brickbat MyClass\f[R] -.RE -.RE -.TP -\f[V]-enablesystemassertions\f[R] or \f[V]-esa\f[R] -Enables assertions in all system classes. -.TP -\f[V]-help\f[R], \f[V]-h\f[R], or \f[V]-?\f[R] -Prints the help message to the error stream. -.TP -\f[V]--help\f[R] -Prints the help message to the output stream. -.TP -\f[V]-javaagent:\f[R]\f[I]jarpath\f[R][\f[V]=\f[R]\f[I]options\f[R]] -Loads the specified Java programming language agent. -See \f[V]java.lang.instrument\f[R]. -.TP -\f[V]--show-version\f[R] -Prints the product version to the output stream and continues. -.TP -\f[V]-showversion\f[R] -Prints the product version to the error stream and continues. -.TP -\f[V]--show-module-resolution\f[R] -Shows module resolution output during startup. -.TP -\f[V]-splash:\f[R]\f[I]imagepath\f[R] -Shows the splash screen with the image specified by \f[I]imagepath\f[R]. -HiDPI scaled images are automatically supported and used if available. -The unscaled image file name, such as \f[V]image.ext\f[R], should always -be passed as the argument to the \f[V]-splash\f[R] option. -The most appropriate scaled image provided is picked up automatically. -.RS -.PP -For example, to show the \f[V]splash.gif\f[R] file from the -\f[V]images\f[R] directory when starting your application, use the -following option: -.RS -.PP -\f[V]-splash:images/splash.gif\f[R] -.RE -.PP -See the SplashScreen API documentation for more information. -.RE -.TP -\f[V]-verbose:class\f[R] -Displays information about each loaded class. -.TP -\f[V]-verbose:gc\f[R] -Displays information about each garbage collection (GC) event. -.TP -\f[V]-verbose:jni\f[R] -Displays information about the use of native methods and other Java -Native Interface (JNI) activity. -.TP -\f[V]-verbose:module\f[R] -Displays information about the modules in use. -.TP -\f[V]--version\f[R] -Prints product version to the output stream and exits. -.TP -\f[V]-version\f[R] -Prints product version to the error stream and exits. -.TP -\f[V]-X\f[R] -Prints the help on extra options to the error stream. -.TP -\f[V]--help-extra\f[R] -Prints the help on extra options to the output stream. -.TP -\f[V]\[at]\f[R]\f[I]argfile\f[R] -Specifies one or more argument files prefixed by \f[V]\[at]\f[R] used by -the \f[V]java\f[R] command. -It isn\[aq]t uncommon for the \f[V]java\f[R] command line to be very -long because of the \f[V].jar\f[R] files needed in the classpath. -The \f[V]\[at]\f[R]\f[I]argfile\f[R] option overcomes command-line -length limitations by enabling the launcher to expand the contents of -argument files after shell expansion, but before argument processing. -Contents in the argument files are expanded because otherwise, they -would be specified on the command line until the -\f[V]--disable-\[at]files\f[R] option was encountered. -.RS -.PP -The argument files can also contain the main class name and all options. -If an argument file contains all of the options required by the -\f[V]java\f[R] command, then the command line could simply be: -.RS -.PP -\f[V]java \[at]\f[R]\f[I]argfile\f[R] -.RE -.PP -See \f[B]java Command-Line Argument Files\f[R] for a description and -examples of using \f[V]\[at]\f[R]-argfiles. -.RE -.SH EXTRA OPTIONS FOR JAVA -.PP -The following \f[V]java\f[R] options are general purpose options that -are specific to the Java HotSpot Virtual Machine. -.TP -\f[V]-Xbatch\f[R] -Disables background compilation. -By default, the JVM compiles the method as a background task, running -the method in interpreter mode until the background compilation is -finished. -The \f[V]-Xbatch\f[R] flag disables background compilation so that -compilation of all methods proceeds as a foreground task until -completed. -This option is equivalent to \f[V]-XX:-BackgroundCompilation\f[R]. -.TP -\f[V]-Xbootclasspath/a:\f[R]\f[I]directories\f[R]|\f[I]zip\f[R]|\f[I]JAR-files\f[R] -Specifies a list of directories, JAR files, and ZIP archives to append -to the end of the default bootstrap class path. -.RS -.PP -On Windows, semicolons (\f[V];\f[R]) separate entities in this list; on -other platforms it is a colon (\f[V]:\f[R]). -.RE -.TP -\f[V]-Xcheck:jni\f[R] -Performs additional checks for Java Native Interface (JNI) functions. -.RS -.PP -The following checks are considered indicative of significant problems -with the native code, and the JVM terminates with an irrecoverable error -in such cases: -.IP \[bu] 2 -The thread doing the call is not attached to the JVM. -.IP \[bu] 2 -The thread doing the call is using the \f[V]JNIEnv\f[R] belonging to -another thread. -.IP \[bu] 2 -A parameter validation check fails: -.RS 2 -.IP \[bu] 2 -A \f[V]jfieldID\f[R], or \f[V]jmethodID\f[R], is detected as being -invalid. -For example: -.RS 2 -.IP \[bu] 2 -Of the wrong type -.IP \[bu] 2 -Associated with the wrong class -.RE -.IP \[bu] 2 -A parameter of the wrong type is detected. -.IP \[bu] 2 -An invalid parameter value is detected. -For example: -.RS 2 -.IP \[bu] 2 -NULL where not permitted -.IP \[bu] 2 -An out-of-bounds array index, or frame capacity -.IP \[bu] 2 -A non-UTF-8 string -.IP \[bu] 2 -An invalid JNI reference -.IP \[bu] 2 -An attempt to use a \f[V]ReleaseXXX\f[R] function on a parameter not -produced by the corresponding \f[V]GetXXX\f[R] function -.RE -.RE -.PP -The following checks only result in warnings being printed: -.IP \[bu] 2 -A JNI call was made without checking for a pending exception from a -previous JNI call, and the current call is not safe when an exception -may be pending. -.IP \[bu] 2 -A class descriptor is in decorated format (\f[V]Lname;\f[R]) when it -should not be. -.IP \[bu] 2 -A \f[V]NULL\f[R] parameter is allowed, but its use is questionable. -.IP \[bu] 2 -Calling other JNI functions in the scope of -\f[V]Get/ReleasePrimitiveArrayCritical\f[R] or -\f[V]Get/ReleaseStringCritical\f[R] -.PP -Expect a performance degradation when this option is used. -.RE -.TP -\f[V]-Xcomp\f[R] -Testing mode to exercise JIT compilers. -This option should not be used in production environments. -.TP -\f[V]-Xdebug\f[R] -Does nothing; deprecated for removal in a future release. -.TP -\f[V]-Xdiag\f[R] -Shows additional diagnostic messages. -.TP -\f[V]-Xint\f[R] -Runs the application in interpreted-only mode. -Compilation to native code is disabled, and all bytecode is executed by -the interpreter. -The performance benefits offered by the just-in-time (JIT) compiler -aren\[aq]t present in this mode. -.TP -\f[V]-Xinternalversion\f[R] -Displays more detailed JVM version information than the -\f[V]-version\f[R] option, and then exits. -.TP -\f[V]-Xlog:\f[R]\f[I]option\f[R] -Configure or enable logging with the Java Virtual Machine (JVM) unified -logging framework. -See \f[B]Enable Logging with the JVM Unified Logging Framework\f[R]. -.TP -\f[V]-Xmixed\f[R] -Executes all bytecode by the interpreter except for hot methods, which -are compiled to native code. -On by default. -Use \f[V]-Xint\f[R] to switch off. -.TP -\f[V]-Xmn\f[R] \f[I]size\f[R] -Sets the initial and maximum size (in bytes) of the heap for the young -generation (nursery) in the generational collectors. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The young generation region of the heap is used for new objects. -GC is performed in this region more often than in other regions. -If the size for the young generation is too small, then a lot of minor -garbage collections are performed. -If the size is too large, then only full garbage collections are -performed, which can take a long time to complete. -It is recommended that you do not set the size for the young generation -for the G1 collector, and keep the size for the young generation greater -than 25% and less than 50% of the overall heap size for other -collectors. -The following examples show how to set the initial and maximum size of -young generation to 256 MB using various units: -.RS -.IP -.nf -\f[CB] --Xmn256m --Xmn262144k --Xmn268435456 -\f[R] -.fi -.PP -Instead of the \f[V]-Xmn\f[R] option to set both the initial and maximum -size of the heap for the young generation, you can use -\f[V]-XX:NewSize\f[R] to set the initial size and -\f[V]-XX:MaxNewSize\f[R] to set the maximum size. -.RE -.TP -\f[V]-Xms\f[R] \f[I]size\f[R] -Sets the minimum and the initial size (in bytes) of the heap. -This value must be a multiple of 1024 and greater than 1 MB. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The following examples show how to set the size of allocated memory to 6 -MB using various units: -.RS -.IP -.nf -\f[CB] --Xms6291456 --Xms6144k --Xms6m -\f[R] -.fi -.PP -If you do not set this option, then the initial size will be set as the -sum of the sizes allocated for the old generation and the young -generation. -The initial size of the heap for the young generation can be set using -the \f[V]-Xmn\f[R] option or the \f[V]-XX:NewSize\f[R] option. -.PP -Note that the \f[V]-XX:InitialHeapSize\f[R] option can also be used to -set the initial heap size. -If it appears after \f[V]-Xms\f[R] on the command line, then the initial -heap size gets set to the value specified with -\f[V]-XX:InitialHeapSize\f[R]. -.RE -.TP -\f[V]-Xmx\f[R] \f[I]size\f[R] -Specifies the maximum size (in bytes) of the heap. -This value must be a multiple of 1024 and greater than 2 MB. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default value is chosen at runtime based on system configuration. -For server deployments, \f[V]-Xms\f[R] and \f[V]-Xmx\f[R] are often set -to the same value. -The following examples show how to set the maximum allowed size of -allocated memory to 80 MB using various units: -.RS -.IP -.nf -\f[CB] --Xmx83886080 --Xmx81920k --Xmx80m -\f[R] -.fi -.PP -The \f[V]-Xmx\f[R] option is equivalent to \f[V]-XX:MaxHeapSize\f[R]. -.RE -.TP -\f[V]-Xnoclassgc\f[R] -Disables garbage collection (GC) of classes. -This can save some GC time, which shortens interruptions during the -application run. -When you specify \f[V]-Xnoclassgc\f[R] at startup, the class objects in -the application are left untouched during GC and are always be -considered live. -This can result in more memory being permanently occupied which, if not -used carefully, throws an out-of-memory exception. -.TP -\f[V]-Xrs\f[R] -Reduces the use of operating system signals by the JVM. -Shutdown hooks enable the orderly shutdown of a Java application by -running user cleanup code (such as closing database connections) at -shutdown, even if the JVM terminates abruptly. -.RS -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] -.RS 2 -.IP \[bu] 2 -The JVM catches signals to implement shutdown hooks for unexpected -termination. -The JVM uses \f[V]SIGHUP\f[R], \f[V]SIGINT\f[R], and \f[V]SIGTERM\f[R] -to initiate the running of shutdown hooks. -.IP \[bu] 2 -Applications embedding the JVM frequently need to trap signals such as -\f[V]SIGINT\f[R] or \f[V]SIGTERM\f[R], which can lead to interference -with the JVM signal handlers. -The \f[V]-Xrs\f[R] option is available to address this issue. -When \f[V]-Xrs\f[R] is used, the signal masks for \f[V]SIGINT\f[R], -\f[V]SIGTERM\f[R], \f[V]SIGHUP\f[R], and \f[V]SIGQUIT\f[R] aren\[aq]t -changed by the JVM, and signal handlers for these signals aren\[aq]t -installed. -.RE -.IP \[bu] 2 -\f[B]Windows:\f[R] -.RS 2 -.IP \[bu] 2 -The JVM watches for console control events to implement shutdown hooks -for unexpected termination. -Specifically, the JVM registers a console control handler that begins -shutdown-hook processing and returns \f[V]TRUE\f[R] for -\f[V]CTRL_C_EVENT\f[R], \f[V]CTRL_CLOSE_EVENT\f[R], -\f[V]CTRL_LOGOFF_EVENT\f[R], and \f[V]CTRL_SHUTDOWN_EVENT\f[R]. -.IP \[bu] 2 -The JVM uses a similar mechanism to implement the feature of dumping -thread stacks for debugging purposes. -The JVM uses \f[V]CTRL_BREAK_EVENT\f[R] to perform thread dumps. -.IP \[bu] 2 -If the JVM is run as a service (for example, as a servlet engine for a -web server), then it can receive \f[V]CTRL_LOGOFF_EVENT\f[R] but -shouldn\[aq]t initiate shutdown because the operating system doesn\[aq]t -actually terminate the process. -To avoid possible interference such as this, the \f[V]-Xrs\f[R] option -can be used. -When the \f[V]-Xrs\f[R] option is used, the JVM doesn\[aq]t install a -console control handler, implying that it doesn\[aq]t watch for or -process \f[V]CTRL_C_EVENT\f[R], \f[V]CTRL_CLOSE_EVENT\f[R], -\f[V]CTRL_LOGOFF_EVENT\f[R], or \f[V]CTRL_SHUTDOWN_EVENT\f[R]. -.RE -.PP -There are two consequences of specifying \f[V]-Xrs\f[R]: -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] \f[V]SIGQUIT\f[R] thread dumps aren\[aq]t -available. -.IP \[bu] 2 -\f[B]Windows:\f[R] Ctrl + Break thread dumps aren\[aq]t available. -.PP -User code is responsible for causing shutdown hooks to run, for example, -by calling \f[V]System.exit()\f[R] when the JVM is to be terminated. -.RE -.TP -\f[V]-Xshare:\f[R]\f[I]mode\f[R] -Sets the class data sharing (CDS) mode. -.RS -.PP -Possible \f[I]mode\f[R] arguments for this option include the following: -.TP -\f[V]auto\f[R] -Use shared class data if possible (default). -.TP -\f[V]on\f[R] -Require using shared class data, otherwise fail. -.RS -.PP -\f[B]Note:\f[R] The \f[V]-Xshare:on\f[R] option is used for testing -purposes only. -It may cause the VM to unexpectedly exit during start-up when the CDS -archive cannot be used (for example, when certain VM parameters are -changed, or when a different JDK is used). -This option should not be used in production environments. -.RE -.TP -\f[V]off\f[R] -Do not attempt to use shared class data. -.RE -.TP -\f[V]-XshowSettings\f[R] -Shows all settings and then continues. -.TP -\f[V]-XshowSettings:\f[R]\f[I]category\f[R] -Shows settings and continues. -Possible \f[I]category\f[R] arguments for this option include the -following: -.RS -.TP -\f[V]all\f[R] -Shows all categories of settings in \f[B]verbose\f[R] detail. -.TP -\f[V]locale\f[R] -Shows settings related to locale. -.TP -\f[V]properties\f[R] -Shows settings related to system properties. -.TP -\f[V]security\f[R] -Shows all settings related to security. -.RS -.PP -sub-category arguments for \f[V]security\f[R] include the following: -.IP \[bu] 2 -\f[V]security:all\f[R] : shows all security settings -.IP \[bu] 2 -\f[V]security:properties\f[R] : shows security properties -.IP \[bu] 2 -\f[V]security:providers\f[R] : shows static security provider settings -.IP \[bu] 2 -\f[V]security:tls\f[R] : shows TLS related security settings -.RE -.TP -\f[V]vm\f[R] -Shows the settings of the JVM. -.TP -\f[V]system\f[R] -\f[B]Linux only:\f[R] Shows host system or container configuration and -continues. -.RE -.TP -\f[V]-Xss\f[R] \f[I]size\f[R] -Sets the thread stack size (in bytes). -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate KB, \f[V]m\f[R] -or \f[V]M\f[R] to indicate MB, or \f[V]g\f[R] or \f[V]G\f[R] to indicate -GB. -The actual size may be rounded up to a multiple of the system page size -as required by the operating system. -The default value depends on the platform. -For example: -.RS -.IP \[bu] 2 -Linux/x64: 1024 KB -.IP \[bu] 2 -Linux/Aarch64: 2048 KB -.IP \[bu] 2 -macOS/x64: 1024 KB -.IP \[bu] 2 -macOS/Aarch64: 2048 KB -.IP \[bu] 2 -Windows: The default value depends on virtual memory -.PP -The following examples set the thread stack size to 1024 KB in different -units: -.IP -.nf -\f[CB] --Xss1m --Xss1024k --Xss1048576 -\f[R] -.fi -.PP -This option is similar to \f[V]-XX:ThreadStackSize\f[R]. -.RE -.TP -\f[V]--add-reads\f[R] \f[I]module\f[R]\f[V]=\f[R]\f[I]target-module\f[R](\f[V],\f[R]\f[I]target-module\f[R])* -Updates \f[I]module\f[R] to read the \f[I]target-module\f[R], regardless -of the module declaration. -\f[I]target-module\f[R] can be \f[V]ALL-UNNAMED\f[R] to read all unnamed -modules. -.TP -\f[V]--add-exports\f[R] \f[I]module\f[R]\f[V]/\f[R]\f[I]package\f[R]\f[V]=\f[R]\f[I]target-module\f[R](\f[V],\f[R]\f[I]target-module\f[R])* -Updates \f[I]module\f[R] to export \f[I]package\f[R] to -\f[I]target-module\f[R], regardless of module declaration. -\f[I]target-module\f[R] can be \f[V]ALL-UNNAMED\f[R] to export to all -unnamed modules. -.TP -\f[V]--add-opens\f[R] \f[I]module\f[R]\f[V]/\f[R]\f[I]package\f[R]\f[V]=\f[R]\f[I]target-module\f[R](\f[V],\f[R]\f[I]target-module\f[R])* -Updates \f[I]module\f[R] to open \f[I]package\f[R] to -\f[I]target-module\f[R], regardless of module declaration. -.TP -\f[V]--limit-modules\f[R] \f[I]module\f[R][\f[V],\f[R]\f[I]module\f[R]...] -Specifies the limit of the universe of observable modules. -.TP -\f[V]--patch-module\f[R] \f[I]module\f[R]\f[V]=\f[R]\f[I]file\f[R](\f[V];\f[R]\f[I]file\f[R])* -Overrides or augments a module with classes and resources in JAR files -or directories. -.TP -\f[V]--source\f[R] \f[I]version\f[R] -Sets the version of the source in source-file mode. -.TP -\f[V]--sun-misc-unsafe-memory-access=\f[R] \f[I]value\f[R] -Allow or deny usage of unsupported API \f[V]sun.misc.Unsafe\f[R]. -\f[I]value\f[R] is one of: -.RS -.TP -\f[V]allow\f[R] -Allow use of the memory-access methods with no warnings at run time. -.TP -\f[V]warn\f[R] -Allow use of the memory-access methods, but issues a warning on the -first occasion that any memory-access method is used. -At most one warning is issued. -.TP -\f[V]debug\f[R] -Allow use of the memory-access methods, but issue a one-line warning and -a stack trace when any memory-access method is used. -.TP -\f[V]deny\f[R] -Disallow use of the memory-access methods by throwing an -\f[V]UnsupportedOperationException\f[R] on every usage. -.PP -The default value when the option is not specified is \f[V]allow\f[R]. -.RE -.SH EXTRA OPTIONS FOR MACOS -.PP -The following extra options are macOS specific. -.TP -\f[V]-XstartOnFirstThread\f[R] -Runs the \f[V]main()\f[R] method on the first (AppKit) thread. -.TP -\f[V]-Xdock:name=\f[R]\f[I]application_name\f[R] -Overrides the default application name displayed in dock. -.TP -\f[V]-Xdock:icon=\f[R]\f[I]path_to_icon_file\f[R] -Overrides the default icon displayed in dock. -.SH ADVANCED OPTIONS FOR JAVA -.PP -These \f[V]java\f[R] options can be used to enable other advanced -options. -.TP -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R] -Unlocks the options intended for diagnosing the JVM. -By default, this option is disabled and diagnostic options aren\[aq]t -available. -.RS -.PP -Command line options that are enabled with the use of this option are -not supported. -If you encounter issues while using any of these options, it is very -likely that you will be required to reproduce the problem without using -any of these unsupported options before Oracle Support can assist with -an investigation. -It is also possible that any of these options may be removed or their -behavior changed without any warning. -.RE -.TP -\f[V]-XX:+UnlockExperimentalVMOptions\f[R] -Unlocks the options that provide experimental features in the JVM. -By default, this option is disabled and experimental features aren\[aq]t -available. -.SH ADVANCED RUNTIME OPTIONS FOR JAVA -.PP -These \f[V]java\f[R] options control the runtime behavior of the Java -HotSpot VM. -.TP -\f[V]-XX:ActiveProcessorCount=\f[R]\f[I]x\f[R] -Overrides the number of CPUs that the VM will use to calculate the size -of thread pools it will use for various operations such as Garbage -Collection and ForkJoinPool. -.RS -.PP -The VM normally determines the number of available processors from the -operating system. -This flag can be useful for partitioning CPU resources when running -multiple Java processes in docker containers. -This flag is honored even if \f[V]UseContainerSupport\f[R] is not -enabled. -See \f[V]-XX:-UseContainerSupport\f[R] for a description of enabling and -disabling container support. -.RE -.TP -\f[V]-XX:AllocateHeapAt=\f[R]\f[I]path\f[R] -Takes a path to the file system and uses memory mapping to allocate the -object heap on the memory device. -Using this option enables the HotSpot VM to allocate the Java object -heap on an alternative memory device, such as an NV-DIMM, specified by -the user. -.RS -.PP -Alternative memory devices that have the same semantics as DRAM, -including the semantics of atomic operations, can be used instead of -DRAM for the object heap without changing the existing application code. -All other memory structures (such as the code heap, metaspace, and -thread stacks) continue to reside in DRAM. -.PP -Some operating systems expose non-DRAM memory through the file system. -Memory-mapped files in these file systems bypass the page cache and -provide a direct mapping of virtual memory to the physical memory on the -device. -The existing heap related flags (such as \f[V]-Xmx\f[R] and -\f[V]-Xms\f[R]) and garbage-collection related flags continue to work as -before. -.RE -.TP -\f[V]-XX:-CompactStrings\f[R] -Disables the Compact Strings feature. -By default, this option is enabled. -When this option is enabled, Java Strings containing only single-byte -characters are internally represented and stored as -single-byte-per-character Strings using ISO-8859-1 / Latin-1 encoding. -This reduces, by 50%, the amount of space required for Strings -containing only single-byte characters. -For Java Strings containing at least one multibyte character: these are -represented and stored as 2 bytes per character using UTF-16 encoding. -Disabling the Compact Strings feature forces the use of UTF-16 encoding -as the internal representation for all Java Strings. -.RS -.PP -Cases where it may be beneficial to disable Compact Strings include the -following: -.IP \[bu] 2 -When it\[aq]s known that an application overwhelmingly will be -allocating multibyte character Strings -.IP \[bu] 2 -In the unexpected event where a performance regression is observed in -migrating from Java SE 8 to Java SE 9 and an analysis shows that Compact -Strings introduces the regression -.PP -In both of these scenarios, disabling Compact Strings makes sense. -.RE -.TP -\f[V]-XX:ErrorFile=\f[R]\f[I]filename\f[R] -Specifies the path and file name to which error data is written when an -irrecoverable error occurs. -By default, this file is created in the current working directory and -named \f[V]hs_err_pid\f[R]\f[I]pid\f[R]\f[V].log\f[R] where -\f[I]pid\f[R] is the identifier of the process that encountered the -error. -.RS -.PP -The following example shows how to set the default log file (note that -the identifier of the process is specified as \f[V]%p\f[R]): -.RS -.PP -\f[V]-XX:ErrorFile=./hs_err_pid%p.log\f[R] -.RE -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] The following example shows how to set the error -log to \f[V]/var/log/java/java_error.log\f[R]: -.RS 2 -.RS -.PP -\f[V]-XX:ErrorFile=/var/log/java/java_error.log\f[R] -.RE -.RE -.IP \[bu] 2 -\f[B]Windows:\f[R] The following example shows how to set the error log -file to \f[V]C:/log/java/java_error.log\f[R]: -.RS 2 -.RS -.PP -\f[V]-XX:ErrorFile=C:/log/java/java_error.log\f[R] -.RE -.RE -.PP -If the file exists, and is writeable, then it will be overwritten. -Otherwise, if the file can\[aq]t be created in the specified directory -(due to insufficient space, permission problem, or another issue), then -the file is created in the temporary directory for the operating system: -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] The temporary directory is \f[V]/tmp\f[R]. -.IP \[bu] 2 -\f[B]Windows:\f[R] The temporary directory is specified by the value of -the \f[V]TMP\f[R] environment variable; if that environment variable -isn\[aq]t defined, then the value of the \f[V]TEMP\f[R] environment -variable is used. -.RE -.TP -\f[V]-XX:+ExtensiveErrorReports\f[R] -Enables the reporting of more extensive error information in the -\f[V]ErrorFile\f[R]. -This option can be turned on in environments where maximal information -is desired - even if the resulting logs may be quite large and/or -contain information that might be considered sensitive. -The information can vary from release to release, and across different -platforms. -By default this option is disabled. -.TP -\f[V]-XX:FlightRecorderOptions=\f[R]\f[I]parameter\f[R]\f[V]=\f[R]\f[I]value\f[R] (or) \f[V]-XX:FlightRecorderOptions:\f[R]\f[I]parameter\f[R]\f[V]=\f[R]\f[I]value\f[R] -Sets the parameters that control the behavior of JFR. -Multiple parameters can be specified by separating them with a comma. -.RS -.PP -The following list contains the available JFR -\f[I]parameter\f[R]\f[V]=\f[R]\f[I]value\f[R] entries: -.TP -\f[V]globalbuffersize=\f[R]\f[I]size\f[R] -Specifies the total amount of primary memory used for data retention. -The default value is based on the value specified for -\f[V]memorysize\f[R]. -Change the \f[V]memorysize\f[R] parameter to alter the size of global -buffers. -.TP -\f[V]maxchunksize=\f[R]\f[I]size\f[R] -Specifies the maximum size (in bytes) of the data chunks in a recording. -Append \f[V]m\f[R] or \f[V]M\f[R] to specify the size in megabytes (MB), -or \f[V]g\f[R] or \f[V]G\f[R] to specify the size in gigabytes (GB). -By default, the maximum size of data chunks is set to 12 MB. -The minimum allowed is 1 MB. -.TP -\f[V]memorysize=\f[R]\f[I]size\f[R] -Determines how much buffer memory should be used, and sets the -\f[V]globalbuffersize\f[R] and \f[V]numglobalbuffers\f[R] parameters -based on the size specified. -Append \f[V]m\f[R] or \f[V]M\f[R] to specify the size in megabytes (MB), -or \f[V]g\f[R] or \f[V]G\f[R] to specify the size in gigabytes (GB). -By default, the memory size is set to 10 MB. -.TP -\f[V]numglobalbuffers\f[R] -Specifies the number of global buffers used. -The default value is based on the memory size specified. -Change the \f[V]memorysize\f[R] parameter to alter the number of global -buffers. -.TP -\f[V]old-object-queue-size=number-of-objects\f[R] -Maximum number of old objects to track. -By default, the number of objects is set to 256. -.TP -\f[V]preserve-repository=\f[R]{\f[V]true\f[R]|\f[V]false\f[R]} -Specifies whether files stored in the disk repository should be kept -after the JVM has exited. -If false, files are deleted. -By default, this parameter is disabled. -.TP -\f[V]repository=\f[R]\f[I]path\f[R] -Specifies the repository (a directory) for temporary disk storage. -By default, the system\[aq]s temporary directory is used. -.TP -\f[V]retransform=\f[R]{\f[V]true\f[R]|\f[V]false\f[R]} -Specifies whether event classes should be retransformed using JVMTI. -If false, instrumentation is added when event classes are loaded. -By default, this parameter is enabled. -.TP -\f[V]stackdepth=\f[R]\f[I]depth\f[R] -Stack depth for stack traces. -By default, the depth is set to 64 method calls. -The maximum is 2048. -Values greater than 64 could create significant overhead and reduce -performance. -.TP -\f[V]threadbuffersize=\f[R]\f[I]size\f[R] -Specifies the per-thread local buffer size (in bytes). -By default, the local buffer size is set to 8 kilobytes, with a minimum -value of 4 kilobytes. -Overriding this parameter could reduce performance and is not -recommended. -.RE -.TP -\f[V]-XX:LargePageSizeInBytes=\f[R]\f[I]size\f[R] -Sets the maximum large page size (in bytes) used by the JVM. -The \f[I]size\f[R] argument must be a valid page size supported by the -environment to have any effect. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -By default, the size is set to 0, meaning that the JVM will use the -default large page size for the environment as the maximum size for -large pages. -See \f[B]Large Pages\f[R]. -.RS -.PP -The following example describes how to set the large page size to 1 -gigabyte (GB): -.RS -.PP -\f[V]-XX:LargePageSizeInBytes=1g\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxDirectMemorySize=\f[R]\f[I]size\f[R] -Sets the maximum total size (in bytes) of the \f[V]java.nio\f[R] -package, direct-buffer allocations. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -If not set, the flag is ignored and the JVM chooses the size for NIO -direct-buffer allocations automatically. -.RS -.PP -The following examples illustrate how to set the NIO size to 1024 KB in -different units: -.IP -.nf -\f[CB] --XX:MaxDirectMemorySize=1m --XX:MaxDirectMemorySize=1024k --XX:MaxDirectMemorySize=1048576 -\f[R] -.fi -.RE -.TP -\f[V]-XX:-MaxFDLimit\f[R] -Disables the attempt to set the soft limit for the number of open file -descriptors to the hard limit. -By default, this option is enabled on all platforms, but is ignored on -Windows. -The only time that you may need to disable this is on macOS, where its -use imposes a maximum of 10240, which is lower than the actual system -maximum. -.TP -\f[V]-XX:NativeMemoryTracking=\f[R]\f[I]mode\f[R] -Specifies the mode for tracking JVM native memory usage. -Possible \f[I]mode\f[R] arguments for this option include the following: -.RS -.TP -\f[V]off\f[R] -Instructs not to track JVM native memory usage. -This is the default behavior if you don\[aq]t specify the -\f[V]-XX:NativeMemoryTracking\f[R] option. -.TP -\f[V]summary\f[R] -Tracks memory usage only by JVM subsystems, such as Java heap, class, -code, and thread. -.TP -\f[V]detail\f[R] -In addition to tracking memory usage by JVM subsystems, track memory -usage by individual \f[V]CallSite\f[R], individual virtual memory region -and its committed regions. -.RE -.TP -\f[V]-XX:TrimNativeHeapInterval=\f[R]\f[I]millis\f[R] -Interval, in ms, at which the JVM will trim the native heap. -Lower values will reclaim memory more eagerly at the cost of higher -overhead. -A value of 0 (default) disables native heap trimming. -Native heap trimming is performed in a dedicated thread. -.RS -.PP -This option is only supported on Linux with GNU C Library (glibc). -.RE -.TP -\f[V]-XX:+NeverActAsServerClassMachine\f[R] -Enable the \[dq]Client VM emulation\[dq] mode which only uses the C1 JIT -compiler, a 32Mb CodeCache and the Serial GC. -The maximum amount of memory that the JVM may use (controlled by the -\f[V]-XX:MaxRAM=n\f[R] flag) is set to 1GB by default. -The string \[dq]emulated-client\[dq] is added to the JVM version string. -.RS -.PP -By default the flag is set to \f[V]true\f[R] only on Windows in 32-bit -mode and \f[V]false\f[R] in all other cases. -.PP -The \[dq]Client VM emulation\[dq] mode will not be enabled if any of the -following flags are used on the command line: -.IP -.nf -\f[CB] --XX:{+|-}TieredCompilation --XX:CompilationMode=mode --XX:TieredStopAtLevel=n --XX:{+|-}EnableJVMCI --XX:{+|-}UseJVMCICompiler -\f[R] -.fi -.RE -.TP -\f[V]-XX:ObjectAlignmentInBytes=\f[R]\f[I]alignment\f[R] -Sets the memory alignment of Java objects (in bytes). -By default, the value is set to 8 bytes. -The specified value should be a power of 2, and must be within the range -of 8 and 256 (inclusive). -This option makes it possible to use compressed pointers with large Java -heap sizes. -.RS -.PP -The heap size limit in bytes is calculated as: -.RS -.PP -\f[V]4GB * ObjectAlignmentInBytes\f[R] -.RE -.RS -.PP -\f[B]Note:\f[R] As the alignment value increases, the unused space -between objects also increases. -As a result, you may not realize any benefits from using compressed -pointers with large Java heap sizes. -.RE -.RE -.TP -\f[V]-XX:OnError=\f[R]\f[I]string\f[R] -Sets a custom command or a series of semicolon-separated commands to run -when an irrecoverable error occurs. -If the string contains spaces, then it must be enclosed in quotation -marks. -.RS -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] The following example shows how the -\f[V]-XX:OnError\f[R] option can be used to run the \f[V]gcore\f[R] -command to create a core image, and start the \f[V]gdb\f[R] debugger to -attach to the process in case of an irrecoverable error (the -\f[V]%p\f[R] designates the current process identifier): -.RS 2 -.RS -.PP -\f[V]-XX:OnError=\[dq]gcore %p;gdb -p %p\[dq]\f[R] -.RE -.RE -.IP \[bu] 2 -\f[B]Windows:\f[R] The following example shows how the -\f[V]-XX:OnError\f[R] option can be used to run the -\f[V]userdump.exe\f[R] utility to obtain a crash dump in case of an -irrecoverable error (the \f[V]%p\f[R] designates the current process -identifier). -This example assumes that the path to the \f[V]userdump.exe\f[R] utility -is specified in the \f[V]PATH\f[R] environment variable: -.RS 2 -.RS -.PP -\f[V]-XX:OnError=\[dq]userdump.exe %p\[dq]\f[R] -.RE -.RE -.RE -.TP -\f[V]-XX:OnOutOfMemoryError=\f[R]\f[I]string\f[R] -Sets a custom command or a series of semicolon-separated commands to run -when an \f[V]OutOfMemoryError\f[R] exception is first thrown. -If the string contains spaces, then it must be enclosed in quotation -marks. -For an example of a command string, see the description of the -\f[V]-XX:OnError\f[R] option. -.TP -\f[V]-XX:+PrintCommandLineFlags\f[R] -Enables printing of ergonomically selected JVM flags that appeared on -the command line. -It can be useful to know the ergonomic values set by the JVM, such as -the heap space size and the selected garbage collector. -By default, this option is disabled and flags aren\[aq]t printed. -.TP -\f[V]-XX:+PreserveFramePointer\f[R] -Selects between using the RBP register as a general purpose register -(\f[V]-XX:-PreserveFramePointer\f[R]) and using the RBP register to hold -the frame pointer of the currently executing method -(\f[V]-XX:+PreserveFramePointer\f[R] . -If the frame pointer is available, then external profiling tools (for -example, Linux perf) can construct more accurate stack traces. -.TP -\f[V]-XX:+PrintNMTStatistics\f[R] -Enables printing of collected native memory tracking data at JVM exit -when native memory tracking is enabled (see -\f[V]-XX:NativeMemoryTracking\f[R]). -By default, this option is disabled and native memory tracking data -isn\[aq]t printed. -.TP -\f[V]-XX:SharedArchiveFile=\f[R]\f[I]path\f[R] -Specifies the path and name of the class data sharing (CDS) archive file -.RS -.PP -See \f[B]Application Class Data Sharing\f[R]. -.RE -.TP -\f[V]-XX:+VerifySharedSpaces\f[R] -If this option is specified, the JVM will load a CDS archive file only -if it passes an integrity check based on CRC32 checksums. -The purpose of this flag is to check for unintentional damage to CDS -archive files in transmission or storage. -To guarantee the security and proper operation of CDS, the user must -ensure that the CDS archive files used by Java applications cannot be -modified without proper authorization. -.TP -\f[V]-XX:SharedArchiveConfigFile=\f[R]\f[I]shared_config_file\f[R] -Specifies additional shared data added to the archive file. -.TP -\f[V]-XX:SharedClassListFile=\f[R]\f[I]file_name\f[R] -Specifies the text file that contains the names of the classes to store -in the class data sharing (CDS) archive. -This file contains the full name of one class per line, except slashes -(\f[V]/\f[R]) replace dots (\f[V].\f[R]). -For example, to specify the classes \f[V]java.lang.Object\f[R] and -\f[V]hello.Main\f[R], create a text file that contains the following two -lines: -.RS -.IP -.nf -\f[CB] -java/lang/Object -hello/Main -\f[R] -.fi -.PP -The classes that you specify in this text file should include the -classes that are commonly used by the application. -They may include any classes from the application, extension, or -bootstrap class paths. -.PP -See \f[B]Application Class Data Sharing\f[R]. -.RE -.TP -\f[V]-XX:+ShowCodeDetailsInExceptionMessages\f[R] -Enables printing of improved \f[V]NullPointerException\f[R] messages. -When an application throws a \f[V]NullPointerException\f[R], the option -enables the JVM to analyze the program\[aq]s bytecode instructions to -determine precisely which reference is \f[V]null\f[R], and describes the -source with a null-detail message. -The null-detail message is calculated and returned by -\f[V]NullPointerException.getMessage()\f[R], and will be printed as the -exception message along with the method, filename, and line number. -By default, this option is enabled. -.TP -\f[V]-XX:+ShowMessageBoxOnError\f[R] -Enables the display of a dialog box when the JVM experiences an -irrecoverable error. -This prevents the JVM from exiting and keeps the process active so that -you can attach a debugger to it to investigate the cause of the error. -By default, this option is disabled. -.TP -\f[V]-XX:StartFlightRecording:\f[R]\f[I]parameter\f[R]\f[V]=\f[R]\f[I]value\f[R] -Starts a JFR recording for the Java application. -This option is equivalent to the \f[V]JFR.start\f[R] diagnostic command -that starts a recording during runtime. -\f[V]-XX:StartFlightRecording:help\f[R] prints available options and -example command lines. -You can set the following \f[I]parameter\f[R]\f[V]=\f[R]\f[I]value\f[R] -entries when starting a JFR recording: -.RS -.TP -\f[V]delay=\f[R]\f[I]time\f[R] -Specifies the delay between the Java application launch time and the -start of the recording. -Append \f[V]s\f[R] to specify the time in seconds, \f[V]m\f[R] for -minutes, \f[V]h\f[R] for hours, or \f[V]d\f[R] for days (for example, -specifying \f[V]10m\f[R] means 10 minutes). -By default, there\[aq]s no delay, and this parameter is set to 0. -.TP -\f[V]disk=\f[R]{\f[V]true\f[R]|\f[V]false\f[R]} -Specifies whether to write data to disk while recording. -By default, this parameter is enabled. -.TP -\f[V]dumponexit=\f[R]{\f[V]true\f[R]|\f[V]false\f[R]} -Specifies if the running recording is dumped when the JVM shuts down. -If enabled and a \f[V]filename\f[R] is not entered, the recording is -written to a file in the directory where the process was started. -The file name is a system-generated name that contains the process ID, -recording ID, and current timestamp, similar to -\f[V]hotspot-pid-47496-id-1-2018_01_25_19_10_41.jfr\f[R]. -By default, this parameter is disabled. -.TP -\f[V]duration=\f[R]\f[I]time\f[R] -Specifies the duration of the recording. -Append \f[V]s\f[R] to specify the time in seconds, \f[V]m\f[R] for -minutes, \f[V]h\f[R] for hours, or \f[V]d\f[R] for days (for example, -specifying \f[V]5h\f[R] means 5 hours). -By default, the duration isn\[aq]t limited, and this parameter is set to -0. -.TP -\f[V]filename=\f[R]\f[I]path\f[R] -Specifies the path and name of the file to which the recording is -written when the recording is stopped, for example: -.RS -.IP \[bu] 2 -\f[V]recording.jfr\f[R] -.IP \[bu] 2 -\f[V]/home/user/recordings/recording.jfr\f[R] -.IP \[bu] 2 -\f[V]c:\[rs]recordings\[rs]recording.jfr\f[R] -.PP -If %p and/or %t is specified in the filename, it expands to the -JVM\[aq]s PID and the current timestamp, respectively. -The filename may also be a directory in which case, the filename is -generated from the PID and the current date in the specified directory. -.RE -.TP -\f[V]name=\f[R]\f[I]identifier\f[R] -Takes both the name and the identifier of a recording. -.TP -\f[V]maxage=\f[R]\f[I]time\f[R] -Specifies the maximum age of disk data to keep for the recording. -This parameter is valid only when the \f[V]disk\f[R] parameter is set to -\f[V]true\f[R]. -Append \f[V]s\f[R] to specify the time in seconds, \f[V]m\f[R] for -minutes, \f[V]h\f[R] for hours, or \f[V]d\f[R] for days (for example, -specifying \f[V]30s\f[R] means 30 seconds). -By default, the maximum age isn\[aq]t limited, and this parameter is set -to \f[V]0s\f[R]. -.TP -\f[V]maxsize=\f[R]\f[I]size\f[R] -Specifies the maximum size (in bytes) of disk data to keep for the -recording. -This parameter is valid only when the \f[V]disk\f[R] parameter is set to -\f[V]true\f[R]. -The value must not be less than the value for the \f[V]maxchunksize\f[R] -parameter set with \f[V]-XX:FlightRecorderOptions\f[R]. -Append \f[V]m\f[R] or \f[V]M\f[R] to specify the size in megabytes, or -\f[V]g\f[R] or \f[V]G\f[R] to specify the size in gigabytes. -By default, the maximum size of disk data isn\[aq]t limited, and this -parameter is set to \f[V]0\f[R]. -.TP -\f[V]path-to-gc-roots=\f[R]{\f[V]true\f[R]|\f[V]false\f[R]} -Specifies whether to collect the path to garbage collection (GC) roots -at the end of a recording. -By default, this parameter is disabled. -.RS -.PP -The path to GC roots is useful for finding memory leaks, but collecting -it is time-consuming. -Enable this option only when you start a recording for an application -that you suspect has a memory leak. -If the \f[V]settings\f[R] parameter is set to \f[V]profile\f[R], the -stack trace from where the potential leaking object was allocated is -included in the information collected. -.RE -.TP -\f[V]settings=\f[R]\f[I]path\f[R] -Specifies the path and name of the event settings file (of type JFC). -By default, the \f[V]default.jfc\f[R] file is used, which is located in -\f[V]JAVA_HOME/lib/jfr\f[R]. -This default settings file collects a predefined set of information with -low overhead, so it has minimal impact on performance and can be used -with recordings that run continuously. -.RS -.PP -A second settings file is also provided, profile.jfc, which provides -more data than the default configuration, but can have more overhead and -impact performance. -Use this configuration for short periods of time when more information -is needed. -.RE -.PP -You can specify values for multiple parameters by separating them with a -comma. -Event settings and .jfc options can be specified using the following -syntax: -.TP -\f[V]option=\f[R]\f[I]value\f[R] -Specifies the option value to modify. -To list available options, use the \f[V]JAVA_HOME\f[R]/bin/jfr tool. -.TP -\f[V]event-setting=\f[R]\f[I]value\f[R] -Specifies the event setting value to modify. -Use the form: \f[V]#=\f[R]. -To add a new event setting, prefix the event name with \[aq]+\[aq]. -.PP -You can specify values for multiple event settings and .jfc options by -separating them with a comma. -In case of a conflict between a parameter and a .jfc option, the -parameter will take precedence. -The whitespace delimiter can be omitted for timespan values, i.e. -20ms. -For more information about the settings syntax, see Javadoc of the -jdk.jfr package. -.PP -To only see warnings and errors from JFR during startup set --Xlog:jfr+startup=warning. -.RE -.TP -\f[V]-XX:ThreadStackSize=\f[R]\f[I]size\f[R] -Sets the Java thread stack size (in kilobytes). -Use of a scaling suffix, such as \f[V]k\f[R], results in the scaling of -the kilobytes value so that \f[V]-XX:ThreadStackSize=1k\f[R] sets the -Java thread stack size to 1024*1024 bytes or 1 megabyte. -The default value depends on the platform. -For example: -.RS -.IP \[bu] 2 -Linux/x64: 1024 KB -.IP \[bu] 2 -Linux/Aarch64: 2048 KB -.IP \[bu] 2 -macOS/x64: 1024 KB -.IP \[bu] 2 -macOS/Aarch64: 2048 KB -.IP \[bu] 2 -Windows: The default value depends on virtual memory -.PP -The following examples show how to set the thread stack size to 1 -megabyte in different units: -.IP -.nf -\f[CB] --XX:ThreadStackSize=1k --XX:ThreadStackSize=1024 -\f[R] -.fi -.PP -This option is similar to \f[V]-Xss\f[R]. -.RE -.TP -\f[V]-XX:-UseCompressedOops\f[R] -Disables the use of compressed pointers. -By default, this option is enabled, and compressed pointers are used. -This will automatically limit the maximum ergonomically determined Java -heap size to the maximum amount of memory that can be covered by -compressed pointers. -By default this range is 32 GB. -.RS -.PP -With compressed oops enabled, object references are represented as -32-bit offsets instead of 64-bit pointers, which typically increases -performance when running the application with Java heap sizes smaller -than the compressed oops pointer range. -This option works only for 64-bit JVMs. -.PP -It\[aq]s possible to use compressed pointers with Java heap sizes -greater than 32 GB. -See the \f[V]-XX:ObjectAlignmentInBytes\f[R] option. -.RE -.TP -\f[V]-XX:-UseContainerSupport\f[R] -\f[B]Linux only:\f[R] The VM now provides automatic container detection -support, which allows the VM to determine the amount of memory and -number of processors that are available to a Java process running in -docker containers. -It uses this information to allocate system resources. -The default for this flag is \f[V]true\f[R], and container support is -enabled by default. -It can be disabled with \f[V]-XX:-UseContainerSupport\f[R]. -.RS -.PP -Unified Logging is available to help to diagnose issues related to this -support. -.PP -Use \f[V]-Xlog:os+container=trace\f[R] for maximum logging of container -information. -See \f[B]Enable Logging with the JVM Unified Logging Framework\f[R] for -a description of using Unified Logging. -.RE -.TP -\f[V]-XX:+UseLargePages\f[R] -Enables the use of large page memory. -By default, this option is disabled and large page memory isn\[aq]t -used. -.RS -.PP -See \f[B]Large Pages\f[R]. -.RE -.TP -\f[V]-XX:+UseTransparentHugePages\f[R] -\f[B]Linux only:\f[R] Enables the use of large pages that can -dynamically grow or shrink. -This option is disabled by default. -You may encounter performance problems with transparent huge pages as -the OS moves other pages around to create huge pages; this option is -made available for experimentation. -.TP -\f[V]-XX:+AllowUserSignalHandlers\f[R] -\f[B]Non-Windows:\f[R] Enables installation of signal handlers by the -application. -By default, this option is disabled and the application isn\[aq]t -allowed to install signal handlers. -.TP -\f[V]-XX:VMOptionsFile=\f[R]\f[I]filename\f[R] -Allows user to specify VM options in a file, for example, -\f[V]java -XX:VMOptionsFile=/var/my_vm_options HelloWorld\f[R]. -.TP -\f[V]-XX:UseBranchProtection=\f[R]\f[I]mode\f[R] -\f[B]Linux AArch64 only:\f[R] Specifies the branch protection mode. -All options other than \f[V]none\f[R] require the VM to have been built -with branch protection enabled. -In addition, for full protection, any native libraries provided by -applications should be compiled with the same level of protection. -.RS -.PP -Possible \f[I]mode\f[R] arguments for this option include the following: -.TP -\f[V]none\f[R] -Do not use branch protection. -This is the default value. -.TP -\f[V]standard\f[R] -Enables all branch protection modes available on the current platform. -.TP -\f[V]pac-ret\f[R] -Enables protection against ROP based attacks. -(AArch64 8.3+ only) -.RE -.SH ADVANCED JIT COMPILER OPTIONS FOR JAVA -.PP -These \f[V]java\f[R] options control the dynamic just-in-time (JIT) -compilation performed by the Java HotSpot VM. -.TP -\f[V]-XX:AllocateInstancePrefetchLines=\f[R]\f[I]lines\f[R] -Sets the number of lines to prefetch ahead of the instance allocation -pointer. -By default, the number of lines to prefetch is set to 1: -.RS -.RS -.PP -\f[V]-XX:AllocateInstancePrefetchLines=1\f[R] -.RE -.RE -.TP -\f[V]-XX:AllocatePrefetchDistance=\f[R]\f[I]size\f[R] -Sets the size (in bytes) of the prefetch distance for object allocation. -Memory about to be written with the value of new objects is prefetched -up to this distance starting from the address of the last allocated -object. -Each Java thread has its own allocation point. -.RS -.PP -Negative values denote that prefetch distance is chosen based on the -platform. -Positive values are bytes to prefetch. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default value is set to -1. -.PP -The following example shows how to set the prefetch distance to 1024 -bytes: -.RS -.PP -\f[V]-XX:AllocatePrefetchDistance=1024\f[R] -.RE -.RE -.TP -\f[V]-XX:AllocatePrefetchInstr=\f[R]\f[I]instruction\f[R] -Sets the prefetch instruction to prefetch ahead of the allocation -pointer. -Possible values are from 0 to 3. -The actual instructions behind the values depend on the platform. -By default, the prefetch instruction is set to 0: -.RS -.RS -.PP -\f[V]-XX:AllocatePrefetchInstr=0\f[R] -.RE -.RE -.TP -\f[V]-XX:AllocatePrefetchLines=\f[R]\f[I]lines\f[R] -Sets the number of cache lines to load after the last object allocation -by using the prefetch instructions generated in compiled code. -The default value is 1 if the last allocated object was an instance, and -3 if it was an array. -.RS -.PP -The following example shows how to set the number of loaded cache lines -to 5: -.RS -.PP -\f[V]-XX:AllocatePrefetchLines=5\f[R] -.RE -.RE -.TP -\f[V]-XX:AllocatePrefetchStepSize=\f[R]\f[I]size\f[R] -Sets the step size (in bytes) for sequential prefetch instructions. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -By default, the step size is set to 16 bytes: -.RS -.RS -.PP -\f[V]-XX:AllocatePrefetchStepSize=16\f[R] -.RE -.RE -.TP -\f[V]-XX:AllocatePrefetchStyle=\f[R]\f[I]style\f[R] -Sets the generated code style for prefetch instructions. -The \f[I]style\f[R] argument is an integer from 0 to 3: -.RS -.TP -\f[V]0\f[R] -Don\[aq]t generate prefetch instructions. -.TP -\f[V]1\f[R] -Execute prefetch instructions after each allocation. -This is the default setting. -.TP -\f[V]2\f[R] -Use the thread-local allocation block (TLAB) watermark pointer to -determine when prefetch instructions are executed. -.TP -\f[V]3\f[R] -Generate one prefetch instruction per cache line. -.RE -.TP -\f[V]-XX:+BackgroundCompilation\f[R] -Enables background compilation. -This option is enabled by default. -To disable background compilation, specify -\f[V]-XX:-BackgroundCompilation\f[R] (this is equivalent to specifying -\f[V]-Xbatch\f[R]). -.TP -\f[V]-XX:CICompilerCount=\f[R]\f[I]threads\f[R] -Sets the number of compiler threads to use for compilation. -By default, the number of compiler threads is selected automatically -depending on the number of CPUs and memory available for compiled code. -The following example shows how to set the number of threads to 2: -.RS -.RS -.PP -\f[V]-XX:CICompilerCount=2\f[R] -.RE -.RE -.TP -\f[V]-XX:+UseDynamicNumberOfCompilerThreads\f[R] -Dynamically create compiler thread up to the limit specified by -\f[V]-XX:CICompilerCount\f[R]. -This option is enabled by default. -.TP -\f[V]-XX:CompileCommand=\f[R]\f[I]command\f[R]\f[V],\f[R]\f[I]method\f[R][\f[V],\f[R]\f[I]option\f[R]] -Specifies a \f[I]command\f[R] to perform on a \f[I]method\f[R]. -For example, to exclude the \f[V]indexOf()\f[R] method of the -\f[V]String\f[R] class from being compiled, use the following: -.RS -.RS -.PP -\f[V]-XX:CompileCommand=exclude,java/lang/String.indexOf\f[R] -.RE -.PP -Note that the full class name is specified, including all packages and -subpackages separated by a slash (\f[V]/\f[R]). -For easier cut-and-paste operations, it\[aq]s also possible to use the -method name format produced by the \f[V]-XX:+PrintCompilation\f[R] and -\f[V]-XX:+LogCompilation\f[R] options: -.RS -.PP -\f[V]-XX:CompileCommand=exclude,java.lang.String::indexOf\f[R] -.RE -.PP -If the method is specified without the signature, then the command is -applied to all methods with the specified name. -However, you can also specify the signature of the method in the class -file format. -In this case, you should enclose the arguments in quotation marks, -because otherwise the shell treats the semicolon as a command end. -For example, if you want to exclude only the \f[V]indexOf(String)\f[R] -method of the \f[V]String\f[R] class from being compiled, use the -following: -.RS -.PP -\f[V]-XX:CompileCommand=\[dq]exclude,java/lang/String.indexOf,(Ljava/lang/String;)I\[dq]\f[R] -.RE -.PP -You can also use the asterisk (*) as a wildcard for class and method -names. -For example, to exclude all \f[V]indexOf()\f[R] methods in all classes -from being compiled, use the following: -.RS -.PP -\f[V]-XX:CompileCommand=exclude,*.indexOf\f[R] -.RE -.PP -The commas and periods are aliases for spaces, making it easier to pass -compiler commands through a shell. -You can pass arguments to \f[V]-XX:CompileCommand\f[R] using spaces as -separators by enclosing the argument in quotation marks: -.RS -.PP -\f[V]-XX:CompileCommand=\[dq]exclude java/lang/String indexOf\[dq]\f[R] -.RE -.PP -Note that after parsing the commands passed on the command line using -the \f[V]-XX:CompileCommand\f[R] options, the JIT compiler then reads -commands from the \f[V].hotspot_compiler\f[R] file. -You can add commands to this file or specify a different file using the -\f[V]-XX:CompileCommandFile\f[R] option. -.PP -To add several commands, either specify the \f[V]-XX:CompileCommand\f[R] -option multiple times, or separate each argument with the new line -separator (\f[V]\[rs]n\f[R]). -The following commands are available: -.TP -\f[V]break\f[R] -Sets a breakpoint when debugging the JVM to stop at the beginning of -compilation of the specified method. -.TP -\f[V]compileonly\f[R] -Excludes all methods from compilation except for the specified method. -As an alternative, you can use the \f[V]-XX:CompileOnly\f[R] option, -which lets you specify several methods. -.TP -\f[V]dontinline\f[R] -Prevents inlining of the specified method. -.TP -\f[V]exclude\f[R] -Excludes the specified method from compilation. -.TP -\f[V]help\f[R] -Prints a help message for the \f[V]-XX:CompileCommand\f[R] option. -.TP -\f[V]inline\f[R] -Attempts to inline the specified method. -.TP -\f[V]log\f[R] -Excludes compilation logging (with the \f[V]-XX:+LogCompilation\f[R] -option) for all methods except for the specified method. -By default, logging is performed for all compiled methods. -.TP -\f[V]option\f[R] -Passes a JIT compilation option to the specified method in place of the -last argument (\f[V]option\f[R]). -The compilation option is set at the end, after the method name. -For example, to enable the \f[V]BlockLayoutByFrequency\f[R] option for -the \f[V]append()\f[R] method of the \f[V]StringBuffer\f[R] class, use -the following: -.RS -.RS -.PP -\f[V]-XX:CompileCommand=option,java/lang/StringBuffer.append,BlockLayoutByFrequency\f[R] -.RE -.PP -You can specify multiple compilation options, separated by commas or -spaces. -.RE -.TP -\f[V]print\f[R] -Prints generated assembler code after compilation of the specified -method. -.TP -\f[V]quiet\f[R] -Instructs not to print the compile commands. -By default, the commands that you specify with the -\f[V]-XX:CompileCommand\f[R] option are printed; for example, if you -exclude from compilation the \f[V]indexOf()\f[R] method of the -\f[V]String\f[R] class, then the following is printed to standard -output: -.RS -.RS -.PP -\f[V]CompilerOracle: exclude java/lang/String.indexOf\f[R] -.RE -.PP -You can suppress this by specifying the -\f[V]-XX:CompileCommand=quiet\f[R] option before other -\f[V]-XX:CompileCommand\f[R] options. -.RE -.RE -.TP -\f[V]-XX:CompileCommandFile=\f[R]\f[I]filename\f[R] -Sets the file from which JIT compiler commands are read. -By default, the \f[V].hotspot_compiler\f[R] file is used to store -commands performed by the JIT compiler. -.RS -.PP -Each line in the command file represents a command, a class name, and a -method name for which the command is used. -For example, this line prints assembly code for the \f[V]toString()\f[R] -method of the \f[V]String\f[R] class: -.RS -.PP -\f[V]print java/lang/String toString\f[R] -.RE -.PP -If you\[aq]re using commands for the JIT compiler to perform on methods, -then see the \f[V]-XX:CompileCommand\f[R] option. -.RE -.TP -\f[V]-XX:CompilerDirectivesFile=\f[R]\f[I]file\f[R] -Adds directives from a file to the directives stack when a program -starts. -See \f[B]Compiler Control\f[R] -[https://docs.oracle.com/en/java/javase/12/vm/compiler-control1.html#GUID-94AD8194-786A-4F19-BFFF-278F8E237F3A]. -.RS -.PP -The \f[V]-XX:CompilerDirectivesFile\f[R] option has to be used together -with the \f[V]-XX:UnlockDiagnosticVMOptions\f[R] option that unlocks -diagnostic JVM options. -.RE -.TP -\f[V]-XX:+CompilerDirectivesPrint\f[R] -Prints the directives stack when the program starts or when a new -directive is added. -.RS -.PP -The \f[V]-XX:+CompilerDirectivesPrint\f[R] option has to be used -together with the \f[V]-XX:UnlockDiagnosticVMOptions\f[R] option that -unlocks diagnostic JVM options. -.RE -.TP -\f[V]-XX:CompileOnly=\f[R]\f[I]methods\f[R] -Sets the list of methods (separated by commas) to which compilation -should be restricted. -Only the specified methods are compiled. -.RS -.PP -\f[V]-XX:CompileOnly=method1,method2,...,methodN\f[R] is an alias for: -.IP -.nf -\f[CB] --XX:CompileCommand=compileonly,method1 --XX:CompileCommand=compileonly,method2 -\&... --XX:CompileCommand=compileonly,methodN -\f[R] -.fi -.RE -.TP -\f[V]-XX:CompileThresholdScaling=\f[R]\f[I]scale\f[R] -Provides unified control of first compilation. -This option controls when methods are first compiled for both the tiered -and the nontiered modes of operation. -The \f[V]CompileThresholdScaling\f[R] option has a floating point value -between 0 and +Inf and scales the thresholds corresponding to the -current mode of operation (both tiered and nontiered). -Setting \f[V]CompileThresholdScaling\f[R] to a value less than 1.0 -results in earlier compilation while values greater than 1.0 delay -compilation. -Setting \f[V]CompileThresholdScaling\f[R] to 0 is equivalent to -disabling compilation. -.TP -\f[V]-XX:+DoEscapeAnalysis\f[R] -Enables the use of escape analysis. -This option is enabled by default. -To disable the use of escape analysis, specify -\f[V]-XX:-DoEscapeAnalysis\f[R]. -.TP -\f[V]-XX:InitialCodeCacheSize=\f[R]\f[I]size\f[R] -Sets the initial code cache size (in bytes). -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default value depends on the platform. -The initial code cache size shouldn\[aq]t be less than the system\[aq]s -minimal memory page size. -The following example shows how to set the initial code cache size to 32 -KB: -.RS -.RS -.PP -\f[V]-XX:InitialCodeCacheSize=32k\f[R] -.RE -.RE -.TP -\f[V]-XX:+Inline\f[R] -Enables method inlining. -This option is enabled by default to increase performance. -To disable method inlining, specify \f[V]-XX:-Inline\f[R]. -.TP -\f[V]-XX:InlineSmallCode=\f[R]\f[I]size\f[R] -Sets the maximum code size (in bytes) for already compiled methods that -may be inlined. -This flag only applies to the C2 compiler. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default value depends on the platform and on whether tiered -compilation is enabled. -In the following example it is set to 1000 bytes: -.RS -.RS -.PP -\f[V]-XX:InlineSmallCode=1000\f[R] -.RE -.RE -.TP -\f[V]-XX:+LogCompilation\f[R] -Enables logging of compilation activity to a file named -\f[V]hotspot.log\f[R] in the current working directory. -You can specify a different log file path and name using the -\f[V]-XX:LogFile\f[R] option. -.RS -.PP -By default, this option is disabled and compilation activity isn\[aq]t -logged. -The \f[V]-XX:+LogCompilation\f[R] option has to be used together with -the \f[V]-XX:UnlockDiagnosticVMOptions\f[R] option that unlocks -diagnostic JVM options. -.PP -You can enable verbose diagnostic output with a message printed to the -console every time a method is compiled by using the -\f[V]-XX:+PrintCompilation\f[R] option. -.RE -.TP -\f[V]-XX:FreqInlineSize=\f[R]\f[I]size\f[R] -Sets the maximum bytecode size (in bytes) of a hot method to be inlined. -This flag only applies to the C2 compiler. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default value depends on the platform. -In the following example it is set to 325 bytes: -.RS -.RS -.PP -\f[V]-XX:FreqInlineSize=325\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxInlineSize=\f[R]\f[I]size\f[R] -Sets the maximum bytecode size (in bytes) of a cold method to be -inlined. -This flag only applies to the C2 compiler. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -By default, the maximum bytecode size is set to 35 bytes: -.RS -.RS -.PP -\f[V]-XX:MaxInlineSize=35\f[R] -.RE -.RE -.TP -\f[V]-XX:C1MaxInlineSize=\f[R]\f[I]size\f[R] -Sets the maximum bytecode size (in bytes) of a cold method to be -inlined. -This flag only applies to the C1 compiler. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -By default, the maximum bytecode size is set to 35 bytes: -.RS -.RS -.PP -\f[V]-XX:MaxInlineSize=35\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxTrivialSize=\f[R]\f[I]size\f[R] -Sets the maximum bytecode size (in bytes) of a trivial method to be -inlined. -This flag only applies to the C2 compiler. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -By default, the maximum bytecode size of a trivial method is set to 6 -bytes: -.RS -.RS -.PP -\f[V]-XX:MaxTrivialSize=6\f[R] -.RE -.RE -.TP -\f[V]-XX:C1MaxTrivialSize=\f[R]\f[I]size\f[R] -Sets the maximum bytecode size (in bytes) of a trivial method to be -inlined. -This flag only applies to the C1 compiler. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -By default, the maximum bytecode size of a trivial method is set to 6 -bytes: -.RS -.RS -.PP -\f[V]-XX:MaxTrivialSize=6\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxNodeLimit=\f[R]\f[I]nodes\f[R] -Sets the maximum number of nodes to be used during single method -compilation. -By default the value depends on the features enabled. -In the following example the maximum number of nodes is set to 100,000: -.RS -.RS -.PP -\f[V]-XX:MaxNodeLimit=100000\f[R] -.RE -.RE -.TP -\f[V]-XX:NonNMethodCodeHeapSize=\f[R]\f[I]size\f[R] -Sets the size in bytes of the code segment containing nonmethod code. -.RS -.PP -A nonmethod code segment containing nonmethod code, such as compiler -buffers and the bytecode interpreter. -This code type stays in the code cache forever. -This flag is used only if \f[V]-XX:SegmentedCodeCache\f[R] is enabled. -.RE -.TP -\f[V]-XX:NonProfiledCodeHeapSize=\f[R]\f[I]size\f[R] -Sets the size in bytes of the code segment containing nonprofiled -methods. -This flag is used only if \f[V]-XX:SegmentedCodeCache\f[R] is enabled. -.TP -\f[V]-XX:+OptimizeStringConcat\f[R] -Enables the optimization of \f[V]String\f[R] concatenation operations. -This option is enabled by default. -To disable the optimization of \f[V]String\f[R] concatenation -operations, specify \f[V]-XX:-OptimizeStringConcat\f[R]. -.TP -\f[V]-XX:+PrintAssembly\f[R] -Enables printing of assembly code for bytecoded and native methods by -using the external \f[V]hsdis-.so\f[R] or \f[V].dll\f[R] library. -For 64-bit VM on Windows, it\[aq]s \f[V]hsdis-amd64.dll\f[R]. -This lets you to see the generated code, which may help you to diagnose -performance issues. -.RS -.PP -By default, this option is disabled and assembly code isn\[aq]t printed. -The \f[V]-XX:+PrintAssembly\f[R] option has to be used together with the -\f[V]-XX:UnlockDiagnosticVMOptions\f[R] option that unlocks diagnostic -JVM options. -.RE -.TP -\f[V]-XX:ProfiledCodeHeapSize=\f[R]\f[I]size\f[R] -Sets the size in bytes of the code segment containing profiled methods. -This flag is used only if \f[V]-XX:SegmentedCodeCache\f[R] is enabled. -.TP -\f[V]-XX:+PrintCompilation\f[R] -Enables verbose diagnostic output from the JVM by printing a message to -the console every time a method is compiled. -This lets you to see which methods actually get compiled. -By default, this option is disabled and diagnostic output isn\[aq]t -printed. -.RS -.PP -You can also log compilation activity to a file by using the -\f[V]-XX:+LogCompilation\f[R] option. -.RE -.TP -\f[V]-XX:+PrintInlining\f[R] -Enables printing of inlining decisions. -This let\[aq]s you see which methods are getting inlined. -.RS -.PP -By default, this option is disabled and inlining information isn\[aq]t -printed. -The \f[V]-XX:+PrintInlining\f[R] option has to be used together with the -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R] option that unlocks diagnostic -JVM options. -.RE -.TP -\f[V]-XX:ReservedCodeCacheSize=\f[R]\f[I]size\f[R] -Sets the maximum code cache size (in bytes) for JIT-compiled code. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default maximum code cache size is 240 MB; if you disable tiered -compilation with the option \f[V]-XX:-TieredCompilation\f[R], then the -default size is 48 MB. -This option has a limit of 2 GB; otherwise, an error is generated. -The maximum code cache size shouldn\[aq]t be less than the initial code -cache size; see the option \f[V]-XX:InitialCodeCacheSize\f[R]. -.TP -\f[V]-XX:+SegmentedCodeCache\f[R] -Enables segmentation of the code cache, without which the code cache -consists of one large segment. -With \f[V]-XX:+SegmentedCodeCache\f[R], separate segments will be used -for non-method, profiled method, and non-profiled method code. -The segments are not resized at runtime. -The advantages are better control of the memory footprint, reduced code -fragmentation, and better CPU iTLB (instruction translation lookaside -buffer) and instruction cache behavior due to improved locality. -.RS -.PP -The feature is enabled by default if tiered compilation is enabled -(\f[V]-XX:+TieredCompilation\f[R] ) and the reserved code cache size -(\f[V]-XX:ReservedCodeCacheSize\f[R]) is at least 240 MB. -.RE -.TP -\f[V]-XX:StartAggressiveSweepingAt=\f[R]\f[I]percent\f[R] -Forces stack scanning of active methods to aggressively remove unused -code when only the given percentage of the code cache is free. -The default value is 10%. -.TP -\f[V]-XX:-TieredCompilation\f[R] -Disables the use of tiered compilation. -By default, this option is enabled. -.TP -\f[V]-XX:UseSSE=\f[R]\f[I]version\f[R] -Enables the use of SSE instruction set of a specified version. -Is set by default to the highest supported version available (x86 only). -.TP -\f[V]-XX:UseAVX=\f[R]\f[I]version\f[R] -Enables the use of AVX instruction set of a specified version. -Is set by default to the highest supported version available (x86 only). -.TP -\f[V]-XX:+UseAES\f[R] -Enables hardware-based AES intrinsics for hardware that supports it. -This option is on by default on hardware that has the necessary -instructions. -The \f[V]-XX:+UseAES\f[R] is used in conjunction with -\f[V]UseAESIntrinsics\f[R]. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseAESIntrinsics\f[R] -Enables AES intrinsics. -Specifying \f[V]-XX:+UseAESIntrinsics\f[R] is equivalent to also -enabling \f[V]-XX:+UseAES\f[R]. -To disable hardware-based AES intrinsics, specify -\f[V]-XX:-UseAES -XX:-UseAESIntrinsics\f[R]. -For example, to enable hardware AES, use the following flags: -.RS -.RS -.PP -\f[V]-XX:+UseAES -XX:+UseAESIntrinsics\f[R] -.RE -.PP -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.RE -.TP -\f[V]-XX:+UseAESCTRIntrinsics\f[R] -Analogous to \f[V]-XX:+UseAESIntrinsics\f[R] enables AES/CTR intrinsics. -.TP -\f[V]-XX:+UseGHASHIntrinsics\f[R] -Controls the use of GHASH intrinsics. -Enabled by default on platforms that support the corresponding -instructions. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseChaCha20Intrinsics\f[R] -Enable ChaCha20 intrinsics. -This option is on by default for supported platforms. -To disable ChaCha20 intrinsics, specify -\f[V]-XX:-UseChaCha20Intrinsics\f[R]. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UsePoly1305Intrinsics\f[R] -Enable Poly1305 intrinsics. -This option is on by default for supported platforms. -To disable Poly1305 intrinsics, specify -\f[V]-XX:-UsePoly1305Intrinsics\f[R]. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseBASE64Intrinsics\f[R] -Controls the use of accelerated BASE64 encoding routines for -\f[V]java.util.Base64\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseAdler32Intrinsics\f[R] -Controls the use of Adler32 checksum algorithm intrinsic for -\f[V]java.util.zip.Adler32\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseCRC32Intrinsics\f[R] -Controls the use of CRC32 intrinsics for \f[V]java.util.zip.CRC32\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseCRC32CIntrinsics\f[R] -Controls the use of CRC32C intrinsics for -\f[V]java.util.zip.CRC32C\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseSHA\f[R] -Enables hardware-based intrinsics for SHA crypto hash functions for some -hardware. -The \f[V]UseSHA\f[R] option is used in conjunction with the -\f[V]UseSHA1Intrinsics\f[R], \f[V]UseSHA256Intrinsics\f[R], and -\f[V]UseSHA512Intrinsics\f[R] options. -.RS -.PP -The \f[V]UseSHA\f[R] and \f[V]UseSHA*Intrinsics\f[R] flags are enabled -by default on machines that support the corresponding instructions. -.PP -This feature is applicable only when using the -\f[V]sun.security.provider.Sun\f[R] provider for SHA operations. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.PP -To disable all hardware-based SHA intrinsics, specify the -\f[V]-XX:-UseSHA\f[R]. -To disable only a particular SHA intrinsic, use the appropriate -corresponding option. -For example: \f[V]-XX:-UseSHA256Intrinsics\f[R]. -.RE -.TP -\f[V]-XX:+UseSHA1Intrinsics\f[R] -Enables intrinsics for SHA-1 crypto hash function. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseSHA256Intrinsics\f[R] -Enables intrinsics for SHA-224 and SHA-256 crypto hash functions. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseSHA512Intrinsics\f[R] -Enables intrinsics for SHA-384 and SHA-512 crypto hash functions. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseMathExactIntrinsics\f[R] -Enables intrinsification of various \f[V]java.lang.Math.*Exact()\f[R] -functions. -Enabled by default. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseMultiplyToLenIntrinsic\f[R] -Enables intrinsification of \f[V]BigInteger.multiplyToLen()\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP --XX:+UseSquareToLenIntrinsic -Enables intrinsification of \f[V]BigInteger.squareToLen()\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP --XX:+UseMulAddIntrinsic -Enables intrinsification of \f[V]BigInteger.mulAdd()\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP --XX:+UseMontgomeryMultiplyIntrinsic -Enables intrinsification of \f[V]BigInteger.montgomeryMultiply()\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP --XX:+UseMontgomerySquareIntrinsic -Enables intrinsification of \f[V]BigInteger.montgomerySquare()\f[R]. -Enabled by default on platforms that support it. -Flags that control intrinsics now require the option -\f[V]-XX:+UnlockDiagnosticVMOptions\f[R]. -.TP -\f[V]-XX:+UseCMoveUnconditionally\f[R] -Generates CMove (scalar and vector) instructions regardless of -profitability analysis. -.TP -\f[V]-XX:+UseCodeCacheFlushing\f[R] -Enables flushing of the code cache before shutting down the compiler. -This option is enabled by default. -To disable flushing of the code cache before shutting down the compiler, -specify \f[V]-XX:-UseCodeCacheFlushing\f[R]. -.TP -\f[V]-XX:+UseCondCardMark\f[R] -Enables checking if the card is already marked before updating the card -table. -This option is disabled by default. -It should be used only on machines with multiple sockets, where it -increases the performance of Java applications that rely on concurrent -operations. -.TP -\f[V]-XX:+UseCountedLoopSafepoints\f[R] -Keeps safepoints in counted loops. -Its default value depends on whether the selected garbage collector -requires low latency safepoints. -.TP -\f[V]-XX:LoopStripMiningIter=\f[R]\f[I]number_of_iterations\f[R] -Controls the number of iterations in the inner strip mined loop. -Strip mining transforms counted loops into two level nested loops. -Safepoints are kept in the outer loop while the inner loop can execute -at full speed. -This option controls the maximum number of iterations in the inner loop. -The default value is 1,000. -.TP -\f[V]-XX:LoopStripMiningIterShortLoop=\f[R]\f[I]number_of_iterations\f[R] -Controls loop strip mining optimization. -Loops with the number of iterations less than specified will not have -safepoints in them. -Default value is 1/10th of \f[V]-XX:LoopStripMiningIter\f[R]. -.TP -\f[V]-XX:+UseFMA\f[R] -Enables hardware-based FMA intrinsics for hardware where FMA -instructions are available (such as, Intel and ARM64). -FMA intrinsics are generated for the -\f[V]java.lang.Math.fma(\f[R]\f[I]a\f[R]\f[V],\f[R] -\f[I]b\f[R]\f[V],\f[R] \f[I]c\f[R]\f[V])\f[R] methods that calculate the -value of \f[V](\f[R] \f[I]a\f[R] \f[V]*\f[R] \f[I]b\f[R] \f[V]+\f[R] -\f[I]c\f[R] \f[V])\f[R] expressions. -.TP -\f[V]-XX:+UseSuperWord\f[R] -Enables the transformation of scalar operations into superword -operations. -Superword is a vectorization optimization. -This option is enabled by default. -To disable the transformation of scalar operations into superword -operations, specify \f[V]-XX:-UseSuperWord\f[R]. -.SH ADVANCED SERVICEABILITY OPTIONS FOR JAVA -.PP -These \f[V]java\f[R] options provide the ability to gather system -information and perform extensive debugging. -.TP -\f[V]-XX:+DisableAttachMechanism\f[R] -Disables the mechanism that lets tools attach to the JVM. -By default, this option is disabled, meaning that the attach mechanism -is enabled and you can use diagnostics and troubleshooting tools such as -\f[V]jcmd\f[R], \f[V]jstack\f[R], \f[V]jmap\f[R], and \f[V]jinfo\f[R]. -.RS -.RS -.PP -\f[B]Note:\f[R] The tools such as \f[B]jcmd\f[R], \f[B]jinfo\f[R], -\f[B]jmap\f[R], and \f[B]jstack\f[R] shipped with the JDK aren\[aq]t -supported when using the tools from one JDK version to troubleshoot a -different JDK version. -.RE -.RE -.TP -\f[V]-XX:+DTraceAllocProbes\f[R] -\f[B]Linux and macOS:\f[R] Enable \f[V]dtrace\f[R] tool probes for -object allocation. -.TP -\f[V]-XX:+DTraceMethodProbes\f[R] -\f[B]Linux and macOS:\f[R] Enable \f[V]dtrace\f[R] tool probes for -method-entry and method-exit. -.TP -\f[V]-XX:+DTraceMonitorProbes\f[R] -\f[B]Linux and macOS:\f[R] Enable \f[V]dtrace\f[R] tool probes for -monitor events. -.TP -\f[V]-XX:+HeapDumpOnOutOfMemoryError\f[R] -Enables the dumping of the Java heap to a file in the current directory -by using the heap profiler (HPROF) when a -\f[V]java.lang.OutOfMemoryError\f[R] exception is thrown. -You can explicitly set the heap dump file path and name using the -\f[V]-XX:HeapDumpPath\f[R] option. -By default, this option is disabled and the heap isn\[aq]t dumped when -an \f[V]OutOfMemoryError\f[R] exception is thrown. -.TP -\f[V]-XX:HeapDumpPath=\f[R]\f[I]path\f[R] -Sets the path and file name for writing the heap dump provided by the -heap profiler (HPROF) when the \f[V]-XX:+HeapDumpOnOutOfMemoryError\f[R] -option is set. -By default, the file is created in the current working directory, and -it\[aq]s named \f[V]java_pid.hprof\f[R] where \f[V]\f[R] is -the identifier of the process that caused the error. -The following example shows how to set the default file explicitly -(\f[V]%p\f[R] represents the current process identifier): -.RS -.RS -.PP -\f[V]-XX:HeapDumpPath=./java_pid%p.hprof\f[R] -.RE -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] The following example shows how to set the heap -dump file to \f[V]/var/log/java/java_heapdump.hprof\f[R]: -.RS 2 -.RS -.PP -\f[V]-XX:HeapDumpPath=/var/log/java/java_heapdump.hprof\f[R] -.RE -.RE -.IP \[bu] 2 -\f[B]Windows:\f[R] The following example shows how to set the heap dump -file to \f[V]C:/log/java/java_heapdump.log\f[R]: -.RS 2 -.RS -.PP -\f[V]-XX:HeapDumpPath=C:/log/java/java_heapdump.log\f[R] -.RE -.RE -.RE -.TP -\f[V]-XX:LogFile=\f[R]\f[I]path\f[R] -Sets the path and file name to where log data is written. -By default, the file is created in the current working directory, and -it\[aq]s named \f[V]hotspot.log\f[R]. -.RS -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] The following example shows how to set the log -file to \f[V]/var/log/java/hotspot.log\f[R]: -.RS 2 -.RS -.PP -\f[V]-XX:LogFile=/var/log/java/hotspot.log\f[R] -.RE -.RE -.IP \[bu] 2 -\f[B]Windows:\f[R] The following example shows how to set the log file -to \f[V]C:/log/java/hotspot.log\f[R]: -.RS 2 -.RS -.PP -\f[V]-XX:LogFile=C:/log/java/hotspot.log\f[R] -.RE -.RE -.RE -.TP -\f[V]-XX:+PrintClassHistogram\f[R] -Enables printing of a class instance histogram after one of the -following events: -.RS -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] \f[V]Control+\[rs]\f[R] (\f[V]SIGQUIT\f[R]) -.IP \[bu] 2 -\f[B]Windows:\f[R] \f[V]Control+C\f[R] (\f[V]SIGTERM\f[R]) -.PP -By default, this option is disabled. -.PP -Setting this option is equivalent to running the \f[V]jmap -histo\f[R] -command, or the \f[V]jcmd\f[R] \f[I]pid\f[R] -\f[V]GC.class_histogram\f[R] command, where \f[I]pid\f[R] is the current -Java process identifier. -.RE -.TP -\f[V]-XX:+PrintConcurrentLocks\f[R] -Enables printing of \f[V]java.util.concurrent\f[R] locks after one of -the following events: -.RS -.IP \[bu] 2 -\f[B]Non-Windows:\f[R] \f[V]Control+\[rs]\f[R] (\f[V]SIGQUIT\f[R]) -.IP \[bu] 2 -\f[B]Windows:\f[R] \f[V]Control+C\f[R] (\f[V]SIGTERM\f[R]) -.PP -By default, this option is disabled. -.PP -Setting this option is equivalent to running the \f[V]jstack -l\f[R] -command or the \f[V]jcmd\f[R] \f[I]pid\f[R] \f[V]Thread.print -l\f[R] -command, where \f[I]pid\f[R] is the current Java process identifier. -.RE -.TP -\f[V]-XX:+PrintFlagsRanges\f[R] -Prints the range specified and allows automatic testing of the values. -See \f[B]Validate Java Virtual Machine Flag Arguments\f[R]. -.TP -\f[V]-XX:+PerfDataSaveToFile\f[R] -If enabled, saves \f[B]jstat\f[R] binary data when the Java application -exits. -This binary data is saved in a file named -\f[V]hsperfdata_\f[R]\f[I]pid\f[R], where \f[I]pid\f[R] is the process -identifier of the Java application that you ran. -Use the \f[V]jstat\f[R] command to display the performance data -contained in this file as follows: -.RS -.RS -.PP -\f[V]jstat -class file:///\f[R]\f[I]path\f[R]\f[V]/hsperfdata_\f[R]\f[I]pid\f[R] -.RE -.RS -.PP -\f[V]jstat -gc file:///\f[R]\f[I]path\f[R]\f[V]/hsperfdata_\f[R]\f[I]pid\f[R] -.RE -.RE -.TP -\f[V]-XX:+UsePerfData\f[R] -Enables the \f[V]perfdata\f[R] feature. -This option is enabled by default to allow JVM monitoring and -performance testing. -Disabling it suppresses the creation of the \f[V]hsperfdata_userid\f[R] -directories. -To disable the \f[V]perfdata\f[R] feature, specify -\f[V]-XX:-UsePerfData\f[R]. -.SH ADVANCED GARBAGE COLLECTION OPTIONS FOR JAVA -.PP -These \f[V]java\f[R] options control how garbage collection (GC) is -performed by the Java HotSpot VM. -.TP -\f[V]-XX:+AggressiveHeap\f[R] -Enables Java heap optimization. -This sets various parameters to be optimal for long-running jobs with -intensive memory allocation, based on the configuration of the computer -(RAM and CPU). -By default, the option is disabled and the heap sizes are configured -less aggressively. -.TP -\f[V]-XX:+AlwaysPreTouch\f[R] -Requests the VM to touch every page on the Java heap after requesting it -from the operating system and before handing memory out to the -application. -By default, this option is disabled and all pages are committed as the -application uses the heap space. -.TP -\f[V]-XX:ConcGCThreads=\f[R]\f[I]threads\f[R] -Sets the number of threads used for concurrent GC. -Sets \f[I]\f[VI]threads\f[I]\f[R] to approximately 1/4 of the number of -parallel garbage collection threads. -The default value depends on the number of CPUs available to the JVM. -.RS -.PP -For example, to set the number of threads for concurrent GC to 2, -specify the following option: -.RS -.PP -\f[V]-XX:ConcGCThreads=2\f[R] -.RE -.RE -.TP -\f[V]-XX:+DisableExplicitGC\f[R] -Enables the option that disables processing of calls to the -\f[V]System.gc()\f[R] method. -This option is disabled by default, meaning that calls to -\f[V]System.gc()\f[R] are processed. -If processing of calls to \f[V]System.gc()\f[R] is disabled, then the -JVM still performs GC when necessary. -.TP -\f[V]-XX:+ExplicitGCInvokesConcurrent\f[R] -Enables invoking of concurrent GC by using the \f[V]System.gc()\f[R] -request. -This option is disabled by default and can be enabled only with the -\f[V]-XX:+UseG1GC\f[R] option. -.TP -\f[V]-XX:G1AdaptiveIHOPNumInitialSamples=\f[R]\f[I]number\f[R] -When \f[V]-XX:UseAdaptiveIHOP\f[R] is enabled, this option sets the -number of completed marking cycles used to gather samples until G1 -adaptively determines the optimum value of -\f[V]-XX:InitiatingHeapOccupancyPercent\f[R]. -Before, G1 uses the value of -\f[V]-XX:InitiatingHeapOccupancyPercent\f[R] directly for this purpose. -The default value is 3. -.TP -\f[V]-XX:G1HeapRegionSize=\f[R]\f[I]size\f[R] -Sets the size of the regions into which the Java heap is subdivided when -using the garbage-first (G1) collector. -The value is a power of 2 and can range from 1 MB to 32 MB. -The default region size is determined ergonomically based on the heap -size with a goal of approximately 2048 regions. -.RS -.PP -The following example sets the size of the subdivisions to 16 MB: -.RS -.PP -\f[V]-XX:G1HeapRegionSize=16m\f[R] -.RE -.RE -.TP -\f[V]-XX:G1HeapWastePercent=\f[R]\f[I]percent\f[R] -Sets the percentage of heap that you\[aq]re willing to waste. -The Java HotSpot VM doesn\[aq]t initiate the mixed garbage collection -cycle when the reclaimable percentage is less than the heap waste -percentage. -The default is 5 percent. -.TP -\f[V]-XX:G1MaxNewSizePercent=\f[R]\f[I]percent\f[R] -Sets the percentage of the heap size to use as the maximum for the young -generation size. -The default value is 60 percent of your Java heap. -.RS -.PP -This is an experimental flag. -This setting replaces the \f[V]-XX:DefaultMaxNewGenPercent\f[R] setting. -.RE -.TP -\f[V]-XX:G1MixedGCCountTarget=\f[R]\f[I]number\f[R] -Sets the target number of mixed garbage collections after a marking -cycle to collect old regions with at most -\f[V]G1MixedGCLIveThresholdPercent\f[R] live data. -The default is 8 mixed garbage collections. -The goal for mixed collections is to be within this target number. -.TP -\f[V]-XX:G1MixedGCLiveThresholdPercent=\f[R]\f[I]percent\f[R] -Sets the occupancy threshold for an old region to be included in a mixed -garbage collection cycle. -The default occupancy is 85 percent. -.RS -.PP -This is an experimental flag. -This setting replaces the -\f[V]-XX:G1OldCSetRegionLiveThresholdPercent\f[R] setting. -.RE -.TP -\f[V]-XX:G1NewSizePercent=\f[R]\f[I]percent\f[R] -Sets the percentage of the heap to use as the minimum for the young -generation size. -The default value is 5 percent of your Java heap. -.RS -.PP -This is an experimental flag. -This setting replaces the \f[V]-XX:DefaultMinNewGenPercent\f[R] setting. -.RE -.TP -\f[V]-XX:G1OldCSetRegionThresholdPercent=\f[R]\f[I]percent\f[R] -Sets an upper limit on the number of old regions to be collected during -a mixed garbage collection cycle. -The default is 10 percent of the Java heap. -.TP -\f[V]-XX:G1ReservePercent=\f[R]\f[I]percent\f[R] -Sets the percentage of the heap (0 to 50) that\[aq]s reserved as a false -ceiling to reduce the possibility of promotion failure for the G1 -collector. -When you increase or decrease the percentage, ensure that you adjust the -total Java heap by the same amount. -By default, this option is set to 10%. -.RS -.PP -The following example sets the reserved heap to 20%: -.RS -.PP -\f[V]-XX:G1ReservePercent=20\f[R] -.RE -.RE -.TP -\f[V]-XX:+G1UseAdaptiveIHOP\f[R] -Controls adaptive calculation of the old generation occupancy to start -background work preparing for an old generation collection. -If enabled, G1 uses \f[V]-XX:InitiatingHeapOccupancyPercent\f[R] for the -first few times as specified by the value of -\f[V]-XX:G1AdaptiveIHOPNumInitialSamples\f[R], and after that adaptively -calculates a new optimum value for the initiating occupancy -automatically. -Otherwise, the old generation collection process always starts at the -old generation occupancy determined by -\f[V]-XX:InitiatingHeapOccupancyPercent\f[R]. -.RS -.PP -The default is enabled. -.RE -.TP -\f[V]-XX:InitialHeapSize=\f[R]\f[I]size\f[R] -Sets the initial size (in bytes) of the memory allocation pool. -This value must be either 0, or a multiple of 1024 and greater than 1 -MB. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default value is selected at run time based on the system -configuration. -.RS -.PP -The following examples show how to set the size of allocated memory to 6 -MB using various units: -.IP -.nf -\f[CB] --XX:InitialHeapSize=6291456 --XX:InitialHeapSize=6144k --XX:InitialHeapSize=6m -\f[R] -.fi -.PP -If you set this option to 0, then the initial size is set as the sum of -the sizes allocated for the old generation and the young generation. -The size of the heap for the young generation can be set using the -\f[V]-XX:NewSize\f[R] option. -Note that the \f[V]-Xms\f[R] option sets both the minimum and the -initial heap size of the heap. -If \f[V]-Xms\f[R] appears after \f[V]-XX:InitialHeapSize\f[R] on the -command line, then the initial heap size gets set to the value specified -with \f[V]-Xms\f[R]. -.RE -.TP -\f[V]-XX:InitialRAMPercentage=\f[R]\f[I]percent\f[R] -Sets the initial amount of memory that the JVM will use for the Java -heap before applying ergonomics heuristics as a percentage of the -maximum amount determined as described in the \f[V]-XX:MaxRAM\f[R] -option. -The default value is 1.5625 percent. -.RS -.PP -The following example shows how to set the percentage of the initial -amount of memory used for the Java heap: -.RS -.PP -\f[V]-XX:InitialRAMPercentage=5\f[R] -.RE -.RE -.TP -\f[V]-XX:InitialSurvivorRatio=\f[R]\f[I]ratio\f[R] -Sets the initial survivor space ratio used by the throughput garbage -collector (which is enabled by the \f[V]-XX:+UseParallelGC\f[R] option). -Adaptive sizing is enabled by default with the throughput garbage -collector by using the \f[V]-XX:+UseParallelGC\f[R] option, and the -survivor space is resized according to the application behavior, -starting with the initial value. -If adaptive sizing is disabled (using the -\f[V]-XX:-UseAdaptiveSizePolicy\f[R] option), then the -\f[V]-XX:SurvivorRatio\f[R] option should be used to set the size of the -survivor space for the entire execution of the application. -.RS -.PP -The following formula can be used to calculate the initial size of -survivor space (S) based on the size of the young generation (Y), and -the initial survivor space ratio (R): -.RS -.PP -\f[V]S=Y/(R+2)\f[R] -.RE -.PP -The 2 in the equation denotes two survivor spaces. -The larger the value specified as the initial survivor space ratio, the -smaller the initial survivor space size. -.PP -By default, the initial survivor space ratio is set to 8. -If the default value for the young generation space size is used (2 MB), -then the initial size of the survivor space is 0.2 MB. -.PP -The following example shows how to set the initial survivor space ratio -to 4: -.RS -.PP -\f[V]-XX:InitialSurvivorRatio=4\f[R] -.RE -.RE -.TP -\f[V]-XX:InitiatingHeapOccupancyPercent=\f[R]\f[I]percent\f[R] -Sets the percentage of the old generation occupancy (0 to 100) at which -to start the first few concurrent marking cycles for the G1 garbage -collector. -.RS -.PP -By default, the initiating value is set to 45%. -A value of 0 implies nonstop concurrent GC cycles from the beginning -until G1 adaptively sets this value. -.PP -See also the \f[V]-XX:G1UseAdaptiveIHOP\f[R] and -\f[V]-XX:G1AdaptiveIHOPNumInitialSamples\f[R] options. -.PP -The following example shows how to set the initiating heap occupancy to -75%: -.RS -.PP -\f[V]-XX:InitiatingHeapOccupancyPercent=75\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxGCPauseMillis=\f[R]\f[I]time\f[R] -Sets a target for the maximum GC pause time (in milliseconds). -This is a soft goal, and the JVM will make its best effort to achieve -it. -The specified value doesn\[aq]t adapt to your heap size. -By default, for G1 the maximum pause time target is 200 milliseconds. -The other generational collectors do not use a pause time goal by -default. -.RS -.PP -The following example shows how to set the maximum target pause time to -500 ms: -.RS -.PP -\f[V]-XX:MaxGCPauseMillis=500\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxHeapSize=\f[R]\f[I]size\f[R] -Sets the maximum size (in byes) of the memory allocation pool. -This value must be a multiple of 1024 and greater than 2 MB. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default value is selected at run time based on the system -configuration. -For server deployments, the options \f[V]-XX:InitialHeapSize\f[R] and -\f[V]-XX:MaxHeapSize\f[R] are often set to the same value. -.RS -.PP -The following examples show how to set the maximum allowed size of -allocated memory to 80 MB using various units: -.IP -.nf -\f[CB] --XX:MaxHeapSize=83886080 --XX:MaxHeapSize=81920k --XX:MaxHeapSize=80m -\f[R] -.fi -.PP -The \f[V]-XX:MaxHeapSize\f[R] option is equivalent to \f[V]-Xmx\f[R]. -.RE -.TP -\f[V]-XX:MaxHeapFreeRatio=\f[R]\f[I]percent\f[R] -Sets the maximum allowed percentage of free heap space (0 to 100) after -a GC event. -If free heap space expands above this value, then the heap is shrunk. -By default, this value is set to 70%. -.RS -.PP -Minimize the Java heap size by lowering the values of the parameters -\f[V]MaxHeapFreeRatio\f[R] (default value is 70%) and -\f[V]MinHeapFreeRatio\f[R] (default value is 40%) with the command-line -options \f[V]-XX:MaxHeapFreeRatio\f[R] and -\f[V]-XX:MinHeapFreeRatio\f[R]. -Lowering \f[V]MaxHeapFreeRatio\f[R] to as low as 10% and -\f[V]MinHeapFreeRatio\f[R] to 5% has successfully reduced the heap size -without too much performance regression; however, results may vary -greatly depending on your application. -Try different values for these parameters until they\[aq]re as low as -possible yet still retain acceptable performance. -.RS -.PP -\f[V]-XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=5\f[R] -.RE -.PP -Customers trying to keep the heap small should also add the option -\f[V]-XX:-ShrinkHeapInSteps\f[R]. -See \f[B]Performance Tuning Examples\f[R] for a description of using -this option to keep the Java heap small by reducing the dynamic -footprint for embedded applications. -.RE -.TP -\f[V]-XX:MaxMetaspaceSize=\f[R]\f[I]size\f[R] -Sets the maximum amount of native memory that can be allocated for class -metadata. -By default, the size isn\[aq]t limited. -The amount of metadata for an application depends on the application -itself, other running applications, and the amount of memory available -on the system. -.RS -.PP -The following example shows how to set the maximum class metadata size -to 256 MB: -.RS -.PP -\f[V]-XX:MaxMetaspaceSize=256m\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxNewSize=\f[R]\f[I]size\f[R] -Sets the maximum size (in bytes) of the heap for the young generation -(nursery). -The default value is set ergonomically. -.TP -\f[V]-XX:MaxRAM=\f[R]\f[I]size\f[R] -Sets the maximum amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics. -The default value is the maximum amount of available memory to the JVM -process or 128 GB, whichever is lower. -.RS -.PP -The maximum amount of available memory to the JVM process is the minimum -of the machine\[aq]s physical memory and any constraints set by the -environment (e.g. -container). -.PP -Specifying this option disables automatic use of compressed oops if the -combined result of this and other options influencing the maximum amount -of memory is larger than the range of memory addressable by compressed -oops. -See \f[V]-XX:UseCompressedOops\f[R] for further information about -compressed oops. -.PP -The following example shows how to set the maximum amount of available -memory for sizing the Java heap to 2 GB: -.RS -.PP -\f[V]-XX:MaxRAM=2G\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxRAMPercentage=\f[R]\f[I]percent\f[R] -Sets the maximum amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics as a percentage of the maximum -amount determined as described in the \f[V]-XX:MaxRAM\f[R] option. -The default value is 25 percent. -.RS -.PP -Specifying this option disables automatic use of compressed oops if the -combined result of this and other options influencing the maximum amount -of memory is larger than the range of memory addressable by compressed -oops. -See \f[V]-XX:UseCompressedOops\f[R] for further information about -compressed oops. -.PP -The following example shows how to set the percentage of the maximum -amount of memory used for the Java heap: -.RS -.PP -\f[V]-XX:MaxRAMPercentage=75\f[R] -.RE -.RE -.TP -\f[V]-XX:MinRAMPercentage=\f[R]\f[I]percent\f[R] -Sets the maximum amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics as a percentage of the maximum -amount determined as described in the \f[V]-XX:MaxRAM\f[R] option for -small heaps. -A small heap is a heap of approximately 125 MB. -The default value is 50 percent. -.RS -.PP -The following example shows how to set the percentage of the maximum -amount of memory used for the Java heap for small heaps: -.RS -.PP -\f[V]-XX:MinRAMPercentage=75\f[R] -.RE -.RE -.TP -\f[V]-XX:MaxTenuringThreshold=\f[R]\f[I]threshold\f[R] -Sets the maximum tenuring threshold for use in adaptive GC sizing. -The largest value is 15. -The default value is 15 for the parallel (throughput) collector. -.RS -.PP -The following example shows how to set the maximum tenuring threshold to -10: -.RS -.PP -\f[V]-XX:MaxTenuringThreshold=10\f[R] -.RE -.RE -.TP -\f[V]-XX:MetaspaceSize=\f[R]\f[I]size\f[R] -Sets the size of the allocated class metadata space that triggers a -garbage collection the first time it\[aq]s exceeded. -This threshold for a garbage collection is increased or decreased -depending on the amount of metadata used. -The default size depends on the platform. -.TP -\f[V]-XX:MinHeapFreeRatio=\f[R]\f[I]percent\f[R] -Sets the minimum allowed percentage of free heap space (0 to 100) after -a GC event. -If free heap space falls below this value, then the heap is expanded. -By default, this value is set to 40%. -.RS -.PP -Minimize Java heap size by lowering the values of the parameters -\f[V]MaxHeapFreeRatio\f[R] (default value is 70%) and -\f[V]MinHeapFreeRatio\f[R] (default value is 40%) with the command-line -options \f[V]-XX:MaxHeapFreeRatio\f[R] and -\f[V]-XX:MinHeapFreeRatio\f[R]. -Lowering \f[V]MaxHeapFreeRatio\f[R] to as low as 10% and -\f[V]MinHeapFreeRatio\f[R] to 5% has successfully reduced the heap size -without too much performance regression; however, results may vary -greatly depending on your application. -Try different values for these parameters until they\[aq]re as low as -possible, yet still retain acceptable performance. -.RS -.PP -\f[V]-XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=5\f[R] -.RE -.PP -Customers trying to keep the heap small should also add the option -\f[V]-XX:-ShrinkHeapInSteps\f[R]. -See \f[B]Performance Tuning Examples\f[R] for a description of using -this option to keep the Java heap small by reducing the dynamic -footprint for embedded applications. -.RE -.TP -\f[V]-XX:MinHeapSize=\f[R]\f[I]size\f[R] -Sets the minimum size (in bytes) of the memory allocation pool. -This value must be either 0, or a multiple of 1024 and greater than 1 -MB. -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -The default value is selected at run time based on the system -configuration. -.RS -.PP -The following examples show how to set the minimum size of allocated -memory to 6 MB using various units: -.IP -.nf -\f[CB] --XX:MinHeapSize=6291456 --XX:MinHeapSize=6144k --XX:MinHeapSize=6m -\f[R] -.fi -.PP -If you set this option to 0, then the minimum size is set to the same -value as the initial size. -.RE -.TP -\f[V]-XX:NewRatio=\f[R]\f[I]ratio\f[R] -Sets the ratio between young and old generation sizes. -By default, this option is set to 2. -The following example shows how to set the young-to-old ratio to 1: -.RS -.RS -.PP -\f[V]-XX:NewRatio=1\f[R] -.RE -.RE -.TP -\f[V]-XX:NewSize=\f[R]\f[I]size\f[R] -Sets the initial size (in bytes) of the heap for the young generation -(nursery). -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -.RS -.PP -The young generation region of the heap is used for new objects. -GC is performed in this region more often than in other regions. -If the size for the young generation is too low, then a large number of -minor GCs are performed. -If the size is too high, then only full GCs are performed, which can -take a long time to complete. -It is recommended that you keep the size for the young generation -greater than 25% and less than 50% of the overall heap size. -.PP -The following examples show how to set the initial size of the young -generation to 256 MB using various units: -.IP -.nf -\f[CB] --XX:NewSize=256m --XX:NewSize=262144k --XX:NewSize=268435456 -\f[R] -.fi -.PP -The \f[V]-XX:NewSize\f[R] option is equivalent to \f[V]-Xmn\f[R]. -.RE -.TP -\f[V]-XX:ParallelGCThreads=\f[R]\f[I]threads\f[R] -Sets the number of the stop-the-world (STW) worker threads. -The default value depends on the number of CPUs available to the JVM and -the garbage collector selected. -.RS -.PP -For example, to set the number of threads for G1 GC to 2, specify the -following option: -.RS -.PP -\f[V]-XX:ParallelGCThreads=2\f[R] -.RE -.RE -.TP -\f[V]-XX:+ParallelRefProcEnabled\f[R] -Enables parallel reference processing. -By default, this option is disabled. -.TP -\f[V]-XX:+PrintAdaptiveSizePolicy\f[R] -Enables printing of information about adaptive-generation sizing. -By default, this option is disabled. -.TP -\f[V]-XX:SoftRefLRUPolicyMSPerMB=\f[R]\f[I]time\f[R] -Sets the amount of time (in milliseconds) a softly reachable object is -kept active on the heap after the last time it was referenced. -The default value is one second of lifetime per free megabyte in the -heap. -The \f[V]-XX:SoftRefLRUPolicyMSPerMB\f[R] option accepts integer values -representing milliseconds per one megabyte of the current heap size (for -Java HotSpot Client VM) or the maximum possible heap size (for Java -HotSpot Server VM). -This difference means that the Client VM tends to flush soft references -rather than grow the heap, whereas the Server VM tends to grow the heap -rather than flush soft references. -In the latter case, the value of the \f[V]-Xmx\f[R] option has a -significant effect on how quickly soft references are garbage collected. -.RS -.PP -The following example shows how to set the value to 2.5 seconds: -.PP -\f[V]-XX:SoftRefLRUPolicyMSPerMB=2500\f[R] -.RE -.TP -\f[V]-XX:-ShrinkHeapInSteps\f[R] -Incrementally reduces the Java heap to the target size, specified by the -option \f[V]-XX:MaxHeapFreeRatio\f[R]. -This option is enabled by default. -If disabled, then it immediately reduces the Java heap to the target -size instead of requiring multiple garbage collection cycles. -Disable this option if you want to minimize the Java heap size. -You will likely encounter performance degradation when this option is -disabled. -.RS -.PP -See \f[B]Performance Tuning Examples\f[R] for a description of using the -\f[V]MaxHeapFreeRatio\f[R] option to keep the Java heap small by -reducing the dynamic footprint for embedded applications. -.RE -.TP -\f[V]-XX:StringDeduplicationAgeThreshold=\f[R]\f[I]threshold\f[R] -Identifies \f[V]String\f[R] objects reaching the specified age that are -considered candidates for deduplication. -An object\[aq]s age is a measure of how many times it has survived -garbage collection. -This is sometimes referred to as tenuring. -.RS -.RS -.PP -\f[B]Note:\f[R] \f[V]String\f[R] objects that are promoted to an old -heap region before this age has been reached are always considered -candidates for deduplication. -The default value for this option is \f[V]3\f[R]. -See the \f[V]-XX:+UseStringDeduplication\f[R] option. -.RE -.RE -.TP -\f[V]-XX:SurvivorRatio=\f[R]\f[I]ratio\f[R] -Sets the ratio between eden space size and survivor space size. -By default, this option is set to 8. -The following example shows how to set the eden/survivor space ratio to -4: -.RS -.RS -.PP -\f[V]-XX:SurvivorRatio=4\f[R] -.RE -.RE -.TP -\f[V]-XX:TargetSurvivorRatio=\f[R]\f[I]percent\f[R] -Sets the desired percentage of survivor space (0 to 100) used after -young garbage collection. -By default, this option is set to 50%. -.RS -.PP -The following example shows how to set the target survivor space ratio -to 30%: -.RS -.PP -\f[V]-XX:TargetSurvivorRatio=30\f[R] -.RE -.RE -.TP -\f[V]-XX:TLABSize=\f[R]\f[I]size\f[R] -Sets the initial size (in bytes) of a thread-local allocation buffer -(TLAB). -Append the letter \f[V]k\f[R] or \f[V]K\f[R] to indicate kilobytes, -\f[V]m\f[R] or \f[V]M\f[R] to indicate megabytes, or \f[V]g\f[R] or -\f[V]G\f[R] to indicate gigabytes. -If this option is set to 0, then the JVM selects the initial size -automatically. -.RS -.PP -The following example shows how to set the initial TLAB size to 512 KB: -.RS -.PP -\f[V]-XX:TLABSize=512k\f[R] -.RE -.RE -.TP -\f[V]-XX:+UseAdaptiveSizePolicy\f[R] -Enables the use of adaptive generation sizing. -This option is enabled by default. -To disable adaptive generation sizing, specify -\f[V]-XX:-UseAdaptiveSizePolicy\f[R] and set the size of the memory -allocation pool explicitly. -See the \f[V]-XX:SurvivorRatio\f[R] option. -.TP -\f[V]-XX:+UseG1GC\f[R] -Enables the use of the garbage-first (G1) garbage collector. -It\[aq]s a server-style garbage collector, targeted for multiprocessor -machines with a large amount of RAM. -This option meets GC pause time goals with high probability, while -maintaining good throughput. -The G1 collector is recommended for applications requiring large heaps -(sizes of around 6 GB or larger) with limited GC latency requirements (a -stable and predictable pause time below 0.5 seconds). -By default, this option is enabled and G1 is used as the default garbage -collector. -.TP -\f[V]-XX:+UseGCOverheadLimit\f[R] -Enables the use of a policy that limits the proportion of time spent by -the JVM on GC before an \f[V]OutOfMemoryError\f[R] exception is thrown. -This option is enabled, by default, and the parallel GC will throw an -\f[V]OutOfMemoryError\f[R] if more than 98% of the total time is spent -on garbage collection and less than 2% of the heap is recovered. -When the heap is small, this feature can be used to prevent applications -from running for long periods of time with little or no progress. -To disable this option, specify the option -\f[V]-XX:-UseGCOverheadLimit\f[R]. -.TP -\f[V]-XX:+UseNUMA\f[R] -Enables performance optimization of an application on a machine with -nonuniform memory architecture (NUMA) by increasing the -application\[aq]s use of lower latency memory. -By default, this option is disabled and no optimization for NUMA is -made. -The option is available only when the parallel garbage collector is used -(\f[V]-XX:+UseParallelGC\f[R]). -.TP -\f[V]-XX:+UseParallelGC\f[R] -Enables the use of the parallel scavenge garbage collector (also known -as the throughput collector) to improve the performance of your -application by leveraging multiple processors. -.RS -.PP -By default, this option is disabled and the default collector is used. -.RE -.TP -\f[V]-XX:+UseSerialGC\f[R] -Enables the use of the serial garbage collector. -This is generally the best choice for small and simple applications that -don\[aq]t require any special functionality from garbage collection. -By default, this option is disabled and the default collector is used. -.TP -\f[V]-XX:+UseStringDeduplication\f[R] -Enables string deduplication. -By default, this option is disabled. -To use this option, you must enable the garbage-first (G1) garbage -collector. -.RS -.PP -String deduplication reduces the memory footprint of \f[V]String\f[R] -objects on the Java heap by taking advantage of the fact that many -\f[V]String\f[R] objects are identical. -Instead of each \f[V]String\f[R] object pointing to its own character -array, identical \f[V]String\f[R] objects can point to and share the -same character array. -.RE -.TP -\f[V]-XX:+UseTLAB\f[R] -Enables the use of thread-local allocation blocks (TLABs) in the young -generation space. -This option is enabled by default. -To disable the use of TLABs, specify the option \f[V]-XX:-UseTLAB\f[R]. -.TP -\f[V]-XX:+UseZGC\f[R] -Enables the use of the Z garbage collector (ZGC). -This is a low latency garbage collector, providing max pause times of a -few milliseconds, at some throughput cost. -Pause times are independent of what heap size is used. -Supports heap sizes from 8MB to 16TB. -.TP -\f[V]-XX:ZAllocationSpikeTolerance=\f[R]\f[I]factor\f[R] -Sets the allocation spike tolerance for ZGC. -By default, this option is set to 2.0. -This factor describes the level of allocation spikes to expect. -For example, using a factor of 3.0 means the current allocation rate can -be expected to triple at any time. -.TP -\f[V]-XX:ZCollectionInterval=\f[R]\f[I]seconds\f[R] -Sets the maximum interval (in seconds) between two GC cycles when using -ZGC. -By default, this option is set to 0 (disabled). -.TP -\f[V]-XX:ZFragmentationLimit=\f[R]\f[I]percent\f[R] -Sets the maximum acceptable heap fragmentation (in percent) for ZGC. -By default, this option is set to 25. -Using a lower value will cause the heap to be compacted more -aggressively, to reclaim more memory at the cost of using more CPU time. -.TP -\f[V]-XX:+ZProactive\f[R] -Enables proactive GC cycles when using ZGC. -By default, this option is enabled. -ZGC will start a proactive GC cycle if doing so is expected to have -minimal impact on the running application. -This is useful if the application is mostly idle or allocates very few -objects, but you still want to keep the heap size down and allow -reference processing to happen even when there are a lot of free space -on the heap. -.TP -\f[V]-XX:+ZUncommit\f[R] -Enables uncommitting of unused heap memory when using ZGC. -By default, this option is enabled. -Uncommitting unused heap memory will lower the memory footprint of the -JVM, and make that memory available for other processes to use. -.TP -\f[V]-XX:ZUncommitDelay=\f[R]\f[I]seconds\f[R] -Sets the amount of time (in seconds) that heap memory must have been -unused before being uncommitted. -By default, this option is set to 300 (5 minutes). -Committing and uncommitting memory are relatively expensive operations. -Using a lower value will cause heap memory to be uncommitted earlier, at -the risk of soon having to commit it again. -.SH DEPRECATED JAVA OPTIONS -.PP -These \f[V]java\f[R] options are deprecated and might be removed in a -future JDK release. -They\[aq]re still accepted and acted upon, but a warning is issued when -they\[aq]re used. -.TP -\f[V]-Xloggc:\f[R]\f[I]filename\f[R] -Sets the file to which verbose GC events information should be -redirected for logging. -The \f[V]-Xloggc\f[R] option overrides \f[V]-verbose:gc\f[R] if both are -given with the same java command. -\f[V]-Xloggc:\f[R]\f[I]filename\f[R] is replaced by -\f[V]-Xlog:gc:\f[R]\f[I]filename\f[R]. -See Enable Logging with the JVM Unified Logging Framework. -.RS -.PP -Example: -.PP -\f[V]-Xlog:gc:garbage-collection.log\f[R] -.RE -.TP -\f[V]-XX:+FlightRecorder\f[R] -Enables the use of Java Flight Recorder (JFR) during the runtime of the -application. -Since JDK 8u40 this option has not been required to use JFR. -.SH OBSOLETE JAVA OPTIONS -.PP -These \f[V]java\f[R] options are still accepted but ignored, and a -warning is issued when they\[aq]re used. -.TP -\f[V]--illegal-access=\f[R]\f[I]parameter\f[R] -Controlled \f[I]relaxed strong encapsulation\f[R], as defined in -\f[B]JEP 261\f[R] -[https://openjdk.org/jeps/261#Relaxed-strong-encapsulation]. -This option was deprecated in JDK 16 by \f[B]JEP 396\f[R] -[https://openjdk.org/jeps/396] and made obsolete in JDK 17 by \f[B]JEP -403\f[R] [https://openjdk.org/jeps/403]. -.TP -\f[V]-XX:RTMAbortRatio=\f[R]\f[I]abort_ratio\f[R] -Specifies the RTM abort ratio is specified as a percentage (%) of all -executed RTM transactions. -If a number of aborted transactions becomes greater than this ratio, -then the compiled code is deoptimized. -This ratio is used when the \f[V]-XX:+UseRTMDeopt\f[R] option is -enabled. -The default value of this option is 50. -This means that the compiled code is deoptimized if 50% of all -transactions are aborted. -.TP -\f[V]-XX:RTMRetryCount=\f[R]\f[I]number_of_retries\f[R] -Specifies the number of times that the RTM locking code is retried, when -it is aborted or busy, before falling back to the normal locking -mechanism. -The default value for this option is 5. -The \f[V]-XX:UseRTMLocking\f[R] option must be enabled. -.TP -\f[V]-XX:+UseRTMDeopt\f[R] -Autotunes RTM locking depending on the abort ratio. -This ratio is specified by the \f[V]-XX:RTMAbortRatio\f[R] option. -If the number of aborted transactions exceeds the abort ratio, then the -method containing the lock is deoptimized and recompiled with all locks -as normal locks. -This option is disabled by default. -The \f[V]-XX:+UseRTMLocking\f[R] option must be enabled. -.TP -\f[V]-XX:+UseRTMLocking\f[R] -Generates Restricted Transactional Memory (RTM) locking code for all -inflated locks, with the normal locking mechanism as the fallback -handler. -This option is disabled by default. -Options related to RTM are available only on x86 CPUs that support -Transactional Synchronization Extensions (TSX). -.RS -.PP -RTM is part of Intel\[aq]s TSX, which is an x86 instruction set -extension and facilitates the creation of multithreaded applications. -RTM introduces the new instructions \f[V]XBEGIN\f[R], \f[V]XABORT\f[R], -\f[V]XEND\f[R], and \f[V]XTEST\f[R]. -The \f[V]XBEGIN\f[R] and \f[V]XEND\f[R] instructions enclose a set of -instructions to run as a transaction. -If no conflict is found when running the transaction, then the memory -and register modifications are committed together at the \f[V]XEND\f[R] -instruction. -The \f[V]XABORT\f[R] instruction can be used to explicitly abort a -transaction and the \f[V]XTEST\f[R] instruction checks if a set of -instructions is being run in a transaction. -.PP -A lock on a transaction is inflated when another thread tries to access -the same transaction, thereby blocking the thread that didn\[aq]t -originally request access to the transaction. -RTM requires that a fallback set of operations be specified in case a -transaction aborts or fails. -An RTM lock is a lock that has been delegated to the TSX\[aq]s system. -.PP -RTM improves performance for highly contended locks with low conflict in -a critical region (which is code that must not be accessed by more than -one thread concurrently). -RTM also improves the performance of coarse-grain locking, which -typically doesn\[aq]t perform well in multithreaded applications. -(Coarse-grain locking is the strategy of holding locks for long periods -to minimize the overhead of taking and releasing locks, while -fine-grained locking is the strategy of trying to achieve maximum -parallelism by locking only when necessary and unlocking as soon as -possible.) -Also, for lightly contended locks that are used by different threads, -RTM can reduce false cache line sharing, also known as cache line -ping-pong. -This occurs when multiple threads from different processors are -accessing different resources, but the resources share the same cache -line. -As a result, the processors repeatedly invalidate the cache lines of -other processors, which forces them to read from main memory instead of -their cache. -.RE -.SH REMOVED JAVA OPTIONS -.PP -These \f[V]java\f[R] options have been removed in JDK 24 and using them -results in an error of: -.RS -.PP -\f[V]Unrecognized VM option\f[R] \f[I]option-name\f[R] -.RE -.TP -\f[V]-XX:InitialRAMFraction=\f[R]\f[I]ratio\f[R] -Sets the initial amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics as a ratio of the maximum amount -determined as described in the \f[V]-XX:MaxRAM\f[R] option. -The default value is 64. -.RS -.PP -Use the option \f[V]-XX:InitialRAMPercentage\f[R] instead. -.RE -.TP -\f[V]-XX:MaxRAMFraction=\f[R]\f[I]ratio\f[R] -Sets the maximum amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics as a fraction of the maximum -amount determined as described in the \f[V]-XX:MaxRAM\f[R] option. -The default value is 4. -.RS -.PP -Specifying this option disables automatic use of compressed oops if the -combined result of this and other options influencing the maximum amount -of memory is larger than the range of memory addressable by compressed -oops. -See \f[V]-XX:UseCompressedOops\f[R] for further information about -compressed oops. -.PP -Use the option \f[V]-XX:MaxRAMPercentage\f[R] instead. -.RE -.TP -\f[V]-XX:MinRAMFraction=\f[R]\f[I]ratio\f[R] -Sets the maximum amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics as a fraction of the maximum -amount determined as described in the \f[V]-XX:MaxRAM\f[R] option for -small heaps. -A small heap is a heap of approximately 125 MB. -The default value is 2. -.RS -.PP -Use the option \f[V]-XX:MinRAMPercentage\f[R] instead. -.RE -.TP -\f[V]-XX:+ScavengeBeforeFullGC\f[R] -Enables GC of the young generation before each full GC. -This option is enabled by default. -It is recommended that you \f[I]don\[aq]t\f[R] disable it, because -scavenging the young generation before a full GC can reduce the number -of objects reachable from the old generation space into the young -generation space. -To disable GC of the young generation before each full GC, specify the -option \f[V]-XX:-ScavengeBeforeFullGC\f[R]. -.TP -\f[V]-Xfuture\f[R] -Enables strict class-file format checks that enforce close conformance -to the class-file format specification. -Developers should use this flag when developing new code. -Stricter checks may become the default in future releases. -.RS -.PP -Use the option \f[V]-Xverify:all\f[R] instead. -.RE -.PP -For the lists and descriptions of options removed in previous releases -see the \f[I]Removed Java Options\f[R] section in: -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 23\f[R] -[https://docs.oracle.com/en/java/javase/23/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 22\f[R] -[https://docs.oracle.com/en/java/javase/22/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 21\f[R] -[https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 20\f[R] -[https://docs.oracle.com/en/java/javase/20/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 19\f[R] -[https://docs.oracle.com/en/java/javase/19/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 18\f[R] -[https://docs.oracle.com/en/java/javase/18/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 17\f[R] -[https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 16\f[R] -[https://docs.oracle.com/en/java/javase/16/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 15\f[R] -[https://docs.oracle.com/en/java/javase/15/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 14\f[R] -[https://docs.oracle.com/en/java/javase/14/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]The \f[VB]java\f[B] Command, Release 13\f[R] -[https://docs.oracle.com/en/java/javase/13/docs/specs/man/java.html] -.IP \[bu] 2 -\f[B]Java Platform, Standard Edition Tools Reference, Release 12\f[R] -[https://docs.oracle.com/en/java/javase/12/tools/java.html#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE] -.IP \[bu] 2 -\f[B]Java Platform, Standard Edition Tools Reference, Release 11\f[R] -[https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-741FC470-AA3E-494A-8D2B-1B1FE4A990D1] -.IP \[bu] 2 -\f[B]Java Platform, Standard Edition Tools Reference, Release 10\f[R] -[https://docs.oracle.com/javase/10/tools/java.htm#JSWOR624] -.IP \[bu] 2 -\f[B]Java Platform, Standard Edition Tools Reference, Release 9\f[R] -[https://docs.oracle.com/javase/9/tools/java.htm#JSWOR624] -.IP \[bu] 2 -\f[B]Java Platform, Standard Edition Tools Reference, Release 8 for -Oracle JDK on Windows\f[R] -[https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html#BGBCIEFC] -.IP \[bu] 2 -\f[B]Java Platform, Standard Edition Tools Reference, Release 8 for -Oracle JDK on Solaris, Linux, and macOS\f[R] -[https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BGBCIEFC] -.SH JAVA COMMAND-LINE ARGUMENT FILES -.PP -You can shorten or simplify the \f[V]java\f[R] command by using -\f[V]\[at]\f[R] argument files to specify one or more text files that -contain arguments, such as options and class names, which are passed to -the \f[V]java\f[R] command. -This let\[aq]s you to create \f[V]java\f[R] commands of any length on -any operating system. -.PP -In the command line, use the at sign (\f[V]\[at]\f[R]) prefix to -identify an argument file that contains \f[V]java\f[R] options and class -names. -When the \f[V]java\f[R] command encounters a file beginning with the at -sign (\f[V]\[at]\f[R]), it expands the contents of that file into an -argument list just as they would be specified on the command line. -.PP -The \f[V]java\f[R] launcher expands the argument file contents until it -encounters the \f[V]--disable-\[at]files\f[R] option. -You can use the \f[V]--disable-\[at]files\f[R] option anywhere on the -command line, including in an argument file, to stop \f[V]\[at]\f[R] -argument files expansion. -.PP -The following items describe the syntax of \f[V]java\f[R] argument -files: -.IP \[bu] 2 -The argument file must contain only ASCII characters or characters in -system default encoding that\[aq]s ASCII friendly, such as UTF-8. -.IP \[bu] 2 -The argument file size must not exceed MAXINT (2,147,483,647) bytes. -.IP \[bu] 2 -The launcher doesn\[aq]t expand wildcards that are present within an -argument file. -.IP \[bu] 2 -Use white space or new line characters to separate arguments included in -the file. -.IP \[bu] 2 -White space includes a white space character, \f[V]\[rs]t\f[R], -\f[V]\[rs]n\f[R], \f[V]\[rs]r\f[R], and \f[V]\[rs]f\f[R]. -.RS 2 -.PP -For example, it is possible to have a path with a space, such as -\f[V]c:\[rs]Program Files\f[R] that can be specified as either -\f[V]\[dq]c:\[rs]\[rs]Program Files\[dq]\f[R] or, to avoid an escape, -\f[V]c:\[rs]Program\[dq] \[dq]Files\f[R]. -.RE -.IP \[bu] 2 -Any option that contains spaces, such as a path component, must be -within quotation marks using quotation (\[aq]\[dq]\[aq]) characters in -its entirety. -.IP \[bu] 2 -A string within quotation marks may contain the characters -\f[V]\[rs]n\f[R], \f[V]\[rs]r\f[R], \f[V]\[rs]t\f[R], and -\f[V]\[rs]f\f[R]. -They are converted to their respective ASCII codes. -.IP \[bu] 2 -If a file name contains embedded spaces, then put the whole file name in -double quotation marks. -.IP \[bu] 2 -File names in an argument file are relative to the current directory, -not to the location of the argument file. -.IP \[bu] 2 -Use the number sign \f[V]#\f[R] in the argument file to identify -comments. -All characters following the \f[V]#\f[R] are ignored until the end of -line. -.IP \[bu] 2 -Additional at sign \f[V]\[at]\f[R] prefixes to \f[V]\[at]\f[R] prefixed -options act as an escape, (the first \f[V]\[at]\f[R] is removed and the -rest of the arguments are presented to the launcher literally). -.IP \[bu] 2 -Lines may be continued using the continuation character -(\f[V]\[rs]\f[R]) at the end-of-line. -The two lines are concatenated with the leading white spaces trimmed. -To prevent trimming the leading white spaces, a continuation character -(\f[V]\[rs]\f[R]) may be placed at the first column. -.IP \[bu] 2 -Because backslash (\[rs]) is an escape character, a backslash character -must be escaped with another backslash character. -.IP \[bu] 2 -Partial quote is allowed and is closed by an end-of-file. -.IP \[bu] 2 -An open quote stops at end-of-line unless \f[V]\[rs]\f[R] is the last -character, which then joins the next line by removing all leading white -space characters. -.IP \[bu] 2 -Wildcards (*) aren\[aq]t allowed in these lists (such as specifying -\f[V]*.java\f[R]). -.IP \[bu] 2 -Use of the at sign (\f[V]\[at]\f[R]) to recursively interpret files -isn\[aq]t supported. -.SS Example of Open or Partial Quotes in an Argument File -.PP -In the argument file, -.IP -.nf -\f[CB] --cp \[dq]lib/ -cool/ -app/ -jars -\f[R] -.fi -.PP -this is interpreted as: -.RS -.PP -\f[V]-cp lib/cool/app/jars\f[R] -.RE -.SS Example of a Backslash Character Escaped with Another Backslash Character in an Argument File -.PP -To output the following: -.RS -.PP -\f[V]-cp c:\[rs]Program Files (x86)\[rs]Java\[rs]jre\[rs]lib\[rs]ext;c:\[rs]Program Files\[rs]Java\[rs]jre9\[rs]lib\[rs]ext\f[R] -.RE -.PP -The backslash character must be specified in the argument file as: -.RS -.PP -\f[V]-cp \[dq]c:\[rs]\[rs]Program Files (x86)\[rs]\[rs]Java\[rs]\[rs]jre\[rs]\[rs]lib\[rs]\[rs]ext;c:\[rs]\[rs]Program Files\[rs]\[rs]Java\[rs]\[rs]jre9\[rs]\[rs]lib\[rs]\[rs]ext\[dq]\f[R] -.RE -.SS Example of an EOL Escape Used to Force Concatenation of Lines in an Argument File -.PP -In the argument file, -.IP -.nf -\f[CB] --cp \[dq]/lib/cool app/jars:\[rs] - /lib/another app/jars\[dq] -\f[R] -.fi -.PP -This is interpreted as: -.RS -.PP -\f[V]-cp /lib/cool app/jars:/lib/another app/jars\f[R] -.RE -.SS Example of Line Continuation with Leading Spaces in an Argument File -.PP -In the argument file, -.IP -.nf -\f[CB] --cp \[dq]/lib/cool\[rs] -\[rs]app/jars\[dq] -\f[R] -.fi -.PP -This is interpreted as: -.PP -\f[V]-cp /lib/cool app/jars\f[R] -.SS Examples of Using Single Argument File -.PP -You can use a single argument file, such as \f[V]myargumentfile\f[R] in -the following example, to hold all required \f[V]java\f[R] arguments: -.RS -.PP -\f[V]java \[at]myargumentfile\f[R] -.RE -.SS Examples of Using Argument Files with Paths -.PP -You can include relative paths in argument files; however, they\[aq]re -relative to the current working directory and not to the paths of the -argument files themselves. -In the following example, \f[V]path1/options\f[R] and -\f[V]path2/options\f[R] represent argument files with different paths. -Any relative paths that they contain are relative to the current working -directory and not to the argument files: -.RS -.PP -\f[V]java \[at]path1/options \[at]path2/classes\f[R] -.RE -.SH CODE HEAP STATE ANALYTICS -.SS Overview -.PP -There are occasions when having insight into the current state of the -JVM code heap would be helpful to answer questions such as: -.IP \[bu] 2 -Why was the JIT turned off and then on again and again? -.IP \[bu] 2 -Where has all the code heap space gone? -.IP \[bu] 2 -Why is the method sweeper not working effectively? -.PP -To provide this insight, a code heap state analytics feature has been -implemented that enables on-the-fly analysis of the code heap. -The analytics process is divided into two parts. -The first part examines the entire code heap and aggregates all -information that is believed to be useful or important. -The second part consists of several independent steps that print the -collected information with an emphasis on different aspects of the data. -Data collection and printing are done on an \[dq]on request\[dq] basis. -.SS Syntax -.PP -Requests for real-time, on-the-fly analysis can be issued with the -following command: -.RS -.PP -\f[V]jcmd\f[R] \f[I]pid\f[R] \f[V]Compiler.CodeHeap_Analytics\f[R] -[\f[I]function\f[R]] [\f[I]granularity\f[R]] -.RE -.PP -If you are only interested in how the code heap looks like after running -a sample workload, you can use the command line option: -.RS -.PP -\f[V]-Xlog:codecache=Trace\f[R] -.RE -.PP -To see the code heap state when a \[dq]CodeCache full\[dq] condition -exists, start the VM with the command line option: -.RS -.PP -\f[V]-Xlog:codecache=Debug\f[R] -.RE -.PP -See \f[B]CodeHeap State Analytics (OpenJDK)\f[R] -[https://bugs.openjdk.org/secure/attachment/75649/JVM_CodeHeap_StateAnalytics_V2.pdf] -for a detailed description of the code heap state analytics feature, the -supported functions, and the granularity options. -.SH ENABLE LOGGING WITH THE JVM UNIFIED LOGGING FRAMEWORK -.PP -You use the \f[V]-Xlog\f[R] option to configure or enable logging with -the Java Virtual Machine (JVM) unified logging framework. -.SS Synopsis -.RS -.PP -\f[V]-Xlog\f[R][\f[V]:\f[R][\f[I]what\f[R]][\f[V]:\f[R][\f[I]output\f[R]][\f[V]:\f[R][\f[I]decorators\f[R]][\f[V]:\f[R]\f[I]output-options\f[R][\f[V],\f[R]...]]]]] -.PP -\f[V]-Xlog:\f[R]\f[I]directive\f[R] -.RE -.TP -\f[I]what\f[R] -Specifies a combination of tags and levels of the form -\f[I]tag1\f[R][\f[V]+\f[R]\f[I]tag2\f[R]...][\f[V]*\f[R]][\f[V]=\f[R]\f[I]level\f[R]][\f[V],\f[R]...]. -Unless the wildcard (\f[V]*\f[R]) is specified, only log messages tagged -with exactly the tags specified are matched. -See \f[B]-Xlog Tags and Levels\f[R]. -.TP -\f[I]output\f[R] -Sets the type of output. -Omitting the \f[I]output\f[R] type defaults to \f[V]stdout\f[R]. -See \f[B]-Xlog Output\f[R]. -.TP -\f[I]decorators\f[R] -Configures the output to use a custom set of decorators. -Omitting \f[I]decorators\f[R] defaults to \f[V]uptime\f[R], -\f[V]level\f[R], and \f[V]tags\f[R]. -See \f[B]Decorations\f[R]. -.TP -\f[I]output-options\f[R] -Sets the \f[V]-Xlog\f[R] logging output options. -.TP -\f[I]directive\f[R] -A global option or subcommand: help, disable, async -.SS Description -.PP -The Java Virtual Machine (JVM) unified logging framework provides a -common logging system for all components of the JVM. -GC logging for the JVM has been changed to use the new logging -framework. -The mapping of old GC flags to the corresponding new Xlog configuration -is described in \f[B]Convert GC Logging Flags to Xlog\f[R]. -In addition, runtime logging has also been changed to use the JVM -unified logging framework. -The mapping of legacy runtime logging flags to the corresponding new -Xlog configuration is described in \f[B]Convert Runtime Logging Flags to -Xlog\f[R]. -.PP -The following provides quick reference to the \f[V]-Xlog\f[R] command -and syntax for options: -.TP -\f[V]-Xlog\f[R] -Enables JVM logging on an \f[V]info\f[R] level. -.TP -\f[V]-Xlog:help\f[R] -Prints \f[V]-Xlog\f[R] usage syntax and available tags, levels, and -decorators along with example command lines with explanations. -.TP -\f[V]-Xlog:disable\f[R] -Turns off all logging and clears all configuration of the logging -framework including the default configuration for warnings and errors. -.TP -\f[V]-Xlog\f[R][\f[V]:\f[R]\f[I]option\f[R]] -Applies multiple arguments in the order that they appear on the command -line. -Multiple \f[V]-Xlog\f[R] arguments for the same output override each -other in their given order. -.RS -.PP -The \f[I]option\f[R] is set as: -.RS -.PP -[\f[I]tag-selection\f[R]][\f[V]:\f[R][\f[I]output\f[R]][\f[V]:\f[R][\f[I]decorators\f[R]][\f[V]:\f[R]\f[I]output-options\f[R]]]] -.RE -.PP -Omitting the \f[I]tag-selection\f[R] defaults to a tag-set of -\f[V]all\f[R] and a level of \f[V]info\f[R]. -.RS -.PP -\f[I]tag\f[R][\f[V]+\f[R]...] -\f[V]all\f[R] -.RE -.PP -The \f[V]all\f[R] tag is a meta tag consisting of all tag-sets -available. -The asterisk \f[V]*\f[R] in a tag set definition denotes a wildcard tag -match. -Matching with a wildcard selects all tag sets that contain \f[I]at -least\f[R] the specified tags. -Without the wildcard, only exact matches of the specified tag sets are -selected. -.PP -\f[I]output-options\f[R] is -.RS -.PP -\f[V]filecount=\f[R]\f[I]file-count\f[R] \f[V]filesize=\f[R]\f[I]file -size with optional K, M or G suffix\f[R] -\f[V]foldmultilines=\f[R]\f[I]\f[R] -.RE -.PP -When \f[V]foldmultilines\f[R] is true, a log event that consists of -multiple lines will be folded into a single line by replacing newline -characters with the sequence \f[V]\[aq]\[rs]\[aq]\f[R] and -\f[V]\[aq]n\[aq]\f[R] in the output. -Existing single backslash characters will also be replaced with a -sequence of two backslashes so that the conversion can be reversed. -This option is safe to use with UTF-8 character encodings, but other -encodings may not work. -For example, it may incorrectly convert multi-byte sequences in Shift -JIS and BIG5. -.RE -.SS Default Configuration -.PP -When the \f[V]-Xlog\f[R] option and nothing else is specified on the -command line, the default configuration is used. -The default configuration logs all messages with a level that matches -either warning or error regardless of what tags the message is -associated with. -The default configuration is equivalent to entering the following on the -command line: -.RS -.PP -\f[V]-Xlog:all=warning:stdout:uptime,level,tags\f[R] -.RE -.SS Controlling Logging at Runtime -.PP -Logging can also be controlled at run time through Diagnostic Commands -(with the \f[B]jcmd\f[R] utility). -Everything that can be specified on the command line can also be -specified dynamically with the \f[V]VM.log\f[R] command. -As the diagnostic commands are automatically exposed as MBeans, you can -use JMX to change logging configuration at run time. -.SS -Xlog Tags and Levels -.PP -Each log message has a level and a tag set associated with it. -The level of the message corresponds to its details, and the tag set -corresponds to what the message contains or which JVM component it -involves (such as, \f[V]gc\f[R], \f[V]jit\f[R], or \f[V]os\f[R]). -Mapping GC flags to the Xlog configuration is described in \f[B]Convert -GC Logging Flags to Xlog\f[R]. -Mapping legacy runtime logging flags to the corresponding Xlog -configuration is described in \f[B]Convert Runtime Logging Flags to -Xlog\f[R]. -.PP -\f[B]Available log levels:\f[R] -.IP \[bu] 2 -\f[V]off\f[R] -.IP \[bu] 2 -\f[V]trace\f[R] -.IP \[bu] 2 -\f[V]debug\f[R] -.IP \[bu] 2 -\f[V]info\f[R] -.IP \[bu] 2 -\f[V]warning\f[R] -.IP \[bu] 2 -\f[V]error\f[R] -.PP -\f[B]Available log tags:\f[R] -.PP -There are literally dozens of log tags, which in the right combinations, -will enable a range of logging output. -The full set of available log tags can be seen using -\f[V]-Xlog:help\f[R]. -Specifying \f[V]all\f[R] instead of a tag combination matches all tag -combinations. -.SS -Xlog Output -.PP -The \f[V]-Xlog\f[R] option supports the following types of outputs: -.IP \[bu] 2 -\f[V]stdout\f[R] --- Sends output to stdout -.IP \[bu] 2 -\f[V]stderr\f[R] --- Sends output to stderr -.IP \[bu] 2 -\f[V]file=\f[R]\f[I]filename\f[R] --- Sends output to text file(s). -.PP -When using \f[V]file=\f[R]\f[I]filename\f[R], specifying \f[V]%p\f[R], -\f[V]%t\f[R] and/or \f[V]%hn\f[R] in the file name expands to the -JVM\[aq]s PID, startup timestamp and host name, respectively. -You can also configure text files to handle file rotation based on file -size and a number of files to rotate. -For example, to rotate the log file every 10 MB and keep 5 files in -rotation, specify the options \f[V]filesize=10M, filecount=5\f[R]. -The target size of the files isn\[aq]t guaranteed to be exact, it\[aq]s -just an approximate value. -Files are rotated by default with up to 5 rotated files of target size -20 MB, unless configured otherwise. -Specifying \f[V]filecount=0\f[R] means that the log file shouldn\[aq]t -be rotated. -There\[aq]s a possibility of the pre-existing log file getting -overwritten. -.SS -Xlog Output Mode -.PP -By default logging messages are output synchronously - each log message -is written to the designated output when the logging call is made. -But you can instead use asynchronous logging mode by specifying: -.TP -\f[V]-Xlog:async\f[R] -Write all logging asynchronously. -.PP -In asynchronous logging mode, log sites enqueue all logging messages to -an intermediate buffer and a standalone thread is responsible for -flushing them to the corresponding outputs. -The intermediate buffer is bounded and on buffer exhaustion the -enqueuing message is discarded. -Log entry write operations are guaranteed non-blocking. -.PP -The option \f[V]-XX:AsyncLogBufferSize=N\f[R] specifies the memory -budget in bytes for the intermediate buffer. -The default value should be big enough to cater for most cases. -Users can provide a custom value to trade memory overhead for log -accuracy if they need to. -.SS Decorations -.PP -Logging messages are decorated with information about the message. -You can configure each output to use a custom set of decorators. -The order of the output is always the same as listed in the table. -You can configure the decorations to be used at run time. -Decorations are prepended to the log message. -For example: -.IP -.nf -\f[CB] -[6.567s][info][gc,old] Old collection complete -\f[R] -.fi -.PP -Omitting \f[V]decorators\f[R] defaults to \f[V]uptime\f[R], -\f[V]level\f[R], and \f[V]tags\f[R]. -The \f[V]none\f[R] decorator is special and is used to turn off all -decorations. -.PP -\f[V]time\f[R] (\f[V]t\f[R]), \f[V]utctime\f[R] (\f[V]utc\f[R]), -\f[V]uptime\f[R] (\f[V]u\f[R]), \f[V]timemillis\f[R] (\f[V]tm\f[R]), -\f[V]uptimemillis\f[R] (\f[V]um\f[R]), \f[V]timenanos\f[R] -(\f[V]tn\f[R]), \f[V]uptimenanos\f[R] (\f[V]un\f[R]), \f[V]hostname\f[R] -(\f[V]hn\f[R]), \f[V]pid\f[R] (\f[V]p\f[R]), \f[V]tid\f[R] -(\f[V]ti\f[R]), \f[V]level\f[R] (\f[V]l\f[R]), \f[V]tags\f[R] -(\f[V]tg\f[R]) decorators can also be specified as \f[V]none\f[R] for no -decoration. -.PP -Logging Messages Decorations -.TS -tab(@); -lw(14.9n) lw(55.1n). -T{ -Decorations -T}@T{ -Description -T} -_ -T{ -\f[V]time\f[R] or \f[V]t\f[R] -T}@T{ -Current time and date in ISO-8601 format. -T} -T{ -\f[V]utctime\f[R] or \f[V]utc\f[R] -T}@T{ -Universal Time Coordinated or Coordinated Universal Time. -T} -T{ -\f[V]uptime\f[R] or \f[V]u\f[R] -T}@T{ -Time since the start of the JVM in seconds and milliseconds. -For example, 6.567s. -T} -T{ -\f[V]timemillis\f[R] or \f[V]tm\f[R] -T}@T{ -The same value as generated by \f[V]System.currentTimeMillis()\f[R] -T} -T{ -\f[V]uptimemillis\f[R] or \f[V]um\f[R] -T}@T{ -Milliseconds since the JVM started. -T} -T{ -\f[V]timenanos\f[R] or \f[V]tn\f[R] -T}@T{ -The same value generated by \f[V]System.nanoTime()\f[R]. -T} -T{ -\f[V]uptimenanos\f[R] or \f[V]un\f[R] -T}@T{ -Nanoseconds since the JVM started. -T} -T{ -\f[V]hostname\f[R] or \f[V]hn\f[R] -T}@T{ -The host name. -T} -T{ -\f[V]pid\f[R] or \f[V]p\f[R] -T}@T{ -The process identifier. -T} -T{ -\f[V]tid\f[R] or \f[V]ti\f[R] -T}@T{ -The thread identifier. -T} -T{ -\f[V]level\f[R] or \f[V]l\f[R] -T}@T{ -The level associated with the log message. -T} -T{ -\f[V]tags\f[R] or \f[V]tg\f[R] -T}@T{ -The tag-set associated with the log message. -T} -.TE -.SS Convert GC Logging Flags to Xlog -.PP -Legacy GC Logging Flags to Xlog Configuration Mapping -.TS -tab(@); -lw(22.4n) lw(16.5n) lw(31.2n). -T{ -Legacy Garbage Collection (GC) Flag -T}@T{ -Xlog Configuration -T}@T{ -Comment -T} -_ -T{ -\f[V]G1PrintHeapRegions\f[R] -T}@T{ -\f[V]-Xlog:gc+region=trace\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]GCLogFileSize\f[R] -T}@T{ -No configuration available -T}@T{ -Log rotation is handled by the framework. -T} -T{ -\f[V]NumberOfGCLogFiles\f[R] -T}@T{ -Not Applicable -T}@T{ -Log rotation is handled by the framework. -T} -T{ -\f[V]PrintAdaptiveSizePolicy\f[R] -T}@T{ -\f[V]-Xlog:gc+ergo*=\f[R]\f[I]level\f[R] -T}@T{ -Use a \f[I]level\f[R] of \f[V]debug\f[R] for most of the information, or -a \f[I]level\f[R] of \f[V]trace\f[R] for all of what was logged for -\f[V]PrintAdaptiveSizePolicy\f[R]. -T} -T{ -\f[V]PrintGC\f[R] -T}@T{ -\f[V]-Xlog:gc\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]PrintGCApplicationConcurrentTime\f[R] -T}@T{ -\f[V]-Xlog:safepoint\f[R] -T}@T{ -Note that \f[V]PrintGCApplicationConcurrentTime\f[R] and -\f[V]PrintGCApplicationStoppedTime\f[R] are logged on the same tag and -aren\[aq]t separated in the new logging. -T} -T{ -\f[V]PrintGCApplicationStoppedTime\f[R] -T}@T{ -\f[V]-Xlog:safepoint\f[R] -T}@T{ -Note that \f[V]PrintGCApplicationConcurrentTime\f[R] and -\f[V]PrintGCApplicationStoppedTime\f[R] are logged on the same tag and -not separated in the new logging. -T} -T{ -\f[V]PrintGCCause\f[R] -T}@T{ -Not Applicable -T}@T{ -GC cause is now always logged. -T} -T{ -\f[V]PrintGCDateStamps\f[R] -T}@T{ -Not Applicable -T}@T{ -Date stamps are logged by the framework. -T} -T{ -\f[V]PrintGCDetails\f[R] -T}@T{ -\f[V]-Xlog:gc*\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]PrintGCID\f[R] -T}@T{ -Not Applicable -T}@T{ -GC ID is now always logged. -T} -T{ -\f[V]PrintGCTaskTimeStamps\f[R] -T}@T{ -\f[V]-Xlog:gc+task*=debug\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]PrintGCTimeStamps\f[R] -T}@T{ -Not Applicable -T}@T{ -Time stamps are logged by the framework. -T} -T{ -\f[V]PrintHeapAtGC\f[R] -T}@T{ -\f[V]-Xlog:gc+heap=trace\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]PrintReferenceGC\f[R] -T}@T{ -\f[V]-Xlog:gc+ref*=debug\f[R] -T}@T{ -Note that in the old logging, \f[V]PrintReferenceGC\f[R] had an effect -only if \f[V]PrintGCDetails\f[R] was also enabled. -T} -T{ -\f[V]PrintStringDeduplicationStatistics\f[R] -T}@T{ -\[ga]-Xlog:gc+stringdedup*=debug -T}@T{ -\[ga] Not Applicable -T} -T{ -\f[V]PrintTenuringDistribution\f[R] -T}@T{ -\f[V]-Xlog:gc+age*=\f[R]\f[I]level\f[R] -T}@T{ -Use a \f[I]level\f[R] of \f[V]debug\f[R] for the most relevant -information, or a \f[I]level\f[R] of \f[V]trace\f[R] for all of what was -logged for \f[V]PrintTenuringDistribution\f[R]. -T} -T{ -\f[V]UseGCLogFileRotation\f[R] -T}@T{ -Not Applicable -T}@T{ -What was logged for \f[V]PrintTenuringDistribution\f[R]. -T} -.TE -.SS Convert Runtime Logging Flags to Xlog -.PP -These legacy flags are no longer recognized and will cause an error if -used directly. -Use their unified logging equivalent instead. -.PP -Runtime Logging Flags to Xlog Configuration Mapping -.TS -tab(@); -lw(15.0n) lw(20.2n) lw(34.7n). -T{ -Legacy Runtime Flag -T}@T{ -Xlog Configuration -T}@T{ -Comment -T} -_ -T{ -\f[V]TraceExceptions\f[R] -T}@T{ -\f[V]-Xlog:exceptions=info\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceClassLoading\f[R] -T}@T{ -\f[V]-Xlog:class+load=\f[R]\f[I]level\f[R] -T}@T{ -Use \f[I]level\f[R]=\f[V]info\f[R] for regular information, or -\f[I]level\f[R]=\f[V]debug\f[R] for additional information. -In Unified Logging syntax, \f[V]-verbose:class\f[R] equals -\f[V]-Xlog:class+load=info,class+unload=info\f[R]. -T} -T{ -\f[V]TraceClassLoadingPreorder\f[R] -T}@T{ -\f[V]-Xlog:class+preorder=debug\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceClassUnloading\f[R] -T}@T{ -\f[V]-Xlog:class+unload=\f[R]\f[I]level\f[R] -T}@T{ -Use \f[I]level\f[R]=\f[V]info\f[R] for regular information, or -\f[I]level\f[R]=\f[V]trace\f[R] for additional information. -In Unified Logging syntax, \f[V]-verbose:class\f[R] equals -\f[V]-Xlog:class+load=info,class+unload=info\f[R]. -T} -T{ -\f[V]VerboseVerification\f[R] -T}@T{ -\f[V]-Xlog:verification=info\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceClassPaths\f[R] -T}@T{ -\f[V]-Xlog:class+path=info\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceClassResolution\f[R] -T}@T{ -\f[V]-Xlog:class+resolve=debug\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceClassInitialization\f[R] -T}@T{ -\f[V]-Xlog:class+init=info\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceLoaderConstraints\f[R] -T}@T{ -\f[V]-Xlog:class+loader+constraints=info\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceClassLoaderData\f[R] -T}@T{ -\f[V]-Xlog:class+loader+data=\f[R]\f[I]level\f[R] -T}@T{ -Use \f[I]level\f[R]=\f[V]debug\f[R] for regular information or -\f[I]level\f[R]=\f[V]trace\f[R] for additional information. -T} -T{ -\f[V]TraceSafepointCleanupTime\f[R] -T}@T{ -\f[V]-Xlog:safepoint+cleanup=info\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceSafepoint\f[R] -T}@T{ -\f[V]-Xlog:safepoint=debug\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceMonitorInflation\f[R] -T}@T{ -\f[V]-Xlog:monitorinflation=debug\f[R] -T}@T{ -Not Applicable -T} -T{ -\f[V]TraceRedefineClasses\f[R] -T}@T{ -\f[V]-Xlog:redefine+class*=\f[R]\f[I]level\f[R] -T}@T{ -\f[I]level\f[R]=\f[V]info\f[R], \f[V]debug\f[R], and \f[V]trace\f[R] -provide increasing amounts of information. -T} -.TE -.SS -Xlog Usage Examples -.PP -The following are \f[V]-Xlog\f[R] examples. -.TP -\f[V]-Xlog\f[R] -Logs all messages by using the \f[V]info\f[R] level to \f[V]stdout\f[R] -with \f[V]uptime\f[R], \f[V]levels\f[R], and \f[V]tags\f[R] decorations. -This is equivalent to using: -.RS -.RS -.PP -\f[V]-Xlog:all=info:stdout:uptime,levels,tags\f[R] -.RE -.RE -.TP -\f[V]-Xlog:gc\f[R] -Logs messages tagged with the \f[V]gc\f[R] tag using \f[V]info\f[R] -level to \f[V]stdout\f[R]. -The default configuration for all other messages at level -\f[V]warning\f[R] is in effect. -.TP -\f[V]-Xlog:gc,safepoint\f[R] -Logs messages tagged either with the \f[V]gc\f[R] or \f[V]safepoint\f[R] -tags, both using the \f[V]info\f[R] level, to \f[V]stdout\f[R], with -default decorations. -Messages tagged with both \f[V]gc\f[R] and \f[V]safepoint\f[R] won\[aq]t -be logged. -.TP -\f[V]-Xlog:gc+ref=debug\f[R] -Logs messages tagged with both \f[V]gc\f[R] and \f[V]ref\f[R] tags, -using the \f[V]debug\f[R] level to \f[V]stdout\f[R], with default -decorations. -Messages tagged only with one of the two tags won\[aq]t be logged. -.TP -\f[V]-Xlog:gc=debug:file=gc.txt:none\f[R] -Logs messages tagged with the \f[V]gc\f[R] tag using the \f[V]debug\f[R] -level to a file called \f[V]gc.txt\f[R] with no decorations. -The default configuration for all other messages at level -\f[V]warning\f[R] is still in effect. -.TP -\f[V]-Xlog:gc=trace:file=gctrace.txt:uptimemillis,pid:filecount=5,filesize=1024\f[R] -Logs messages tagged with the \f[V]gc\f[R] tag using the \f[V]trace\f[R] -level to a rotating file set with 5 files with size 1 MB with the base -name \f[V]gctrace.txt\f[R] and uses decorations \f[V]uptimemillis\f[R] -and \f[V]pid\f[R]. -.RS -.PP -The default configuration for all other messages at level -\f[V]warning\f[R] is still in effect. -.RE -.TP -\f[V]-Xlog:gc::uptime,tid\f[R] -Logs messages tagged with the \f[V]gc\f[R] tag using the default -\[aq]info\[aq] level to default the output \f[V]stdout\f[R] and uses -decorations \f[V]uptime\f[R] and \f[V]tid\f[R]. -The default configuration for all other messages at level -\f[V]warning\f[R] is still in effect. -.TP -\f[V]-Xlog:gc*=info,safepoint*=off\f[R] -Logs messages tagged with at least \f[V]gc\f[R] using the \f[V]info\f[R] -level, but turns off logging of messages tagged with -\f[V]safepoint\f[R]. -Messages tagged with both \f[V]gc\f[R] and \f[V]safepoint\f[R] won\[aq]t -be logged. -.TP -\f[V]-Xlog:disable -Xlog:safepoint=trace:safepointtrace.txt\f[R] -Turns off all logging, including warnings and errors, and then enables -messages tagged with \f[V]safepoint\f[R]using \f[V]trace\f[R]level to -the file \f[V]safepointtrace.txt\f[R]. -The default configuration doesn\[aq]t apply, because the command line -started with \f[V]-Xlog:disable\f[R]. -.SS Complex -Xlog Usage Examples -.PP -The following describes a few complex examples of using the -\f[V]-Xlog\f[R] option. -.TP -\f[V]-Xlog:gc+class*=debug\f[R] -Logs messages tagged with at least \f[V]gc\f[R] and \f[V]class\f[R] tags -using the \f[V]debug\f[R] level to \f[V]stdout\f[R]. -The default configuration for all other messages at the level -\f[V]warning\f[R] is still in effect -.TP -\f[V]-Xlog:gc+meta*=trace,class*=off:file=gcmetatrace.txt\f[R] -Logs messages tagged with at least the \f[V]gc\f[R] and \f[V]meta\f[R] -tags using the \f[V]trace\f[R] level to the file \f[V]metatrace.txt\f[R] -but turns off all messages tagged with \f[V]class\f[R]. -Messages tagged with \f[V]gc\f[R], \f[V]meta\f[R], and \f[V]class\f[R] -aren\[aq]t be logged as \f[V]class*\f[R] is set to off. -The default configuration for all other messages at level -\f[V]warning\f[R] is in effect except for those that include -\f[V]class\f[R]. -.TP -\f[V]-Xlog:gc+meta=trace\f[R] -Logs messages tagged with exactly the \f[V]gc\f[R] and \f[V]meta\f[R] -tags using the \f[V]trace\f[R] level to \f[V]stdout\f[R]. -The default configuration for all other messages at level -\f[V]warning\f[R] is still be in effect. -.TP -\f[V]-Xlog:gc+class+heap*=debug,meta*=warning,threads*=off\f[R] -Logs messages tagged with at least \f[V]gc\f[R], \f[V]class\f[R], and -\f[V]heap\f[R] tags using the \f[V]trace\f[R] level to \f[V]stdout\f[R] -but only log messages tagged with \f[V]meta\f[R] with level. -The default configuration for all other messages at the level -\f[V]warning\f[R] is in effect except for those that include -\f[V]threads\f[R]. -.SH VALIDATE JAVA VIRTUAL MACHINE FLAG ARGUMENTS -.PP -You use values provided to all Java Virtual Machine (JVM) command-line -flags for validation and, if the input value is invalid or out-of-range, -then an appropriate error message is displayed. -.PP -Whether they\[aq]re set ergonomically, in a command line, by an input -tool, or through the APIs (for example, classes contained in the package -\f[V]java.lang.management\f[R]) the values provided to all Java Virtual -Machine (JVM) command-line flags are validated. -Ergonomics are described in Java Platform, Standard Edition HotSpot -Virtual Machine Garbage Collection Tuning Guide. -.PP -Range and constraints are validated either when all flags have their -values set during JVM initialization or a flag\[aq]s value is changed -during runtime (for example using the \f[V]jcmd\f[R] tool). -The JVM is terminated if a value violates either the range or constraint -check and an appropriate error message is printed on the error stream. -.PP -For example, if a flag violates a range or a constraint check, then the -JVM exits with an error: -.IP -.nf -\f[CB] -java -XX:AllocatePrefetchStyle=5 -version -intx AllocatePrefetchStyle=5 is outside the allowed range [ 0 ... 3 ] -Improperly specified VM option \[aq]AllocatePrefetchStyle=5\[aq] -Error: Could not create the Java Virtual Machine. -Error: A fatal exception has occurred. Program will exit. -\f[R] -.fi -.PP -The flag \f[V]-XX:+PrintFlagsRanges\f[R] prints the range of all the -flags. -This flag allows automatic testing of the flags by the values provided -by the ranges. -For the flags that have the ranges specified, the type, name, and the -actual range is printed in the output. -.PP -For example, -.IP -.nf -\f[CB] -intx ThreadStackSize [ 0 ... 9007199254740987 ] {pd product} -\f[R] -.fi -.PP -For the flags that don\[aq]t have the range specified, the values -aren\[aq]t displayed in the print out. -For example: -.IP -.nf -\f[CB] -size_t NewSize [ ... ] {product} -\f[R] -.fi -.PP -This helps to identify the flags that need to be implemented. -The automatic testing framework can skip those flags that don\[aq]t have -values and aren\[aq]t implemented. -.SH LARGE PAGES -.PP -You use large pages, also known as huge pages, as memory pages that are -significantly larger than the standard memory page size (which varies -depending on the processor and operating system). -Large pages optimize processor Translation-Lookaside Buffers. -.PP -A Translation-Lookaside Buffer (TLB) is a page translation cache that -holds the most-recently used virtual-to-physical address translations. -A TLB is a scarce system resource. -A TLB miss can be costly because the processor must then read from the -hierarchical page table, which may require multiple memory accesses. -By using a larger memory page size, a single TLB entry can represent a -larger memory range. -This results in less pressure on a TLB, and memory-intensive -applications may have better performance. -.PP -However, using large pages can negatively affect system performance. -For example, when a large amount of memory is pinned by an application, -it may create a shortage of regular memory and cause excessive paging in -other applications and slow down the entire system. -Also, a system that has been up for a long time could produce excessive -fragmentation, which could make it impossible to reserve enough large -page memory. -When this happens, either the OS or JVM reverts to using regular pages. -.PP -Linux and Windows support large pages. -.SS Large Pages Support for Linux -.PP -Linux supports large pages since version 2.6. -To check if your environment supports large pages, try the following: -.IP -.nf -\f[CB] -# cat /proc/meminfo | grep Huge -HugePages_Total: 0 -HugePages_Free: 0 -\&... -Hugepagesize: 2048 kB -\f[R] -.fi -.PP -If the output contains items prefixed with \[dq]Huge\[dq], then your -system supports large pages. -The values may vary depending on environment. -The \f[V]Hugepagesize\f[R] field shows the default large page size in -your environment, and the other fields show details for large pages of -this size. -Newer kernels have support for multiple large page sizes. -To list the supported page sizes, run this: -.IP -.nf -\f[CB] -# ls /sys/kernel/mm/hugepages/ -hugepages-1048576kB hugepages-2048kB -\f[R] -.fi -.PP -The above environment supports 2 MB and 1 GB large pages, but they need -to be configured so that the JVM can use them. -When using large pages and not enabling transparent huge pages (option -\f[V]-XX:+UseTransparentHugePages\f[R]), the number of large pages must -be pre-allocated. -For example, to enable 8 GB of memory to be backed by 2 MB large pages, -login as \f[V]root\f[R] and run: -.RS -.PP -\f[V]# echo 4096 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages\f[R] -.RE -.PP -It is always recommended to check the value of \f[V]nr_hugepages\f[R] -after the request to make sure the kernel was able to allocate the -requested number of large pages. -.RS -.PP -\f[B]Note:\f[R] The values contained in \f[V]/proc\f[R] and -\f[V]/sys\f[R] reset after you reboot your system, so may want to set -them in an initialization script (for example, \f[V]rc.local\f[R] or -\f[V]sysctl.conf\f[R]). -.RE -.PP -If you configure the OS kernel parameters to enable use of large pages, -the Java processes may allocate large pages for the Java heap as well as -other internal areas, for example: -.IP \[bu] 2 -Code cache -.IP \[bu] 2 -Marking bitmaps -.PP -Consequently, if you configure the \f[V]nr_hugepages\f[R] parameter to -the size of the Java heap, then the JVM can still fail to allocate the -heap using large pages because other areas such as the code cache might -already have used some of the configured large pages. -.SS Large Pages Support for Windows -.PP -To use large pages support on Windows, the administrator must first -assign additional privileges to the user who is running the application: -.IP "1." 3 -Select \f[B]Control Panel\f[R], \f[B]Administrative Tools\f[R], and then -\f[B]Local Security Policy\f[R]. -.IP "2." 3 -Select \f[B]Local Policies\f[R] and then \f[B]User Rights -Assignment\f[R]. -.IP "3." 3 -Double-click \f[B]Lock pages in memory\f[R], then add users and/or -groups. -.IP "4." 3 -Reboot your system. -.PP -Note that these steps are required even if it\[aq]s the administrator -who\[aq]s running the application, because administrators by default -don\[aq]t have the privilege to lock pages in memory. -.SH APPLICATION CLASS DATA SHARING -.PP -Application Class Data Sharing (AppCDS) stores classes used by your -applications in an archive file. -Since these classes are stored in a format that can be loaded very -quickly (compared to classes stored in a JAR file), AppCDS can improve -the start-up time of your applications. -In addition, AppCDS can reduce the runtime memory footprint by sharing -parts of these classes across multiple processes. -.PP -Classes in the CDS archive are stored in an optimized format that\[aq]s -about 2 to 5 times larger than classes stored in JAR files or the JDK -runtime image. -Therefore, it\[aq]s a good idea to archive only those classes that are -actually used by your application. -These usually are just a small portion of all available classes. -For example, your application may use only a few APIs provided by a -large library. -.SS Using CDS Archives -.PP -By default, in most JDK distributions, unless \f[V]-Xshare:off\f[R] is -specified, the JVM starts up with a default CDS archive, which is -usually located in \f[V]JAVA_HOME/lib/server/classes.jsa\f[R] (or -\f[V]JAVA_HOME\[rs]bin\[rs]server\[rs]classes.jsa\f[R] on Windows). -This archive contains about 1300 core library classes that are used by -most applications. -.PP -To use CDS for the exact set of classes used by your application, you -can use the \f[V]-XX:SharedArchiveFile\f[R] option, which has the -general form: -.RS -.PP -\f[V]-XX:SharedArchiveFile=:\f[R] -.RE -.IP \[bu] 2 -The \f[V]\f[R] overrides the default CDS archive. -.IP \[bu] 2 -The \f[V]\f[R] provides additional classes that can be -loaded on top of those in the \f[V]\f[R]. -.IP \[bu] 2 -On Windows, the above path delimiter \f[V]:\f[R] should be replaced with -\f[V];\f[R] -.PP -(The names \[dq]static\[dq] and \[dq]dynamic\[dq] are used for -historical reasons. -The only significance is that the \[dq]static\[dq] archive is loaded -first and the \[dq]dynamic\[dq] archive is loaded second). -.PP -The JVM can use up to two archives. -To use only a single \f[V]\f[R], you can omit the -\f[V]\f[R] portion: -.RS -.PP -\f[V]-XX:SharedArchiveFile=\f[R] -.RE -.PP -For convenience, the \f[V]\f[R] records the location of -the \f[V]\f[R]. -Therefore, you can omit the \f[V]\f[R] by saying only: -.RS -.PP -\f[V]-XX:SharedArchiveFile=\f[R] -.RE -.SS Manually Creating CDS Archives -.PP -CDS archives can be created manually using several methods: -.IP \[bu] 2 -\f[V]-Xshare:dump\f[R] -.IP \[bu] 2 -\f[V]-XX:ArchiveClassesAtExit\f[R] -.IP \[bu] 2 -\f[V]jcmd VM.cds\f[R] -.PP -One common operation in all these methods is a \[dq]trial run\[dq], -where you run the application once to determine the classes that should -be stored in the archive. -.SS Creating a Static CDS Archive File with -Xshare:dump -.PP -The following steps create a static CDS archive file that contains all -the classes used by the \f[V]test.Hello\f[R] application. -.IP "1." 3 -Create a list of all classes used by the \f[V]test.Hello\f[R] -application. -The following command creates a file named \f[V]hello.classlist\f[R] -that contains a list of all classes used by this application: -.RS 4 -.RS -.PP -\f[V]java -Xshare:off -XX:DumpLoadedClassList=hello.classlist -cp hello.jar test.Hello\f[R] -.RE -.PP -The classpath specified by the \f[V]-cp\f[R] parameter must contain only -JAR files. -.RE -.IP "2." 3 -Create a static archive, named \f[V]hello.jsa\f[R], that contains all -the classes in \f[V]hello.classlist\f[R]: -.RS 4 -.RS -.PP -\f[V]java -Xshare:dump -XX:SharedArchiveFile=hello.jsa -XX:SharedClassListFile=hello.classlist -cp hello.jar\f[R] -.RE -.RE -.IP "3." 3 -Run the application \f[V]test.Hello\f[R] with the archive -\f[V]hello.jsa\f[R]: -.RS 4 -.RS -.PP -\f[V]java -XX:SharedArchiveFile=hello.jsa -cp hello.jar test.Hello\f[R] -.RE -.RE -.IP "4." 3 -\f[B]Optional\f[R] Verify that the \f[V]test.Hello\f[R] application is -using the class contained in the \f[V]hello.jsa\f[R] shared archive: -.RS 4 -.RS -.PP -\f[V]java -XX:SharedArchiveFile=hello.jsa -cp hello.jar -Xlog:class+load test.Hello\f[R] -.RE -.PP -The output of this command should contain the following text: -.RS -.PP -\f[V][info][class,load] test.Hello source: shared objects file\f[R] -.RE -.RE -.PP -By default, when the \f[V]-Xshare:dump\f[R] option is used, the JVM runs -in interpreter-only mode (as if the \f[V]-Xint\f[R] option were -specified). -This is required for generating deterministic output in the shared -archive file. -I.e., the exact same archive will be generated, bit-for-bit, every time -you dump it. -However, if deterministic output is not needed, and you have a large -classlist, you can explicitly add \f[V]-Xmixed\f[R] to the command-line -to enable the JIT compiler. -This will speed up the archive creation. -.SS Creating a Dynamic CDS Archive File with -XX:ArchiveClassesAtExit -.PP -Advantages of dynamic CDS archives are: -.IP \[bu] 2 -They usually use less disk space, since they don\[aq]t need to store the -classes that are already in the static archive. -.IP \[bu] 2 -They are created with one fewer step than the comparable static archive. -.PP -The following steps create a dynamic CDS archive file that contains the -classes that are used by the \f[V]test.Hello\f[R] application, excluding -those that are already in the default CDS archive. -.IP "1." 3 -Create a dynamic CDS archive, named \f[V]hello.jsa\f[R], that contains -all the classes in \f[V]hello.jar\f[R] loaded by the application -\f[V]test.Hello\f[R]: -.RS 4 -.RS -.PP -\f[V]java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello\f[R] -.RE -.RE -.IP "2." 3 -Run the application \f[V]test.Hello\f[R] with the shared archive -\f[V]hello.jsa\f[R]: -.RS 4 -.RS -.PP -\f[V]java -XX:SharedArchiveFile=hello.jsa -cp hello.jar test.Hello\f[R] -.RE -.RE -.IP "3." 3 -\f[B]Optional\f[R] Repeat step 4 of the previous section to verify that -the \f[V]test.Hello\f[R] application is using the class contained in the -\f[V]hello.jsa\f[R] shared archive. -.PP -It\[aq]s also possible to create a dynamic CDS archive with a -non-default static CDS archive. -E.g., -.RS -.PP -\f[V]java -XX:SharedArchiveFile=base.jsa -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello\f[R] -.RE -.PP -To run the application using this dynamic CDS archive: -.RS -.PP -\f[V]java -XX:SharedArchiveFile=base.jsa:hello.jsa -cp hello.jar Hello\f[R] -.RE -.PP -(On Windows, the above path delimiter \f[V]:\f[R] should be replaced -with \f[V];\f[R]) -.PP -As mention above, the name of the static archive can be skipped: -.RS -.PP -\f[V]java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello\f[R] -.RE -.SS Creating CDS Archive Files with jcmd -.PP -The previous two sections require you to modify the application\[aq]s -start-up script in order to create a CDS archive. -Sometimes this could be difficult, for example, if the application\[aq]s -class path is set up by complex routines. -.PP -The \f[V]jcmd VM.cds\f[R] command provides a less intrusive way for -creating a CDS archive by connecting to a running JVM process. -You can create either a static: -.RS -.PP -\f[V]jcmd VM.cds static_dump my_static_archive.jsa\f[R] -.RE -.PP -or a dynamic archive: -.RS -.PP -\f[V]jcmd VM.cds dynamic_dump my_dynamic_archive.jsa\f[R] -.RE -.PP -To use the resulting archive file in a subsequent run of the application -without modifying the application\[aq]s start-up script, you can use the -following technique: -.RS -.PP -\f[V]env JAVA_TOOL_OPTIONS=-XX:SharedArchiveFile=my_static_archive.jsa bash app_start.sh\f[R] -.RE -.PP -Note: to use \f[V]jcmd VM.cds dynamic_dump\f[R], the JVM process -identified by \f[V]\f[R] must be started with -\f[V]-XX:+RecordDynamicDumpInfo\f[R], which can also be passed to the -application start-up script with the same technique: -.RS -.PP -\f[V]env JAVA_TOOL_OPTIONS=-XX:+RecordDynamicDumpInfo bash app_start.sh\f[R] -.RE -.SS Creating Dynamic CDS Archive File with -XX:+AutoCreateSharedArchive -.PP -\f[V]-XX:+AutoCreateSharedArchive\f[R] is a more convenient way of -creating/using CDS archives. -Unlike the methods of manual CDS archive creation described in the -previous section, with \f[V]-XX:+AutoCreateSharedArchive\f[R], it\[aq]s -no longer necessary to have a separate trial run. -Instead, you can always run the application with the same command-line -and enjoy the benefits of CDS automatically. -.RS -.PP -\f[V]java -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello\f[R] -.RE -.PP -If the specified archive file exists and was created by the same version -of the JDK, then it will be loaded as a dynamic archive; otherwise it is -ignored at VM startup. -.PP -At VM exit, if the specified archive file does not exist, it will be -created. -If it exists but was created with a different (but post JDK 19) version -of the JDK, then it will be replaced. -In both cases the archive will be ready to be loaded the next time the -JVM is launched with the same command line. -.PP -If the specified archive file exists but was created by a JDK version -prior to JDK 19, then it will be ignored: neither loaded at startup, nor -replaced at exit. -.PP -Developers should note that the contents of the CDS archive file are -specific to each build of the JDK. -Therefore, if you switch to a different JDK build, -\f[V]-XX:+AutoCreateSharedArchive\f[R] will automatically recreate the -archive to match the JDK. -If you intend to use this feature with an existing archive, you should -make sure that the archive is created by at least version 19 of the JDK. -.SS Restrictions on Class Path and Module Path -.IP \[bu] 2 -Neither the class path (\f[V]-classpath\f[R] and -\f[V]-Xbootclasspath/a\f[R]) nor the module path -(\f[V]--module-path\f[R]) can contain non-empty directories. -.IP \[bu] 2 -Only modular JAR files are supported in \f[V]--module-path\f[R]. -Exploded modules are not supported. -.IP \[bu] 2 -The class path used at archive creation time must be the same as (or a -prefix of) the class path used at run time. -(There\[aq]s no such requirement for the module path.) -.IP \[bu] 2 -The CDS archive cannot be loaded if any JAR files in the class path or -module path are modified after the archive is generated. -.IP \[bu] 2 -If any of the VM options \f[V]--upgrade-module-path\f[R], -\f[V]--patch-module\f[R] or \f[V]--limit-modules\f[R] are specified, CDS -is disabled. -This means that the JVM will execute without loading any CDS archives. -In addition, if you try to create a CDS archive with any of these 3 -options specified, the JVM will report an error. -.SH PERFORMANCE TUNING EXAMPLES -.PP -You can use the Java advanced runtime options to optimize the -performance of your applications. -.SS Tuning for Higher Throughput -.PP -Use the following commands and advanced options to achieve higher -throughput performance for your application: -.RS -.PP -\f[V]java -server -XX:+UseParallelGC -XX:+UseLargePages -Xmn10g -Xms26g -Xmx26g\f[R] -.RE -.SS Tuning for Lower Response Time -.PP -Use the following commands and advanced options to achieve lower -response times for your application: -.RS -.PP -\f[V]java -XX:+UseG1GC -XX:MaxGCPauseMillis=100\f[R] -.RE -.SS Keeping the Java Heap Small and Reducing the Dynamic Footprint of Embedded Applications -.PP -Use the following advanced runtime options to keep the Java heap small -and reduce the dynamic footprint of embedded applications: -.RS -.PP -\f[V]-XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=5\f[R] -.RE -.RS -.PP -\f[B]Note:\f[R] The defaults for these two options are 70% and 40% -respectively. -Because performance sacrifices can occur when using these small -settings, you should optimize for a small footprint by reducing these -settings as much as possible without introducing unacceptable -performance degradation. -.RE -.SH EXIT STATUS -.PP -The following exit values are typically returned by the launcher when -the launcher is called with the wrong arguments, serious errors, or -exceptions thrown by the JVM. -However, a Java application may choose to return any value by using the -API call \f[V]System.exit(exitValue)\f[R]. -The values are: -.IP \[bu] 2 -\f[V]0\f[R]: Successful completion -.IP \[bu] 2 -\f[V]>0\f[R]: An error occurred diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md new file mode 100644 index 00000000000..5f1f9d8ef45 --- /dev/null +++ b/src/java.base/share/man/java.md @@ -0,0 +1,4052 @@ +--- +# Copyright (c) 1994, 2024, 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. +# + +title: 'JAVA(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +java - launch a Java application + +## Synopsis + +To launch a class file: + +`java` \[*options*\] *mainclass* \[*args* ...\] + +To launch the main class in a JAR file: + +`java` \[*options*\] `-jar` *jarfile* \[*args* ...\] + +To launch the main class in a module: + +`java` \[*options*\] `-m` *module*\[`/`*mainclass*\] \[*args* ...\] + +or + +`java` \[*options*\] `--module` *module*\[`/`*mainclass*\] \[*args* ...\] + +To launch a source-file program: + +`java` \[*options*\] *source-file* \[*args* ...\] + +*options* +: Optional: Specifies command-line options separated by spaces. See [Overview + of Java Options] for a description of available + options. + +*mainclass* +: Specifies the name of the class to be launched. Command-line entries + following `classname` are the arguments for the main method. + +`-jar` *jarfile* +: Executes a program encapsulated in a JAR file. The *jarfile* argument is + the name of a JAR file with a manifest that contains a line in the form + `Main-Class:`*classname* that defines the class with the + `public static void main(String[] args)` method that serves as your + application's starting point. When you use `-jar`, the specified JAR file + is the source of all user classes, and other class path settings are + ignored. If you're using JAR files, then see [jar](jar.html). + +`-m` or `--module` *module*\[`/`*mainclass*\] +: Executes the main class in a module specified by *mainclass* if it is + given, or, if it is not given, the value in the *module*. In other words, + *mainclass* can be used when it is not specified by the module, or to + override the value when it is specified. + + See [Standard Options for Java]. + +*source-file* +: Only used to launch a source-file program. Specifies the source file + that contains the main class when using source-file mode. See [Using + Source-File Mode to Launch Source-Code Programs] + +*args* ... +: Optional: Arguments following *mainclass*, *source-file*, `-jar` *jarfile*, + and `-m` or `--module` *module*`/`*mainclass* are passed as arguments to + the main class. + +## Description + +The `java` command starts a Java application. It does this by starting the Java +Virtual Machine (JVM), loading the specified class, and calling that +class's `main()` method. The method must be declared `public` and `static`, it +must not return any value, and it must accept a `String` array as a parameter. +The method declaration has the following form: + +> `public static void main(String[] args)` + +In source-file mode, the `java` command can launch a class declared in a source +file. See [Using Source-File Mode to Launch Source-Code Programs] +for a description of using the source-file mode. + +> **Note:** You can use the `JDK_JAVA_OPTIONS` launcher environment variable to prepend its +content to the actual command line of the `java` launcher. See [Using the +JDK\_JAVA\_OPTIONS Launcher Environment Variable]. + +By default, the first argument that isn't an option of the `java` command is +the fully qualified name of the class to be called. If `-jar` is specified, +then its argument is the name of the JAR file containing class and resource +files for the application. The startup class must be indicated by the +`Main-Class` manifest header in its manifest file. + +Arguments after the class file name or the JAR file name are passed to the +`main()` method. + +### `javaw` + +**Windows:** The `javaw` command is identical to `java`, except that with +`javaw` there's no associated console window. Use `javaw` when you don't want a +command prompt window to appear. The `javaw` launcher will, however, display a +dialog box with error information if a launch fails. + +## Using Source-File Mode to Launch Source-Code Programs + +To launch a class declared in a source file, run the `java` launcher in +source-file mode. Entering source-file mode is determined by two items on the +`java` command line: + +- The first item on the command line that is not an option or part of an + option. In other words, the item in the command line that would otherwise + be the main class name. + +- The `--source` *version* option, if present. + +If the class identifies an existing file that has a `.java` extension, or if +the `--source` option is specified, then source-file mode is selected. The +source file is then compiled and run. The `--source` option can be used to +specify the source *version* or *N* of the source code. This determines the API +that can be used. When you set `--source` *N*, you can only use the public API +that was defined in JDK *N*. + +> **Note:** The valid values of *N* change for each release, with new values added and old +values removed. You'll get an error message if you use a value of *N* that is +no longer supported. +The supported values of *N* are the current Java SE release (`@@VERSION_SPECIFICATION@@`) +and a limited number of previous releases, detailed in the command-line help +for `javac`, under the `--source` and `--release` options. + +If the file does not have the `.java` extension, the `--source` option must be +used to tell the `java` command to use the source-file mode. The `--source` +option is used for cases when the source file is a "script" to be executed and +the name of the source file does not follow the normal naming conventions for +Java source files. + +In source-file mode, the effect is as though the source file is compiled into +memory, and the first class found in the source file is executed. Any arguments +placed after the name of the source file in the original command line are +passed to the compiled class when it is executed. + +For example, if a file were named `HelloWorld.java` and contained a class named +`HelloWorld`, then the source-file mode command to launch the class would be: + +> `java HelloWorld.java` + +This use of source-file mode is informally equivalent to using the following two +commands: + +``` +javac -d --source-path HelloWorld.java +java --class-path HelloWorld +``` + +where `` is computed + +**In source-file mode, any additional command-line options are processed as +follows:** + +- The launcher scans the options specified before the source file for any + that are relevant in order to compile the source file. + + This includes: `--class-path`, `--module-path`, `--add-exports`, + `--add-modules`, `--limit-modules`, `--patch-module`, + `--upgrade-module-path`, and any variant forms of those options. It also + includes the new `--enable-preview` option, described in JEP 12. + +- No provision is made to pass any additional options to the compiler, such + as `-processor` or `-Werror`. + +- Command-line argument files (`@`-files) may be used in the standard way. + Long lists of arguments for either the VM or the program being invoked may + be placed in files specified on the command-line by prefixing the filename + with an `@` character. + +**In source-file mode, compilation proceeds as follows:** + +- Any command-line options that are relevant to the compilation environment + are taken into account. These include: `--class-path`/`-classpath`/`-cp`, + `--module-path`/`-p`, `--add-exports`, `--add-modules`, `--limit-modules`, + `--patch-module`, `--upgrade-module-path`, `--enable-preview`. + +- The root of the source tree, `` is computed from the package + of the class being launched. For example, if `HelloWorld.java` declared its classes + to be in the `hello` package, then the file `HelloWorld.java` is expected + to reside in the directory `somedir/hello/`. In this case, `somedir` is + computed to be the root of the source tree. + +- The root of the source tree serves as the source-path for compilation, so that + other source files found in that tree and are needed by `HelloWorld` could be + compiled. + +- Annotation processing is disabled, as if `-proc:none` is in effect. + +- If a version is specified, via the `--source` option, the value is used as + the argument for an implicit `--release` option for the compilation. This + sets both the source version accepted by compiler and the system API that + may be used by the code in the source file. + +- If `--enable-preview` is specified, the `--source N` arguments can be omitted. + If the Java runtime version is `N`, then `--release N` is implied when + compiling source files. + +- If a `module-info.java` file exists in the `` directory, its + module declaration is used to define a named module that will contain all + the classes compiled from `.java` files in the source tree. If + `module-info.java` does not exist, all the classes compiled from source files + will be compiled in the context of the unnamed module. + +- The source file that is launched should contain one or more top-level classes, the first of + which is taken as the class to be executed. + +- For the source file that is launched, the compiler does not enforce the optional restriction defined at the end + of JLS 7.6, that a type in a named package should exist in a file whose + name is composed from the type name followed by the `.java` extension. + +- If a source file contains errors, appropriate error messages are written + to the standard error stream, and the launcher exits with a non-zero exit + code. + +**In source-file mode, execution proceeds as follows:** + +- The class to be executed is the first top-level class found in the source + file. It must contain a declaration of an entry `main` method. + +- The compiled classes are loaded by a custom class loader, that delegates to + the application class loader. This implies that classes appearing on the + application class path cannot refer to any classes declared in source files. + +- If a `module-info.java` file exists in the `` directory, then all + the classes compiled from `.java` files in the source tree will be in that + module, which will serve as the root module for the execution of the program. + If `module-info.java` does not exist, the compiled classes are executed in the + context of an unnamed module, as though `--add-modules=ALL-DEFAULT` is in effect. + This is in addition to any other `--add-module` options that may be have been + specified on the command line. + +- Any arguments appearing after the name of the file on the command line are + passed to the main method in the obvious way. + +- It is an error if there is a class on the application class path whose name + is the same as that of the class to be executed. + +See [JEP 458: Launch Multi-File Source-Code Programs]( +https://openjdk.org/jeps/458) for complete details. + +## Using the JDK\_JAVA\_OPTIONS Launcher Environment Variable + +`JDK_JAVA_OPTIONS` prepends its content to the options parsed from the command +line. The content of the `JDK_JAVA_OPTIONS` environment variable is a list of +arguments separated by white-space characters (as determined by `isspace()`). +These are prepended to the command line arguments passed to `java` launcher. +The encoding requirement for the environment variable is the same as the `java` +command line on the system. `JDK_JAVA_OPTIONS` environment variable content is +treated in the same manner as that specified in the command line. + +Single (`'`) or double (`"`) quotes can be used to enclose arguments that +contain whitespace characters. All content between the open quote and the +first matching close quote are preserved by simply removing the pair of quotes. +In case a matching quote is not found, the launcher will abort with an error +message. `@`-files are supported as they are specified in the command line. +However, as in `@`-files, use of a wildcard is not supported. In order to +mitigate potential misuse of `JDK_JAVA_OPTIONS` behavior, options that specify +the main class (such as `-jar`) or cause the `java` launcher to exit without +executing the main class (such as `-h`) are disallowed in the environment +variable. If any of these options appear in the environment variable, the +launcher will abort with an error message. When `JDK_JAVA_OPTIONS` is set, the +launcher prints a message to stderr as a reminder. + +**Example:** + +``` +$ export JDK_JAVA_OPTIONS='-g @file1 -Dprop=value @file2 -Dws.prop="white spaces"' +$ java -Xint @file3 +``` + +is equivalent to the command line: + +``` +java -g @file1 -Dprop=value @file2 -Dws.prop="white spaces" -Xint @file3 +``` + +## Overview of Java Options + +The `java` command supports a wide range of options in the following +categories: + +- [Standard Options for Java]\: Options guaranteed to be supported by all + implementations of the Java Virtual Machine (JVM). They're used for common + actions, such as checking the version of the JRE, setting the class path, + enabling verbose output, and so on. + +- [Extra Options for Java]\: General purpose options that are specific to the + Java HotSpot Virtual Machine. They aren't guaranteed to be supported by + all JVM implementations, and are subject to change. These options start + with `-X`. + +The advanced options aren't recommended for casual use. These are developer +options used for tuning specific areas of the Java HotSpot Virtual Machine +operation that often have specific system requirements and may require +privileged access to system configuration parameters. Several examples of +performance tuning are provided in [Performance Tuning Examples]. These +options aren't guaranteed to be supported by all JVM implementations and are +subject to change. Advanced options start with `-XX`. + +- [Advanced Runtime Options for Java]\: Control the runtime behavior of the + Java HotSpot VM. + +- [Advanced JIT Compiler Options for java]\: Control the dynamic just-in-time + (JIT) compilation performed by the Java HotSpot VM. + +- [Advanced Serviceability Options for Java]\: Enable gathering system + information and performing extensive debugging. + +- [Advanced Garbage Collection Options for Java]\: Control how garbage + collection (GC) is performed by the Java HotSpot + +Boolean options are used to either enable a feature that's disabled by default +or disable a feature that's enabled by default. Such options don't require a +parameter. Boolean `-XX` options are enabled using the plus sign +(`-XX:+`*OptionName*) and disabled using the minus sign (`-XX:-`*OptionName*). + +For options that require an argument, the argument may be separated from the +option name by a space, a colon (:), or an equal sign (=), or the argument may +directly follow the option (the exact syntax differs for each option). If +you're expected to specify the size in bytes, then you can use no suffix, or +use the suffix `k` or `K` for kilobytes (KB), `m` or `M` for megabytes (MB), or +`g` or `G` for gigabytes (GB). For example, to set the size to 8 GB, you can +specify either `8g`, `8192m`, `8388608k`, or `8589934592` as the argument. If +you are expected to specify the percentage, then use a number from 0 to 1. For +example, specify `0.25` for 25%. + +The following sections describe the options that are deprecated, obsolete, and +removed: + +- [Deprecated Java Options]\: Accepted and acted upon --- a warning is issued + when they're used. + +- [Obsolete Java Options]\: Accepted but ignored --- a warning is issued when + they're used. + +- [Removed Java Options]\: Removed --- using them results in an error. + +## Standard Options for Java + +These are the most commonly used options supported by all implementations of +the JVM. + +> **Note:** To specify an argument for a long option, you can use either +`--`*name*`=`*value* or `--`*name* *value*. + +`-agentlib:`*libname*\[`=`*options*\] +: Loads the specified native agent library. After the library name, a + comma-separated list of options specific to the library can be used. + If the option `-agentlib:foo` is specified, then the JVM attempts to + load the library named `foo` using the platform specific naming + conventions and locations: + + - **Linux and other POSIX-like platforms:** The JVM attempts to load + the library named `libfoo.so` in the location specified by the + `LD_LIBRARY_PATH` system variable. + + - **macOS:** The JVM attempts to load the library named `libfoo.dylib` + in the location specified by the `DYLD_LIBRARY_PATH` system variable. + + - **Windows:** The JVM attempts to load the library named `foo.dll` in + the location specified by the `PATH` system variable. + + The following example shows how to load the Java Debug Wire Protocol + (JDWP) library and listen for the socket connection on port 8000, + suspending the JVM before the main class loads: + + > `-agentlib:jdwp=transport=dt_socket,server=y,address=8000` + +`-agentpath:`*pathname*\[`=`*options*\] +: Loads the native agent library specified by the absolute path name. This + option is equivalent to `-agentlib` but uses the full path and file name of + the library. + +`--class-path` *classpath*, `-classpath` *classpath*, or `-cp` *classpath* +: Specifies a list of directories, JAR files, and ZIP archives to search + for class files. + + On Windows, semicolons (`;`) separate entities in this list; + on other platforms it is a colon (`:`). + + Specifying *classpath* overrides any setting of the `CLASSPATH` environment + variable. If the class path option isn't used and *classpath* isn't set, + then the user class path consists of the current directory (.). + + As a special convenience, a class path element that contains a base name of + an asterisk (\*) is considered equivalent to specifying a list of all the + files in the directory with the extension `.jar` or `.JAR` . A Java program + can't tell the difference between the two invocations. For example, if the + directory mydir contains `a.jar` and `b.JAR`, then the class path element + mydir/\* is expanded to `A.jar:b.JAR`, except that the order of JAR files + is unspecified. All `.jar` files in the specified directory, even hidden + ones, are included in the list. A class path entry consisting of an + asterisk (\*) expands to a list of all the jar files in the current + directory. The `CLASSPATH` environment variable, where defined, is + similarly expanded. Any class path wildcard expansion that occurs before + the Java VM is started. Java programs never see wildcards that aren't + expanded except by querying the environment, such as by calling + `System.getenv("CLASSPATH")`. + +`--disable-@files` +: Can be used anywhere on the command line, including in an argument file, to + prevent further `@filename` expansion. This option stops expanding + `@`-argfiles after the option. + +`--enable-preview` +: Allows classes to depend on [preview features](https://docs.oracle.com/en/java/javase/12/language/index.html#JSLAN-GUID-5A82FE0E-0CA4-4F1F-B075-564874FE2823) of the release. + +`--enable-native-access` *module*\[`,`*module*...\] +: Native access involves access to code or data outside the Java runtime. + This is generally unsafe and, if done incorrectly, might crash the JVM or result + in memory corruption. Native access can occur as a result of calling a method that + is either [restricted](https://openjdk.org/jeps/454#Safety), or `native`. + This option allows code in the specified modules to perform native access. + Native access occurring in a module that has not been explicitly enabled + is deemed *illegal*. + + *module* can be a module name, or `ALL-UNNAMED` to indicate code on the class path. + + +-`--illegal-native-access=`*parameter* +: This option specifies a mode for how illegal native access is handled: + + > **Note:** This option will be removed in a future release. + + - `allow`: This mode allows illegal native access in all modules, + without any warings. + + - `warn`: This mode is identical to `allow` except that a warning + message is issued for the first illegal native access found in a module. + This mode is the default for the current JDK but will change in a future + release. + + - `deny`: This mode disables illegal native access. That is, any illegal native + access causes an `IllegalCallerException`. This mode will become the default + in a future release. + + To verify that your application is ready for a future version of the JDK, + run it with `--illegal-native-access=deny` along with any necessary `--enable-native-access` + options. + +`--finalization=`*value* +: Controls whether the JVM performs finalization of objects. Valid values + are "enabled" and "disabled". Finalization is enabled by default, so the + value "enabled" does nothing. The value "disabled" disables finalization, + so that no finalizers are invoked. + +`--module-path` *modulepath*... or `-p` *modulepath* +: Specifies where to find application modules with a list of path elements. + The elements of a module path can be a file path to a module or a directory + containing modules. Each module is either a modular JAR or an + exploded-module directory. + + On Windows, semicolons (`;`) separate path elements in this list; + on other platforms it is a colon (`:`). + +`--upgrade-module-path` *modulepath*... +: Specifies where to find module replacements of upgradeable modules in the + runtime image with a list of path elements. + The elements of a module path can be a file path to a module or a directory + containing modules. Each module is either a modular JAR or an + exploded-module directory. + + On Windows, semicolons (`;`) separate path elements in this list; + on other platforms it is a colon (`:`). + +`--add-modules` *module*\[`,`*module*...\] +: Specifies the root modules to resolve in addition to the initial module. + *module* can also be `ALL-DEFAULT`, `ALL-SYSTEM`, and `ALL-MODULE-PATH`. + +`--list-modules` +: Lists the observable modules and then exits. + +`-d` *module\_name* or `--describe-module` *module\_name* +: Describes a specified module and then exits. + +`--dry-run` +: Creates the VM but doesn't execute the main method. This `--dry-run` option + might be useful for validating the command-line options such as the module + system configuration. + +`--validate-modules` +: Validates all modules and exit. This option is helpful for finding + conflicts and other errors with modules on the module path. + +`-D`*property*`=`*value* +: Sets a system property value. The *property* variable is a string with no + spaces that represents the name of the property. The *value* variable is a + string that represents the value of the property. If *value* is a string + with spaces, then enclose it in quotation marks (for example + `-Dfoo="foo bar"`). + +`-disableassertions`\[`:`\[*packagename*\]...\|`:`*classname*\] or `-da`\[`:`\[*packagename*\]...\|`:`*classname*\] +: Disables assertions. By default, assertions are disabled in all packages + and classes. With no arguments, `-disableassertions` (`-da`) disables + assertions in all packages and classes. With the *packagename* argument + ending in `...`, the switch disables assertions in the specified package + and any subpackages. If the argument is simply `...`, then the switch + disables assertions in the unnamed package in the current working + directory. With the *classname* argument, the switch disables assertions in + the specified class. + + The `-disableassertions` (`-da`) option applies to all class loaders and to + system classes (which don't have a class loader). There's one exception to + this rule: If the option is provided with no arguments, then it doesn't + apply to system classes. This makes it easy to disable assertions in all + classes except for system classes. The `-disablesystemassertions` option + enables you to disable assertions in all system classes. To explicitly + enable assertions in specific packages or classes, use the + `-enableassertions` (`-ea`) option. Both options can be used at the same + time. For example, to run the `MyClass` application with assertions enabled + in the package `com.wombat.fruitbat` (and any subpackages) but disabled in + the class `com.wombat.fruitbat.Brickbat`, use the following command: + + > `java -ea:com.wombat.fruitbat... -da:com.wombat.fruitbat.Brickbat + MyClass` + +`-disablesystemassertions` or `-dsa` +: Disables assertions in all system classes. + +`-enableassertions`\[`:`\[*packagename*\]...\|`:`*classname*\] or `-ea`\[`:`\[*packagename*\]...\|`:`*classname*\] +: Enables assertions. By default, assertions are disabled in all packages and + classes. With no arguments, `-enableassertions` (`-ea`) enables assertions + in all packages and classes. With the *packagename* argument ending in + `...`, the switch enables assertions in the specified package and any + subpackages. If the argument is simply `...`, then the switch enables + assertions in the unnamed package in the current working directory. With + the *classname* argument, the switch enables assertions in the specified + class. + + The `-enableassertions` (`-ea`) option applies to all class loaders and to + system classes (which don't have a class loader). There's one exception to + this rule: If the option is provided with no arguments, then it doesn't + apply to system classes. This makes it easy to enable assertions in all + classes except for system classes. The `-enablesystemassertions` option + provides a separate switch to enable assertions in all system classes. To + explicitly disable assertions in specific packages or classes, use the + `-disableassertions` (`-da`) option. If a single command contains multiple + instances of these switches, then they're processed in order, before + loading any classes. For example, to run the `MyClass` application with + assertions enabled only in the package `com.wombat.fruitbat` (and any + subpackages) but disabled in the class `com.wombat.fruitbat.Brickbat`, use + the following command: + + > `java -ea:com.wombat.fruitbat... -da:com.wombat.fruitbat.Brickbat + MyClass` + +`-enablesystemassertions` or `-esa` +: Enables assertions in all system classes. + +`-help`, `-h`, or `-?` +: Prints the help message to the error stream. + +`--help` +: Prints the help message to the output stream. + +`-javaagent:`*jarpath*\[`=`*options*\] +: Loads the specified Java programming language agent. See `java.lang.instrument`. + +`--show-version` +: Prints the product version to the output stream and continues. + +`-showversion` +: Prints the product version to the error stream and continues. + +`--show-module-resolution` +: Shows module resolution output during startup. + +`-splash:`*imagepath* +: Shows the splash screen with the image specified by *imagepath*. HiDPI + scaled images are automatically supported and used if available. The + unscaled image file name, such as `image.ext`, should always be passed as + the argument to the `-splash` option. The most appropriate scaled image + provided is picked up automatically. + + For example, to show the `splash.gif` file from the `images` directory when + starting your application, use the following option: + + > `-splash:images/splash.gif` + + See the SplashScreen API documentation for more information. + +`-verbose:class` +: Displays information about each loaded class. + +`-verbose:gc` +: Displays information about each garbage collection (GC) event. + +`-verbose:jni` +: Displays information about the use of native methods and other Java Native + Interface (JNI) activity. + +`-verbose:module` +: Displays information about the modules in use. + +`--version` +: Prints product version to the output stream and exits. + +`-version` +: Prints product version to the error stream and exits. + +`-X` +: Prints the help on extra options to the error stream. + +`--help-extra` +: Prints the help on extra options to the output stream. + +`@`*argfile* +: Specifies one or more argument files prefixed by `@` used by the `java` + command. It isn't uncommon for the `java` command line to be very long + because of the `.jar` files needed in the classpath. The `@`*argfile* + option overcomes command-line length limitations by enabling the launcher + to expand the contents of argument files after shell expansion, but before + argument processing. Contents in the argument files are expanded because + otherwise, they would be specified on the command line until the + `--disable-@files` option was encountered. + + The argument files can also contain the main class name and all options. If + an argument file contains all of the options required by the `java` + command, then the command line could simply be: + + > `java @`*argfile* + + See [java Command-Line Argument Files] for a description and examples of + using `@`-argfiles. + +## Extra Options for Java + +The following `java` options are general purpose options that are specific to +the Java HotSpot Virtual Machine. + +`-Xbatch` +: Disables background compilation. By default, the JVM compiles the method as + a background task, running the method in interpreter mode until the + background compilation is finished. The `-Xbatch` flag disables background + compilation so that compilation of all methods proceeds as a foreground + task until completed. This option is equivalent to + `-XX:-BackgroundCompilation`. + +`-Xbootclasspath/a:`*directories*\|*zip*\|*JAR-files* +: Specifies a list of directories, JAR files, and ZIP archives to append to + the end of the default bootstrap class path. + + On Windows, semicolons (`;`) separate entities in this list; + on other platforms it is a colon (`:`). + +`-Xcheck:jni` +: Performs additional checks for Java Native Interface (JNI) functions. + + The following checks are considered indicative of significant problems + with the native code, and the JVM terminates with an irrecoverable + error in such cases: + + - The thread doing the call is not attached to the JVM. + - The thread doing the call is using the `JNIEnv` belonging to another + thread. + - A parameter validation check fails: + - A `jfieldID`, or `jmethodID`, is detected as being invalid. For example: + - Of the wrong type + - Associated with the wrong class + - A parameter of the wrong type is detected. + - An invalid parameter value is detected. For example: + - NULL where not permitted + - An out-of-bounds array index, or frame capacity + - A non-UTF-8 string + - An invalid JNI reference + - An attempt to use a `ReleaseXXX` function on a parameter not + produced by the corresponding `GetXXX` function + + The following checks only result in warnings being printed: + + - A JNI call was made without checking for a pending exception from a + previous JNI call, and the current call is not safe when an exception + may be pending. + - A class descriptor is in decorated format (`Lname;`) when it should not be. + - A `NULL` parameter is allowed, but its use is questionable. + - Calling other JNI functions in the scope of `Get/ReleasePrimitiveArrayCritical` + or `Get/ReleaseStringCritical` + + Expect a performance degradation when this option is used. + +`-Xcomp` +: Testing mode to exercise JIT compilers. This option should not be used in production environments. + +`-Xdebug` +: Does nothing; deprecated for removal in a future release. + +`-Xdiag` +: Shows additional diagnostic messages. + +`-Xint` +: Runs the application in interpreted-only mode. Compilation to native code + is disabled, and all bytecode is executed by the interpreter. The + performance benefits offered by the just-in-time (JIT) compiler aren't + present in this mode. + +`-Xinternalversion` +: Displays more detailed JVM version information than the `-version` option, + and then exits. + +`-Xlog:`*option* +: Configure or enable logging with the Java Virtual Machine (JVM) unified + logging framework. See [Enable Logging with the JVM Unified Logging + Framework]. + +`-Xmixed` +: Executes all bytecode by the interpreter except for hot methods, which are + compiled to native code. On by default. Use `-Xint` to switch off. + +`-Xmn` *size* +: Sets the initial and maximum size (in bytes) of the heap for the young + generation (nursery) in the generational collectors. Append the letter + `k` or `K` to indicate kilobytes, `m` or `M` to indicate megabytes, or + `g` or `G` to indicate gigabytes. The young generation region of the heap + is used for new objects. GC is performed in this region more often than + in other regions. If the size for the young generation is too small, then + a lot of minor garbage collections are performed. If the size is too large, + then only full garbage collections are performed, which can take a long + time to complete. It is recommended that you do not set the size for the + young generation for the G1 collector, and keep the size for the young + generation greater than 25% and less than 50% of the overall heap size for + other collectors. + The following examples show how to set the initial and maximum size of + young generation to 256 MB using various units: + + ``` + -Xmn256m + -Xmn262144k + -Xmn268435456 + ``` + + Instead of the `-Xmn` option to set both the initial and maximum size of + the heap for the young generation, you can use `-XX:NewSize` to set the + initial size and `-XX:MaxNewSize` to set the maximum size. + +`-Xms` *size* +: Sets the minimum and the initial size (in bytes) of the heap. This value + must be a multiple of 1024 and greater than 1 MB. Append the letter `k` or + `K` to indicate kilobytes, `m` or `M` to indicate megabytes, or `g` or `G` + to indicate gigabytes. The following examples show how to set the size of + allocated memory to 6 MB using various units: + + ``` + -Xms6291456 + -Xms6144k + -Xms6m + ``` + + If you do not set this option, then the initial size will be set as the sum + of the sizes allocated for the old generation and the young generation. The + initial size of the heap for the young generation can be set using the + `-Xmn` option or the `-XX:NewSize` option. + + Note that the `-XX:InitialHeapSize` option can also be used to set the + initial heap size. If it appears after `-Xms` on the command line, then the + initial heap size gets set to the value specified with `-XX:InitialHeapSize`. + +`-Xmx` *size* +: Specifies the maximum size (in bytes) of the heap. This value + must be a multiple of 1024 and greater than 2 MB. Append the letter `k` or + `K` to indicate kilobytes, `m` or `M` to indicate megabytes, or `g` or `G` + to indicate gigabytes. The default value is chosen at runtime based on system + configuration. For server deployments, `-Xms` and `-Xmx` are often set to + the same value. The following examples show how to set the maximum allowed + size of allocated memory to 80 MB using various units: + + ``` + -Xmx83886080 + -Xmx81920k + -Xmx80m + ``` + + The `-Xmx` option is equivalent to `-XX:MaxHeapSize`. + +`-Xnoclassgc` +: Disables garbage collection (GC) of classes. This can save some GC time, + which shortens interruptions during the application run. When you specify + `-Xnoclassgc` at startup, the class objects in the application are left + untouched during GC and are always be considered live. This can result in + more memory being permanently occupied which, if not used carefully, throws + an out-of-memory exception. + +`-Xrs` +: Reduces the use of operating system signals by the JVM. Shutdown hooks + enable the orderly shutdown of a Java application by running user cleanup + code (such as closing database connections) at shutdown, even if the JVM + terminates abruptly. + + - **Non-Windows:** + + - The JVM catches signals to implement shutdown hooks for unexpected + termination. The JVM uses `SIGHUP`, `SIGINT`, and `SIGTERM` to + initiate the running of shutdown hooks. + + - Applications embedding the JVM frequently need to trap signals such + as `SIGINT` or `SIGTERM`, which can lead to interference with the + JVM signal handlers. The `-Xrs` option is available to address this + issue. When `-Xrs` is used, the signal masks for `SIGINT`, + `SIGTERM`, `SIGHUP`, and `SIGQUIT` aren't changed by the JVM, and + signal handlers for these signals aren't installed. + + - **Windows:** + + - The JVM watches for console control events to implement shutdown + hooks for unexpected termination. Specifically, the JVM registers a + console control handler that begins shutdown-hook processing and + returns `TRUE` for `CTRL_C_EVENT`, `CTRL_CLOSE_EVENT`, + `CTRL_LOGOFF_EVENT`, and `CTRL_SHUTDOWN_EVENT`. + + - The JVM uses a similar mechanism to implement the feature of + dumping thread stacks for debugging purposes. The JVM uses + `CTRL_BREAK_EVENT` to perform thread dumps. + + - If the JVM is run as a service (for example, as a servlet engine + for a web server), then it can receive `CTRL_LOGOFF_EVENT` but + shouldn't initiate shutdown because the operating system doesn't + actually terminate the process. To avoid possible interference such + as this, the `-Xrs` option can be used. When the `-Xrs` option is + used, the JVM doesn't install a console control handler, implying + that it doesn't watch for or process `CTRL_C_EVENT`, + `CTRL_CLOSE_EVENT`, `CTRL_LOGOFF_EVENT`, or `CTRL_SHUTDOWN_EVENT`. + + There are two consequences of specifying `-Xrs`: + + - **Non-Windows:** `SIGQUIT` thread dumps aren't + available. + + - **Windows:** Ctrl + Break thread dumps aren't available. + + User code is responsible for causing shutdown hooks to run, for example, by + calling `System.exit()` when the JVM is to be terminated. + +`-Xshare:`*mode* +: Sets the class data sharing (CDS) mode. + + Possible *mode* arguments for this option include the following: + + `auto` + : Use shared class data if possible (default). + + `on` + : Require using shared class data, otherwise fail. + + > **Note:** The `-Xshare:on` option is used for testing purposes only. + It may cause the VM to unexpectedly exit during start-up when the CDS + archive cannot be used (for example, when certain VM parameters are changed, + or when a different JDK is used). This option should not be used + in production environments. + + `off` + : Do not attempt to use shared class data. + +`-XshowSettings` +: Shows all settings and then continues. + +`-XshowSettings:`*category* +: Shows settings and continues. Possible *category* arguments for this option + include the following: + + `all` + : Shows all categories of settings in **verbose** detail. + + `locale` + : Shows settings related to locale. + + `properties` + : Shows settings related to system properties. + + `security` + : Shows all settings related to security. + + sub-category arguments for `security` include the following: + + * `security:all` : shows all security settings + * `security:properties` : shows security properties + * `security:providers` : shows static security provider settings + * `security:tls` : shows TLS related security settings + + `vm` + : Shows the settings of the JVM. + + `system` + : **Linux only:** Shows host system or container configuration and continues. + +`-Xss` *size* +: Sets the thread stack size (in bytes). Append the letter `k` or `K` to + indicate KB, `m` or `M` to indicate MB, or `g` or `G` to indicate GB. The + actual size may be rounded up to a multiple of the system page size as + required by the operating system. The default value depends on the + platform. For example: + + - Linux/x64: 1024 KB + + - Linux/Aarch64: 2048 KB + + - macOS/x64: 1024 KB + + - macOS/Aarch64: 2048 KB + + - Windows: The default value depends on virtual memory + + The following examples set the thread stack size to 1024 KB in different + units: + + ``` + -Xss1m + -Xss1024k + -Xss1048576 + ``` + + This option is similar to `-XX:ThreadStackSize`. + +`--add-reads` *module*`=`*target-module*(`,`*target-module*)\* +: Updates *module* to read the *target-module*, regardless of the module + declaration. *target-module* can be `ALL-UNNAMED` to read all unnamed + modules. + +`--add-exports` *module*`/`*package*`=`*target-module*(`,`*target-module*)\* +: Updates *module* to export *package* to *target-module*, regardless of + module declaration. *target-module* can be `ALL-UNNAMED` to export to all + unnamed modules. + +`--add-opens` *module*`/`*package*`=`*target-module*(`,`*target-module*)\* +: Updates *module* to open *package* to *target-module*, regardless of module + declaration. + +`--limit-modules` *module*\[`,`*module*...\] +: Specifies the limit of the universe of observable modules. + +`--patch-module` *module*`=`*file*(`;`*file*)\* +: Overrides or augments a module with classes and resources in JAR files or + directories. + +`--source` *version* +: Sets the version of the source in source-file mode. + + +`--sun-misc-unsafe-memory-access=` *value* +: Allow or deny usage of unsupported API `sun.misc.Unsafe`. *value* is one of: + + `allow` + : Allow use of the memory-access methods with no warnings at run time. + + `warn` + : Allow use of the memory-access methods, but issues a warning on the first + occasion that any memory-access method is used. At most one warning is + issued. + + `debug` + : Allow use of the memory-access methods, but issue a one-line warning and + a stack trace when any memory-access method is used. + + `deny` + : Disallow use of the memory-access methods by throwing an + `UnsupportedOperationException` on every usage. + + The default value when the option is not specified is `allow`. + + +## Extra Options for macOS + +The following extra options are macOS specific. + +`-XstartOnFirstThread` +: Runs the `main()` method on the first (AppKit) thread. + +`-Xdock:name=`*application\_name* +: Overrides the default application name displayed in dock. + +`-Xdock:icon=`*path\_to\_icon\_file* +: Overrides the default icon displayed in dock. + +## Advanced Options for Java + +These `java` options can be used to enable other advanced options. + +`-XX:+UnlockDiagnosticVMOptions` +: Unlocks the options intended for diagnosing the JVM. By default, this + option is disabled and diagnostic options aren't available. + + Command line options that are enabled with the use of this option are + not supported. If you encounter issues while using any of these + options, it is very likely that you will be required to reproduce the + problem without using any of these unsupported options before Oracle + Support can assist with an investigation. It is also possible that any + of these options may be removed or their behavior changed without any + warning. + +`-XX:+UnlockExperimentalVMOptions` +: Unlocks the options that provide experimental features in the JVM. + By default, this option is disabled and experimental features aren't available. + +## Advanced Runtime Options for Java + +These `java` options control the runtime behavior of the Java HotSpot VM. + +`-XX:ActiveProcessorCount=`*x* +: Overrides the number of CPUs that the VM will use to calculate the size of + thread pools it will use for various operations such as Garbage Collection + and ForkJoinPool. + + The VM normally determines the number of available processors from the + operating system. This flag can be useful for partitioning CPU resources + when running multiple Java processes in docker containers. This flag is + honored even if `UseContainerSupport` is not enabled. See + `-XX:-UseContainerSupport` for a description of enabling and disabling + container support. + +`-XX:AllocateHeapAt=`*path* +: Takes a path to the file system and uses memory mapping to allocate the + object heap on the memory device. Using this option enables the HotSpot VM + to allocate the Java object heap on an alternative memory device, such as + an NV-DIMM, specified by the user. + + Alternative memory devices that have the same semantics as DRAM, including + the semantics of atomic operations, can be used instead of DRAM for the + object heap without changing the existing application code. All other + memory structures (such as the code heap, metaspace, and thread stacks) + continue to reside in DRAM. + + Some operating systems expose non-DRAM memory through the file system. + Memory-mapped files in these file systems bypass the page cache and provide + a direct mapping of virtual memory to the physical memory on the device. + The existing heap related flags (such as `-Xmx` and `-Xms`) and + garbage-collection related flags continue to work as before. + +`-XX:-CompactStrings` +: Disables the Compact Strings feature. By default, this option is enabled. + When this option is enabled, Java Strings containing only single-byte + characters are internally represented and stored as + single-byte-per-character Strings using ISO-8859-1 / Latin-1 encoding. This + reduces, by 50%, the amount of space required for Strings containing only + single-byte characters. For Java Strings containing at least one multibyte + character: these are represented and stored as 2 bytes per character using + UTF-16 encoding. Disabling the Compact Strings feature forces the use of + UTF-16 encoding as the internal representation for all Java Strings. + + Cases where it may be beneficial to disable Compact Strings include the + following: + + - When it's known that an application overwhelmingly will be allocating + multibyte character Strings + + - In the unexpected event where a performance regression is observed in + migrating from Java SE 8 to Java SE 9 and an analysis shows that + Compact Strings introduces the regression + + In both of these scenarios, disabling Compact Strings makes sense. + +`-XX:ErrorFile=`*filename* +: Specifies the path and file name to which error data is written when an + irrecoverable error occurs. By default, this file is created in the current + working directory and named `hs_err_pid`*pid*`.log` where *pid* is the + identifier of the process that encountered the error. + + The following example shows how to set the default log file (note that the + identifier of the process is specified as `%p`): + + > `-XX:ErrorFile=./hs_err_pid%p.log` + + - **Non-Windows:** The following example shows how to + set the error log to `/var/log/java/java_error.log`: + + > `-XX:ErrorFile=/var/log/java/java_error.log` + + - **Windows:** The following example shows how to set the error log file + to `C:/log/java/java_error.log`: + + > `-XX:ErrorFile=C:/log/java/java_error.log` + + If the file exists, and is writeable, then it will be overwritten. + Otherwise, if the file can't be created in the specified directory (due to + insufficient space, permission problem, or another issue), then the file is + created in the temporary directory for the operating system: + + - **Non-Windows:** The temporary directory is `/tmp`. + + - **Windows:** The temporary directory is specified by the value of the + `TMP` environment variable; if that environment variable isn't defined, + then the value of the `TEMP` environment variable is used. + +`-XX:+ExtensiveErrorReports` +: Enables the reporting of more extensive error information in the `ErrorFile`. + This option can be turned on in environments where maximal information is + desired - even if the resulting logs may be quite large and/or contain + information that might be considered sensitive. The information can vary + from release to release, and across different platforms. By default this + option is disabled. + +`-XX:FlightRecorderOptions=`*parameter*`=`*value* (or) `-XX:FlightRecorderOptions:`*parameter*`=`*value* +: Sets the parameters that control the behavior of JFR. Multiple parameters can be specified + by separating them with a comma. + + The following list contains the available JFR *parameter*`=`*value* + entries: + + `globalbuffersize=`*size* + : Specifies the total amount of primary memory used for data retention. + The default value is based on the value specified for `memorysize`. + Change the `memorysize` parameter to alter the size of global buffers. + + `maxchunksize=`*size* + : Specifies the maximum size (in bytes) of the data chunks in a + recording. Append `m` or `M` to specify the size in megabytes (MB), or + `g` or `G` to specify the size in gigabytes (GB). By default, the + maximum size of data chunks is set to 12 MB. The minimum allowed is 1 + MB. + + `memorysize=`*size* + : Determines how much buffer memory should be used, and sets the + `globalbuffersize` and `numglobalbuffers` parameters based on the size + specified. Append `m` or `M` to specify the size in megabytes (MB), or + `g` or `G` to specify the size in gigabytes (GB). By default, the + memory size is set to 10 MB. + + `numglobalbuffers` + : Specifies the number of global buffers used. The default value is based + on the memory size specified. Change the `memorysize` parameter to + alter the number of global buffers. + + `old-object-queue-size=number-of-objects` + : Maximum number of old objects to track. By default, the number of + objects is set to 256. + + `preserve-repository=`{`true`\|`false`} + : Specifies whether files stored in the disk repository should be kept + after the JVM has exited. If false, files are deleted. By default, + this parameter is disabled. + + `repository=`*path* + : Specifies the repository (a directory) for temporary disk storage. By + default, the system's temporary directory is used. + + `retransform=`{`true`\|`false`} + : Specifies whether event classes should be retransformed using JVMTI. If + false, instrumentation is added when event classes are loaded. By + default, this parameter is enabled. + + `stackdepth=`*depth* + : Stack depth for stack traces. By default, the depth is set to 64 method + calls. The maximum is 2048. Values greater than 64 could create + significant overhead and reduce performance. + + `threadbuffersize=`*size* + : Specifies the per-thread local buffer size (in bytes). By default, the + local buffer size is set to 8 kilobytes, with a minimum value of + 4 kilobytes. Overriding this parameter + could reduce performance and is not recommended. + +`-XX:LargePageSizeInBytes=`*size* +: Sets the maximum large page size (in bytes) used by the JVM. The + *size* argument must be a valid page size supported by the environment + to have any effect. Append the letter `k` or `K` to indicate kilobytes, + `m` or `M` to indicate megabytes, or `g` or `G` to indicate gigabytes. + By default, the size is set to 0, meaning that the JVM will use the + default large page size for the environment as the maximum size for + large pages. See [Large Pages]. + + The following example describes how to set the large page size to 1 + gigabyte (GB): + + > `-XX:LargePageSizeInBytes=1g` + +`-XX:MaxDirectMemorySize=`*size* +: Sets the maximum total size (in bytes) of the `java.nio` package, + direct-buffer allocations. Append the letter `k` or `K` to indicate + kilobytes, `m` or `M` to indicate megabytes, or `g` or `G` to indicate + gigabytes. If not set, the flag is ignored and the JVM chooses the size + for NIO direct-buffer allocations automatically. + + The following examples illustrate how to set the NIO size to 1024 KB in + different units: + + ``` + -XX:MaxDirectMemorySize=1m + -XX:MaxDirectMemorySize=1024k + -XX:MaxDirectMemorySize=1048576 + ``` + +`-XX:-MaxFDLimit` +: Disables the attempt to set the soft limit for the number of open file + descriptors to the hard limit. By default, this option is enabled on all + platforms, but is ignored on Windows. The only time that you may need to + disable this is on macOS, where its use imposes a maximum of 10240, which + is lower than the actual system maximum. + +`-XX:NativeMemoryTracking=`*mode* +: Specifies the mode for tracking JVM native memory usage. Possible *mode* + arguments for this option include the following: + + `off` + : Instructs not to track JVM native memory usage. This is the default + behavior if you don't specify the `-XX:NativeMemoryTracking` option. + + `summary` + : Tracks memory usage only by JVM subsystems, such as Java heap, class, + code, and thread. + + `detail` + : In addition to tracking memory usage by JVM subsystems, track memory + usage by individual `CallSite`, individual virtual memory region and + its committed regions. + +`-XX:TrimNativeHeapInterval=`*millis* +: Interval, in ms, at which the JVM will trim the native heap. Lower values + will reclaim memory more eagerly at the cost of higher overhead. A value + of 0 (default) disables native heap trimming. + Native heap trimming is performed in a dedicated thread. + + This option is only supported on Linux with GNU C Library (glibc). + +`-XX:+NeverActAsServerClassMachine` +: Enable the "Client VM emulation" mode which only uses the C1 JIT compiler, + a 32Mb CodeCache and the Serial GC. The maximum amount of memory that the + JVM may use (controlled by the `-XX:MaxRAM=n` flag) is set to 1GB by default. + The string "emulated-client" is added to the JVM version string. + + By default the flag is set to `true` only on Windows in 32-bit mode and + `false` in all other cases. + + The "Client VM emulation" mode will not be enabled if any of the following + flags are used on the command line: + + ``` + -XX:{+|-}TieredCompilation + -XX:CompilationMode=mode + -XX:TieredStopAtLevel=n + -XX:{+|-}EnableJVMCI + -XX:{+|-}UseJVMCICompiler + ``` + +`-XX:ObjectAlignmentInBytes=`*alignment* +: Sets the memory alignment of Java objects (in bytes). By default, the value + is set to 8 bytes. The specified value should be a power of 2, and must be + within the range of 8 and 256 (inclusive). This option makes it possible to + use compressed pointers with large Java heap sizes. + + The heap size limit in bytes is calculated as: + + > `4GB * ObjectAlignmentInBytes` + + > **Note:** As the alignment value increases, the unused space between objects also + increases. As a result, you may not realize any benefits from using + compressed pointers with large Java heap sizes. + +`-XX:OnError=`*string* +: Sets a custom command or a series of semicolon-separated commands to run + when an irrecoverable error occurs. If the string contains spaces, then it + must be enclosed in quotation marks. + + - **Non-Windows:** The following example shows how + the `-XX:OnError` option can be used to run the `gcore` command to + create a core image, and start the `gdb` debugger to attach to the + process in case of an irrecoverable error (the `%p` designates the + current process identifier): + + > `-XX:OnError="gcore %p;gdb -p %p"` + + - **Windows:** The following example shows how the `-XX:OnError` option + can be used to run the `userdump.exe` utility to obtain a crash dump in + case of an irrecoverable error (the `%p` designates the current + process identifier). This example assumes that the path to the `userdump.exe` + utility is specified in the `PATH` environment variable: + + > `-XX:OnError="userdump.exe %p"` + +`-XX:OnOutOfMemoryError=`*string* +: Sets a custom command or a series of semicolon-separated commands to run + when an `OutOfMemoryError` exception is first thrown. If the string + contains spaces, then it must be enclosed in quotation marks. For an + example of a command string, see the description of the `-XX:OnError` + option. + +`-XX:+PrintCommandLineFlags` +: Enables printing of ergonomically selected JVM flags that appeared on the + command line. It can be useful to know the ergonomic values set by the JVM, + such as the heap space size and the selected garbage collector. By default, + this option is disabled and flags aren't printed. + +`-XX:+PreserveFramePointer` +: Selects between using the RBP register as a general purpose register + (`-XX:-PreserveFramePointer`) and using the RBP register to hold the frame + pointer of the currently executing method (`-XX:+PreserveFramePointer` . If + the frame pointer is available, then external profiling tools (for example, + Linux perf) can construct more accurate stack traces. + +`-XX:+PrintNMTStatistics` +: Enables printing of collected native memory tracking data at JVM exit when + native memory tracking is enabled (see `-XX:NativeMemoryTracking`). By + default, this option is disabled and native memory tracking data isn't + printed. + +`-XX:SharedArchiveFile=`*path* +: Specifies the path and name of the class data sharing (CDS) archive file + + See [Application Class Data Sharing]. + +`-XX:+VerifySharedSpaces` +: If this option is specified, the JVM will load a CDS archive file only if it + passes an integrity check based on CRC32 checksums. The purpose of this flag is + to check for unintentional damage to CDS archive files in transmission or storage. + To guarantee the security and proper operation of CDS, the user must + ensure that the CDS archive files used by Java applications cannot be modified without + proper authorization. + +`-XX:SharedArchiveConfigFile=`*shared\_config\_file* +: Specifies additional shared data added to the archive file. + +`-XX:SharedClassListFile=`*file\_name* +: Specifies the text file that contains the names of the classes to store in + the class data sharing (CDS) archive. This file contains the full name of + one class per line, except slashes (`/`) replace dots (`.`). For example, + to specify the classes `java.lang.Object` and `hello.Main`, create a text + file that contains the following two lines: + + ``` + java/lang/Object + hello/Main + ``` + + The classes that you specify in this text file should include the classes + that are commonly used by the application. They may include any classes + from the application, extension, or bootstrap class paths. + + See [Application Class Data Sharing]. + +`-XX:+ShowCodeDetailsInExceptionMessages` +: Enables printing of improved `NullPointerException` messages. When an application throws a + `NullPointerException`, the option enables the JVM to analyze the program's bytecode + instructions to determine precisely which reference is `null`, + and describes the source with a null-detail message. + The null-detail message is calculated and returned by `NullPointerException.getMessage()`, + and will be printed as the exception message along with + the method, filename, and line number. By default, this option is enabled. + +`-XX:+ShowMessageBoxOnError` +: Enables the display of a dialog box when the JVM experiences an + irrecoverable error. This prevents the JVM from exiting and keeps the + process active so that you can attach a debugger to it to investigate the + cause of the error. By default, this option is disabled. + +`-XX:StartFlightRecording:`*parameter*`=`*value* +: Starts a JFR recording for the Java application. This option is equivalent + to the `JFR.start` diagnostic command that starts a recording during + runtime. `-XX:StartFlightRecording:help` prints available options and + example command lines. You can set the following *parameter*`=`*value* + entries when starting a JFR recording: + + `delay=`*time* + : Specifies the delay between the Java application launch time and the + start of the recording. Append `s` to specify the time in seconds, `m` + for minutes, `h` for hours, or `d` for days (for example, specifying + `10m` means 10 minutes). By default, there's no delay, and this + parameter is set to 0. + + `disk=`{`true`\|`false`} + : Specifies whether to write data to disk while recording. By default, + this parameter is enabled. + + `dumponexit=`{`true`\|`false`} + : Specifies if the running recording is dumped when the JVM shuts down. + If enabled and a `filename` is not entered, the recording is written to + a file in the directory where the process was started. The file name is + a system-generated name that contains the process ID, recording ID, and + current timestamp, similar to + `hotspot-pid-47496-id-1-2018_01_25_19_10_41.jfr`. By default, this + parameter is disabled. + + `duration=`*time* + : Specifies the duration of the recording. Append `s` to specify the time + in seconds, `m` for minutes, `h` for hours, or `d` for days (for + example, specifying `5h` means 5 hours). By default, the duration isn't + limited, and this parameter is set to 0. + + `filename=`*path* + : Specifies the path and name of the file to which the recording is + written when the recording is stopped, for example: + + - `recording.jfr` + - `/home/user/recordings/recording.jfr` + - `c:\recordings\recording.jfr` + + If %p and/or %t is specified in the filename, it expands to the JVM's + PID and the current timestamp, respectively. The filename may also be + a directory in which case, the filename is generated from the PID + and the current date in the specified directory. + + `name=`*identifier* + : Takes both the name and the identifier of a recording. + + `maxage=`*time* + : Specifies the maximum age of disk data to keep for the recording. This + parameter is valid only when the `disk` parameter is set to `true`. + Append `s` to specify the time in seconds, `m` for minutes, `h` for + hours, or `d` for days (for example, specifying `30s` means 30 + seconds). By default, the maximum age isn't limited, and this parameter + is set to `0s`. + + `maxsize=`*size* + : Specifies the maximum size (in bytes) of disk data to keep for the + recording. This parameter is valid only when the `disk` parameter is + set to `true`. The value must not be less than the value for the + `maxchunksize` parameter set with `-XX:FlightRecorderOptions`. Append + `m` or `M` to specify the size in megabytes, or `g` or `G` to specify + the size in gigabytes. By default, the maximum size of disk data isn't + limited, and this parameter is set to `0`. + + `path-to-gc-roots=`{`true`\|`false`} + : Specifies whether to collect the path to garbage collection (GC) roots + at the end of a recording. By default, this parameter is disabled. + + The path to GC roots is useful for finding memory leaks, but collecting + it is time-consuming. Enable this option only when you start a + recording for an application that you suspect has a memory leak. If the + `settings` parameter is set to `profile`, the stack trace from where + the potential leaking object was allocated is included in the + information collected. + + `settings=`*path* + : Specifies the path and name of the event settings file (of type JFC). + By default, the `default.jfc` file is used, which is located in + `JAVA_HOME/lib/jfr`. This default settings file collects a predefined + set of information with low overhead, so it has minimal impact on + performance and can be used with recordings that run continuously. + + A second settings file is also provided, profile.jfc, which provides + more data than the default configuration, but can have more overhead + and impact performance. Use this configuration for short periods of + time when more information is needed. + + You can specify values for multiple parameters by separating them with a + comma. Event settings and .jfc options can be specified using the + following syntax: + + `option=`*value* + : Specifies the option value to modify. To list available options, use + the `JAVA_HOME`/bin/jfr tool. + + `event-setting=`*value* + : Specifies the event setting value to modify. Use the form: + `#=`. + To add a new event setting, prefix the event name with '+'. + + You can specify values for multiple event settings and .jfc options by + separating them with a comma. In case of a conflict between a parameter + and a .jfc option, the parameter will take precedence. The whitespace + delimiter can be omitted for timespan values, i.e. 20ms. For more + information about the settings syntax, see Javadoc of the jdk.jfr + package. + + To only see warnings and errors from JFR during startup set + -Xlog:jfr+startup=warning. + +`-XX:ThreadStackSize=`*size* +: Sets the Java thread stack size (in kilobytes). Use of a scaling suffix, + such as `k`, results in the scaling of the kilobytes value so that + `-XX:ThreadStackSize=1k` sets the Java thread stack size to 1024\*1024 + bytes or 1 megabyte. The default value depends on the platform. For example: + + - Linux/x64: 1024 KB + + - Linux/Aarch64: 2048 KB + + - macOS/x64: 1024 KB + + - macOS/Aarch64: 2048 KB + + - Windows: The default value depends on virtual memory + + The following examples show how to set the thread stack size to 1 megabyte + in different units: + + ``` + -XX:ThreadStackSize=1k + -XX:ThreadStackSize=1024 + ``` + + This option is similar to `-Xss`. + +`-XX:-UseCompressedOops` +: Disables the use of compressed pointers. By default, this option is + enabled, and compressed pointers are used. This will automatically limit + the maximum ergonomically determined Java heap size to the maximum amount + of memory that can be covered by compressed pointers. By default this range + is 32 GB. + + With compressed oops enabled, object references are represented + as 32-bit offsets instead of 64-bit pointers, which typically increases + performance when running the application with Java heap sizes smaller than + the compressed oops pointer range. This option works only for 64-bit JVMs. + + It's possible to use compressed pointers with Java heap sizes greater than + 32 GB. See the `-XX:ObjectAlignmentInBytes` option. + +`-XX:-UseContainerSupport` +: **Linux only:** The VM now provides automatic container detection support, which allows the + VM to determine the amount of memory and number of processors that are + available to a Java process running in docker containers. It uses this + information to allocate system resources. The default for this flag is `true`, + and container support is enabled by default. It can be disabled + with `-XX:-UseContainerSupport`. + + Unified Logging is available to help to diagnose issues related to this + support. + + Use `-Xlog:os+container=trace` for maximum logging of container + information. See [Enable Logging with the JVM Unified Logging Framework] + for a description of using Unified Logging. + +`-XX:+UseLargePages` +: Enables the use of large page memory. By default, this option is disabled + and large page memory isn't used. + + See [Large Pages]. + +`-XX:+UseTransparentHugePages` +: **Linux only:** Enables the use of large pages that can dynamically grow or + shrink. This option is disabled by default. You may encounter performance + problems with transparent huge pages as the OS moves other pages around to + create huge pages; this option is made available for experimentation. + +`-XX:+AllowUserSignalHandlers` +: **Non-Windows:** Enables installation of signal handlers by the application. By default, + this option is disabled and the application isn't allowed to install signal + handlers. + +`-XX:VMOptionsFile=`*filename* +: Allows user to specify VM options in a file, for example, + `java -XX:VMOptionsFile=/var/my_vm_options HelloWorld`. + +`-XX:UseBranchProtection=`*mode* +: **Linux AArch64 only:** Specifies the branch protection mode. + All options other than + `none` require the VM to have been built with branch protection + enabled. In addition, for full protection, any native libraries + provided by applications should be compiled with the same level + of protection. + + Possible *mode* arguments for this option include the following: + + `none` + : Do not use branch protection. This is the default value. + + `standard` + : Enables all branch protection modes available on the current platform. + + `pac-ret` + : Enables protection against ROP based attacks. (AArch64 8.3+ only) + +## Advanced JIT Compiler Options for java + +These `java` options control the dynamic just-in-time (JIT) compilation +performed by the Java HotSpot VM. + +`-XX:AllocateInstancePrefetchLines=`*lines* +: Sets the number of lines to prefetch ahead of the instance allocation + pointer. By default, the number of lines to prefetch is set to 1: + + > `-XX:AllocateInstancePrefetchLines=1` + + +`-XX:AllocatePrefetchDistance=`*size* +: Sets the size (in bytes) of the prefetch distance for object allocation. + Memory about to be written with the value of new objects is prefetched up + to this distance starting from the address of the last allocated object. + Each Java thread has its own allocation point. + + Negative values denote that prefetch distance is chosen based on the + platform. Positive values are bytes to prefetch. Append the letter `k` or + `K` to indicate kilobytes, `m` or `M` to indicate megabytes, or `g` or `G` + to indicate gigabytes. The default value is set to -1. + + The following example shows how to set the prefetch distance to 1024 bytes: + + > `-XX:AllocatePrefetchDistance=1024` + + +`-XX:AllocatePrefetchInstr=`*instruction* +: Sets the prefetch instruction to prefetch ahead of the allocation pointer. + Possible values are from 0 to 3. The actual instructions behind the values + depend on the platform. By default, the prefetch instruction is set to 0: + + > `-XX:AllocatePrefetchInstr=0` + + +`-XX:AllocatePrefetchLines=`*lines* +: Sets the number of cache lines to load after the last object allocation by + using the prefetch instructions generated in compiled code. The default + value is 1 if the last allocated object was an instance, and 3 if it was an + array. + + The following example shows how to set the number of loaded cache lines to + 5: + + > `-XX:AllocatePrefetchLines=5` + + +`-XX:AllocatePrefetchStepSize=`*size* +: Sets the step size (in bytes) for sequential prefetch instructions. Append + the letter `k` or `K` to indicate kilobytes, `m` or `M` to indicate + megabytes, `g` or `G` to indicate gigabytes. By default, the step size is + set to 16 bytes: + + > `-XX:AllocatePrefetchStepSize=16` + + +`-XX:AllocatePrefetchStyle=`*style* +: Sets the generated code style for prefetch instructions. The *style* + argument is an integer from 0 to 3: + + `0` + : Don't generate prefetch instructions. + + `1` + : Execute prefetch instructions after each allocation. This is the + default setting. + + `2` + : Use the thread-local allocation block (TLAB) watermark pointer to + determine when prefetch instructions are executed. + + `3` + : Generate one prefetch instruction per cache line. + + +`-XX:+BackgroundCompilation` +: Enables background compilation. This option is enabled by default. To + disable background compilation, specify `-XX:-BackgroundCompilation` (this + is equivalent to specifying `-Xbatch`). + +`-XX:CICompilerCount=`*threads* +: Sets the number of compiler threads to use for compilation. + By default, the number of compiler threads is selected automatically + depending on the number of CPUs and memory available for compiled code. + The following example shows how to set the number of threads to 2: + + > `-XX:CICompilerCount=2` + +`-XX:+UseDynamicNumberOfCompilerThreads` +: Dynamically create compiler thread up to the limit specified by `-XX:CICompilerCount`. + This option is enabled by default. + +`-XX:CompileCommand=`*command*`,`*method*\[`,`*option*\] +: Specifies a *command* to perform on a *method*. For example, to exclude the + `indexOf()` method of the `String` class from being compiled, use the + following: + + > `-XX:CompileCommand=exclude,java/lang/String.indexOf` + + Note that the full class name is specified, including all packages and + subpackages separated by a slash (`/`). For easier cut-and-paste + operations, it's also possible to use the method name format produced by + the `-XX:+PrintCompilation` and `-XX:+LogCompilation` options: + + > `-XX:CompileCommand=exclude,java.lang.String::indexOf` + + If the method is specified without the signature, then the command is + applied to all methods with the specified name. However, you can also + specify the signature of the method in the class file format. In this case, + you should enclose the arguments in quotation marks, because otherwise the + shell treats the semicolon as a command end. For example, if you want to + exclude only the `indexOf(String)` method of the `String` class from being + compiled, use the following: + + > `-XX:CompileCommand="exclude,java/lang/String.indexOf,(Ljava/lang/String;)I"` + + You can also use the asterisk (\*) as a wildcard for class and method + names. For example, to exclude all `indexOf()` methods in all classes from + being compiled, use the following: + + > `-XX:CompileCommand=exclude,*.indexOf` + + The commas and periods are aliases for spaces, making it easier to pass + compiler commands through a shell. You can pass arguments to + `-XX:CompileCommand` using spaces as separators by enclosing the argument + in quotation marks: + + > `-XX:CompileCommand="exclude java/lang/String indexOf"` + + Note that after parsing the commands passed on the command line using the + `-XX:CompileCommand` options, the JIT compiler then reads commands from the + `.hotspot_compiler` file. You can add commands to this file or specify a + different file using the `-XX:CompileCommandFile` option. + + To add several commands, either specify the `-XX:CompileCommand` option + multiple times, or separate each argument with the new line separator + (`\n`). The following commands are available: + + `break` + : Sets a breakpoint when debugging the JVM to stop at the beginning of + compilation of the specified method. + + `compileonly` + : Excludes all methods from compilation except for the specified method. + As an alternative, you can use the `-XX:CompileOnly` option, which lets + you specify several methods. + + `dontinline` + : Prevents inlining of the specified method. + + `exclude` + : Excludes the specified method from compilation. + + `help` + : Prints a help message for the `-XX:CompileCommand` option. + + `inline` + : Attempts to inline the specified method. + + `log` + : Excludes compilation logging (with the `-XX:+LogCompilation` option) + for all methods except for the specified method. By default, logging is + performed for all compiled methods. + + `option` + : Passes a JIT compilation option to the specified method in place of the + last argument (`option`). The compilation option is set at the end, + after the method name. For example, to enable the + `BlockLayoutByFrequency` option for the `append()` method of the + `StringBuffer` class, use the following: + + > `-XX:CompileCommand=option,java/lang/StringBuffer.append,BlockLayoutByFrequency` + + You can specify multiple compilation options, separated by commas or + spaces. + + `print` + : Prints generated assembler code after compilation of the specified + method. + + `quiet` + : Instructs not to print the compile commands. By default, the commands + that you specify with the `-XX:CompileCommand` option are printed; for + example, if you exclude from compilation the `indexOf()` method of the + `String` class, then the following is printed to standard output: + + > `CompilerOracle: exclude java/lang/String.indexOf` + + You can suppress this by specifying the `-XX:CompileCommand=quiet` + option before other `-XX:CompileCommand` options. + +`-XX:CompileCommandFile=`*filename* +: Sets the file from which JIT compiler commands are read. By default, the + `.hotspot_compiler` file is used to store commands performed by the JIT + compiler. + + Each line in the command file represents a command, a class name, and a + method name for which the command is used. For example, this line prints + assembly code for the `toString()` method of the `String` class: + + > `print java/lang/String toString` + + If you're using commands for the JIT compiler to perform on methods, then + see the `-XX:CompileCommand` option. + +`-XX:CompilerDirectivesFile=`*file* +: Adds directives from a file to the directives stack when a program starts. + See [Compiler Control](https://docs.oracle.com/en/java/javase/12/vm/compiler-control1.html#GUID-94AD8194-786A-4F19-BFFF-278F8E237F3A). + + The `-XX:CompilerDirectivesFile` option has to be used together with the + `-XX:UnlockDiagnosticVMOptions` option that unlocks diagnostic JVM options. + + +`-XX:+CompilerDirectivesPrint` +: Prints the directives stack when the program starts or when a new directive + is added. + + The `-XX:+CompilerDirectivesPrint` option has to be used together with the + `-XX:UnlockDiagnosticVMOptions` option that unlocks diagnostic JVM options. + +`-XX:CompileOnly=`*methods* +: Sets the list of methods (separated by commas) to which compilation should + be restricted. Only the specified methods are compiled. + + `-XX:CompileOnly=method1,method2,...,methodN` is an alias for: + ``` + -XX:CompileCommand=compileonly,method1 + -XX:CompileCommand=compileonly,method2 + ... + -XX:CompileCommand=compileonly,methodN + ``` + +`-XX:CompileThresholdScaling=`*scale* +: Provides unified control of first compilation. This option controls when + methods are first compiled for both the tiered and the nontiered modes of + operation. The `CompileThresholdScaling` option has a floating point value + between 0 and +Inf and scales the thresholds corresponding to the current + mode of operation (both tiered and nontiered). Setting + `CompileThresholdScaling` to a value less than 1.0 results in earlier + compilation while values greater than 1.0 delay compilation. Setting + `CompileThresholdScaling` to 0 is equivalent to disabling compilation. + +`-XX:+DoEscapeAnalysis` +: Enables the use of escape analysis. This option is enabled by default. To + disable the use of escape analysis, specify `-XX:-DoEscapeAnalysis`. + +`-XX:InitialCodeCacheSize=`*size* +: Sets the initial code cache size (in bytes). Append the letter `k` or `K` + to indicate kilobytes, `m` or `M` to indicate megabytes, or `g` or `G` to + indicate gigabytes. The default value depends on the platform. The initial code + cache size shouldn't be less than the system's minimal memory page size. + The following example shows how to set the initial code cache size to 32 + KB: + + > `-XX:InitialCodeCacheSize=32k` + +`-XX:+Inline` +: Enables method inlining. This option is enabled by default to increase + performance. To disable method inlining, specify `-XX:-Inline`. + +`-XX:InlineSmallCode=`*size* +: Sets the maximum code size (in bytes) for already compiled methods + that may be inlined. This flag only applies to the C2 compiler. + Append the letter `k` or `K` to indicate kilobytes, + `m` or `M` to indicate megabytes, or `g` or `G` to indicate gigabytes. + The default value depends on the platform and on whether tiered compilation + is enabled. In the following example it is set to 1000 bytes: + + > `-XX:InlineSmallCode=1000` + +`-XX:+LogCompilation` +: Enables logging of compilation activity to a file named `hotspot.log` in + the current working directory. You can specify a different log file path + and name using the `-XX:LogFile` option. + + By default, this option is disabled and compilation activity isn't logged. + The `-XX:+LogCompilation` option has to be used together with the + `-XX:UnlockDiagnosticVMOptions` option that unlocks diagnostic JVM options. + + You can enable verbose diagnostic output with a message printed to the + console every time a method is compiled by using the + `-XX:+PrintCompilation` option. + + +`-XX:FreqInlineSize=`*size* +: Sets the maximum bytecode size (in bytes) of a hot method to be inlined. + This flag only applies to the C2 compiler. Append + the letter `k` or `K` to indicate kilobytes, `m` or `M` to indicate + megabytes, or `g` or `G` to indicate gigabytes. The default value depends + on the platform. In the following example it is set to 325 bytes: + + > `-XX:FreqInlineSize=325` + + +`-XX:MaxInlineSize=`*size* +: Sets the maximum bytecode size (in bytes) of a cold method to be inlined. + This flag only applies to the C2 compiler. + Append the letter `k` or `K` to indicate kilobytes, `m` or `M` to indicate + megabytes, or `g` or `G` to indicate gigabytes. By default, the maximum + bytecode size is set to 35 bytes: + + > `-XX:MaxInlineSize=35` + +`-XX:C1MaxInlineSize=`*size* +: Sets the maximum bytecode size (in bytes) of a cold method to be inlined. + This flag only applies to the C1 compiler. + Append the letter `k` or `K` to indicate kilobytes, `m` or `M` to indicate + megabytes, or `g` or `G` to indicate gigabytes. By default, the maximum + bytecode size is set to 35 bytes: + + > `-XX:MaxInlineSize=35` + +`-XX:MaxTrivialSize=`*size* +: Sets the maximum bytecode size (in bytes) of a trivial method to be + inlined. This flag only applies to the C2 compiler. + Append the letter `k` or `K` to indicate kilobytes, `m` or `M` to + indicate megabytes, or `g` or `G` to indicate gigabytes. By default, the + maximum bytecode size of a trivial method is set to 6 bytes: + + > `-XX:MaxTrivialSize=6` + +`-XX:C1MaxTrivialSize=`*size* +: Sets the maximum bytecode size (in bytes) of a trivial method to be + inlined. This flag only applies to the C1 compiler. + Append the letter `k` or `K` to indicate kilobytes, `m` or `M` to + indicate megabytes, or `g` or `G` to indicate gigabytes. By default, the + maximum bytecode size of a trivial method is set to 6 bytes: + + > `-XX:MaxTrivialSize=6` + +`-XX:MaxNodeLimit=`*nodes* +: Sets the maximum number of nodes to be used during single method + compilation. By default the value depends on the features enabled. + In the following example the maximum number of nodes is set to 100,000: + + > `-XX:MaxNodeLimit=100000` + +`-XX:NonNMethodCodeHeapSize=`*size* +: Sets the size in bytes of the code segment containing nonmethod code. + + A nonmethod code segment containing nonmethod code, such as compiler + buffers and the bytecode interpreter. This code type stays in the code + cache forever. This flag is used only if `-XX:SegmentedCodeCache` is + enabled. + +`-XX:NonProfiledCodeHeapSize=`*size* +: Sets the size in bytes of the code segment containing nonprofiled methods. + This flag is used only if `-XX:SegmentedCodeCache` is enabled. + +`-XX:+OptimizeStringConcat` +: Enables the optimization of `String` concatenation operations. This option + is enabled by default. To disable the optimization of `String` + concatenation operations, specify `-XX:-OptimizeStringConcat`. + +`-XX:+PrintAssembly` +: Enables printing of assembly code for bytecoded and native methods by using + the external `hsdis-.so` or `.dll` library. For 64-bit VM on Windows, + it's `hsdis-amd64.dll`. This lets you to see the generated code, which may + help you to diagnose performance issues. + + By default, this option is disabled and assembly code isn't printed. The + `-XX:+PrintAssembly` option has to be used together with the + `-XX:UnlockDiagnosticVMOptions` option that unlocks diagnostic JVM options. + +`-XX:ProfiledCodeHeapSize=`*size* +: Sets the size in bytes of the code segment containing profiled methods. + This flag is used only if `-XX:SegmentedCodeCache` is enabled. + +`-XX:+PrintCompilation` +: Enables verbose diagnostic output from the JVM by printing a message to the + console every time a method is compiled. This lets you to see which methods + actually get compiled. By default, this option is disabled and diagnostic + output isn't printed. + + You can also log compilation activity to a file by using the + `-XX:+LogCompilation` option. + +`-XX:+PrintInlining` +: Enables printing of inlining decisions. This let's you see which methods + are getting inlined. + + By default, this option is disabled and inlining information isn't printed. + The `-XX:+PrintInlining` option has to be used together with the + `-XX:+UnlockDiagnosticVMOptions` option that unlocks diagnostic JVM + options. + +`-XX:ReservedCodeCacheSize=`*size* +: Sets the maximum code cache size (in bytes) for JIT-compiled code. Append + the letter `k` or `K` to indicate kilobytes, `m` or `M` to indicate + megabytes, or `g` or `G` to indicate gigabytes. The default maximum code + cache size is 240 MB; if you disable tiered compilation with the option + `-XX:-TieredCompilation`, then the default size is 48 MB. This option has a + limit of 2 GB; otherwise, an error is generated. The maximum code cache + size shouldn't be less than the initial code cache size; see the option + `-XX:InitialCodeCacheSize`. + +`-XX:+SegmentedCodeCache` +: Enables segmentation of the code cache, without which the code cache + consists of one large segment. With `-XX:+SegmentedCodeCache`, separate + segments will be used for non-method, profiled method, and non-profiled + method code. The segments are not resized at runtime. The advantages are + better control of the memory footprint, reduced code fragmentation, and + better CPU iTLB (instruction translation lookaside buffer) and instruction + cache behavior due to improved locality. + + The feature is enabled by default if tiered compilation is enabled + (`-XX:+TieredCompilation` ) and the reserved code cache size + (`-XX:ReservedCodeCacheSize`) is at least 240 MB. + +`-XX:StartAggressiveSweepingAt=`*percent* +: Forces stack scanning of active methods to aggressively remove unused code + when only the given percentage of the code cache is free. The default value + is 10%. + +`-XX:-TieredCompilation` +: Disables the use of tiered compilation. By default, this option is enabled. + +`-XX:UseSSE=`*version* +: Enables the use of SSE instruction set of a specified version. + Is set by default to the highest supported version available (x86 only). + +`-XX:UseAVX=`*version* +: Enables the use of AVX instruction set of a specified version. + Is set by default to the highest supported version available (x86 only). + +`-XX:+UseAES` +: Enables hardware-based AES intrinsics for hardware that supports it. + This option is on by default on hardware that has the necessary instructions. + The `-XX:+UseAES` is used in conjunction with `UseAESIntrinsics`. Flags + that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseAESIntrinsics` +: Enables AES intrinsics. Specifying `-XX:+UseAESIntrinsics` is equivalent to + also enabling `-XX:+UseAES`. To disable hardware-based AES intrinsics, + specify `-XX:-UseAES -XX:-UseAESIntrinsics`. For example, to enable hardware + AES, use the following flags: + + > `-XX:+UseAES -XX:+UseAESIntrinsics` + + Flags that control intrinsics now require the option + `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseAESCTRIntrinsics` +: Analogous to `-XX:+UseAESIntrinsics` enables AES/CTR intrinsics. + +`-XX:+UseGHASHIntrinsics` +: Controls the use of GHASH intrinsics. Enabled by default on platforms that + support the corresponding instructions. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseChaCha20Intrinsics` +: Enable ChaCha20 intrinsics. This option is on by default for supported + platforms. To disable ChaCha20 intrinsics, specify + `-XX:-UseChaCha20Intrinsics`. Flags that control intrinsics now require + the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UsePoly1305Intrinsics` +: Enable Poly1305 intrinsics. This option is on by default for supported + platforms. To disable Poly1305 intrinsics, specify + `-XX:-UsePoly1305Intrinsics`. Flags that control intrinsics now require + the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseBASE64Intrinsics` +: Controls the use of accelerated BASE64 encoding routines for `java.util.Base64`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseAdler32Intrinsics` +: Controls the use of Adler32 checksum algorithm intrinsic for `java.util.zip.Adler32`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseCRC32Intrinsics` +: Controls the use of CRC32 intrinsics for `java.util.zip.CRC32`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseCRC32CIntrinsics` +: Controls the use of CRC32C intrinsics for `java.util.zip.CRC32C`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseSHA` +: Enables hardware-based intrinsics for SHA crypto hash functions for some + hardware. The `UseSHA` option is used in conjunction with the + `UseSHA1Intrinsics`, `UseSHA256Intrinsics`, and `UseSHA512Intrinsics` + options. + + The `UseSHA` and `UseSHA*Intrinsics` flags are enabled by default on + machines that support the corresponding instructions. + + This feature is applicable only when using the `sun.security.provider.Sun` + provider for SHA operations. Flags that control intrinsics now require the + option `-XX:+UnlockDiagnosticVMOptions`. + + To disable all hardware-based SHA intrinsics, specify the `-XX:-UseSHA`. To + disable only a particular SHA intrinsic, use the appropriate corresponding + option. For example: `-XX:-UseSHA256Intrinsics`. + +`-XX:+UseSHA1Intrinsics` +: Enables intrinsics for SHA-1 crypto hash function. Flags that control + intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseSHA256Intrinsics` +: Enables intrinsics for SHA-224 and SHA-256 crypto hash functions. Flags + that control intrinsics now require the option + `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseSHA512Intrinsics` +: Enables intrinsics for SHA-384 and SHA-512 crypto hash functions. Flags + that control intrinsics now require the option + `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseMathExactIntrinsics` +: Enables intrinsification of various `java.lang.Math.*Exact()` functions. + Enabled by default. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseMultiplyToLenIntrinsic` +: Enables intrinsification of `BigInteger.multiplyToLen()`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +-XX:+UseSquareToLenIntrinsic +: Enables intrinsification of `BigInteger.squareToLen()`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +-XX:+UseMulAddIntrinsic +: Enables intrinsification of `BigInteger.mulAdd()`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +-XX:+UseMontgomeryMultiplyIntrinsic +: Enables intrinsification of `BigInteger.montgomeryMultiply()`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +-XX:+UseMontgomerySquareIntrinsic +: Enables intrinsification of `BigInteger.montgomerySquare()`. + Enabled by default on platforms that support it. + Flags that control intrinsics now require the option `-XX:+UnlockDiagnosticVMOptions`. + +`-XX:+UseCMoveUnconditionally` +: Generates CMove (scalar and vector) instructions regardless of + profitability analysis. + +`-XX:+UseCodeCacheFlushing` +: Enables flushing of the code cache before shutting down the compiler. This + option is enabled by default. To disable flushing of the code cache before + shutting down the compiler, specify `-XX:-UseCodeCacheFlushing`. + +`-XX:+UseCondCardMark` +: Enables checking if the card is already marked before updating the card + table. This option is disabled by default. It should be used only on + machines with multiple sockets, where it increases the performance of Java + applications that rely on concurrent operations. + +`-XX:+UseCountedLoopSafepoints` +: Keeps safepoints in counted loops. Its default value depends on whether the + selected garbage collector requires low latency safepoints. + +`-XX:LoopStripMiningIter=`*number_of_iterations* +: Controls the number of iterations in the inner strip mined loop. Strip mining + transforms counted loops into two level nested loops. Safepoints are kept + in the outer loop while the inner loop can execute at full speed. This option + controls the maximum number of iterations in the inner loop. The default value + is 1,000. + +`-XX:LoopStripMiningIterShortLoop=`*number_of_iterations* +: Controls loop strip mining optimization. Loops with the number of iterations + less than specified will not have safepoints in them. Default value is + 1/10th of `-XX:LoopStripMiningIter`. + +`-XX:+UseFMA` +: Enables hardware-based FMA intrinsics for hardware where FMA instructions + are available (such as, Intel and ARM64). FMA intrinsics are + generated for the `java.lang.Math.fma(`*a*`,` *b*`,` *c*`)` methods that + calculate the value of `(` *a* `*` *b* `+` *c* `)` expressions. + +`-XX:+UseSuperWord` +: Enables the transformation of scalar operations into superword operations. + Superword is a vectorization optimization. This option is enabled by + default. To disable the transformation of scalar operations into superword + operations, specify `-XX:-UseSuperWord`. + +## Advanced Serviceability Options for Java + +These `java` options provide the ability to gather system information and +perform extensive debugging. + +`-XX:+DisableAttachMechanism` +: Disables the mechanism that lets tools attach to the JVM. By default, this + option is disabled, meaning that the attach mechanism is enabled and you + can use diagnostics and troubleshooting tools such as `jcmd`, `jstack`, + `jmap`, and `jinfo`. + + > **Note:** The tools such as [jcmd](jcmd.html), [jinfo](jinfo.html), + [jmap](jmap.html), and [jstack](jstack.html) shipped with the JDK aren't + supported when using the tools from one JDK version to troubleshoot a + different JDK version. + +`-XX:+DTraceAllocProbes` +: **Linux and macOS:** Enable `dtrace` tool probes for object allocation. + +`-XX:+DTraceMethodProbes` +: **Linux and macOS:** Enable `dtrace` tool probes for method-entry + and method-exit. + +`-XX:+DTraceMonitorProbes` +: **Linux and macOS:** Enable `dtrace` tool probes for monitor events. + +`-XX:+HeapDumpOnOutOfMemoryError` +: Enables the dumping of the Java heap to a file in the current directory by + using the heap profiler (HPROF) when a `java.lang.OutOfMemoryError` + exception is thrown. You can explicitly set the heap dump file path and + name using the `-XX:HeapDumpPath` option. By default, this option is + disabled and the heap isn't dumped when an `OutOfMemoryError` exception is + thrown. + +`-XX:HeapDumpPath=`*path* +: Sets the path and file name for writing the heap dump provided by the heap + profiler (HPROF) when the `-XX:+HeapDumpOnOutOfMemoryError` option is set. + By default, the file is created in the current working directory, and it's + named `java_pid.hprof` where `` is the identifier of the process + that caused the error. The following example shows how to set the default + file explicitly (`%p` represents the current process identifier): + + > `-XX:HeapDumpPath=./java_pid%p.hprof` + + - **Non-Windows:** The following example shows how to + set the heap dump file to `/var/log/java/java_heapdump.hprof`: + + > `-XX:HeapDumpPath=/var/log/java/java_heapdump.hprof` + + - **Windows:** The following example shows how to set the heap dump file + to `C:/log/java/java_heapdump.log`: + + > `-XX:HeapDumpPath=C:/log/java/java_heapdump.log` + +`-XX:LogFile=`*path* +: Sets the path and file name to where log data is written. By default, the + file is created in the current working directory, and it's named + `hotspot.log`. + + - **Non-Windows:** The following example shows how to + set the log file to `/var/log/java/hotspot.log`: + + > `-XX:LogFile=/var/log/java/hotspot.log` + + - **Windows:** The following example shows how to set the log file to + `C:/log/java/hotspot.log`: + + > `-XX:LogFile=C:/log/java/hotspot.log` + +`-XX:+PrintClassHistogram` +: Enables printing of a class instance histogram after one of the following + events: + + - **Non-Windows:** `Control+\` (`SIGQUIT`) + + - **Windows:** `Control+C` (`SIGTERM`) + + By default, this option is disabled. + + Setting this option is equivalent to running the `jmap -histo` command, or + the `jcmd` *pid* `GC.class_histogram` command, where *pid* is the current + Java process identifier. + +`-XX:+PrintConcurrentLocks` +: Enables printing of `java.util.concurrent` locks after one of the following + events: + + - **Non-Windows:** `Control+\` (`SIGQUIT`) + + - **Windows:** `Control+C` (`SIGTERM`) + + By default, this option is disabled. + + Setting this option is equivalent to running the `jstack -l` command or the + `jcmd` *pid* `Thread.print -l` command, where *pid* is the current Java + process identifier. + +`-XX:+PrintFlagsRanges` +: Prints the range specified and allows automatic testing of the values. See + [Validate Java Virtual Machine Flag + Arguments]. + +`-XX:+PerfDataSaveToFile` +: If enabled, saves [jstat](jstat.html) binary data when the Java application + exits. This binary data is saved in a file named `hsperfdata_`*pid*, where + *pid* is the process identifier of the Java application that you ran. Use + the `jstat` command to display the performance data contained in this file + as follows: + + > `jstat -class file:///`*path*`/hsperfdata_`*pid* + + > `jstat -gc file:///`*path*`/hsperfdata_`*pid* + +`-XX:+UsePerfData` +: Enables the `perfdata` feature. This option is enabled by default to allow + JVM monitoring and performance testing. Disabling it suppresses the + creation of the `hsperfdata_userid` directories. To disable the `perfdata` + feature, specify `-XX:-UsePerfData`. + +## Advanced Garbage Collection Options for Java + +These `java` options control how garbage collection (GC) is performed by the +Java HotSpot VM. + +`-XX:+AggressiveHeap` +: Enables Java heap optimization. This sets various parameters to be + optimal for long-running jobs with intensive memory allocation, based on + the configuration of the computer (RAM and CPU). By default, the option + is disabled and the heap sizes are configured less aggressively. + +`-XX:+AlwaysPreTouch` +: Requests the VM to touch every page on the Java heap after requesting it from + the operating system and before handing memory out to the application. + By default, this option is disabled and all pages are committed as the + application uses the heap space. + +`-XX:ConcGCThreads=`*threads* +: Sets the number of threads used for concurrent GC. Sets *`threads`* to + approximately 1/4 of the number of parallel garbage collection threads. The + default value depends on the number of CPUs available to the JVM. + + For example, to set the number of threads for concurrent GC to 2, specify + the following option: + + > `-XX:ConcGCThreads=2` + +`-XX:+DisableExplicitGC` +: Enables the option that disables processing of calls to the `System.gc()` + method. This option is disabled by default, meaning that calls to + `System.gc()` are processed. If processing of calls to `System.gc()` is + disabled, then the JVM still performs GC when necessary. + +`-XX:+ExplicitGCInvokesConcurrent` +: Enables invoking of concurrent GC by using the `System.gc()` request. This + option is disabled by default and can be enabled only with the `-XX:+UseG1GC` option. + +`-XX:G1AdaptiveIHOPNumInitialSamples=`*number* +: When `-XX:UseAdaptiveIHOP` is enabled, this option sets the number of + completed marking cycles used to gather samples until G1 adaptively + determines the optimum value of `-XX:InitiatingHeapOccupancyPercent`. Before, + G1 uses the value of `-XX:InitiatingHeapOccupancyPercent` directly for + this purpose. The default value is 3. + +`-XX:G1HeapRegionSize=`*size* +: Sets the size of the regions into which the Java heap is subdivided when + using the garbage-first (G1) collector. The value is a power of 2 and can + range from 1 MB to 32 MB. The default region size is determined + ergonomically based on the heap size with a goal of approximately 2048 + regions. + + The following example sets the size of the subdivisions to 16 MB: + + > `-XX:G1HeapRegionSize=16m` + +`-XX:G1HeapWastePercent=`*percent* +: Sets the percentage of heap that you're willing to waste. The Java HotSpot + VM doesn't initiate the mixed garbage collection cycle when the reclaimable + percentage is less than the heap waste percentage. The default is 5 + percent. + +`-XX:G1MaxNewSizePercent=`*percent* +: Sets the percentage of the heap size to use as the maximum for the young + generation size. The default value is 60 percent of your Java heap. + + This is an experimental flag. This setting replaces the + `-XX:DefaultMaxNewGenPercent` setting. + +`-XX:G1MixedGCCountTarget=`*number* +: Sets the target number of mixed garbage collections after a marking cycle + to collect old regions with at most `G1MixedGCLIveThresholdPercent` live + data. The default is 8 mixed garbage collections. The goal for mixed + collections is to be within this target number. + +`-XX:G1MixedGCLiveThresholdPercent=`*percent* +: Sets the occupancy threshold for an old region to be included in a mixed + garbage collection cycle. The default occupancy is 85 percent. + + This is an experimental flag. This setting replaces the + `-XX:G1OldCSetRegionLiveThresholdPercent` setting. + +`-XX:G1NewSizePercent=`*percent* +: Sets the percentage of the heap to use as the minimum for the young + generation size. The default value is 5 percent of your Java heap. + + This is an experimental flag. This setting replaces the + `-XX:DefaultMinNewGenPercent` setting. + +`-XX:G1OldCSetRegionThresholdPercent=`*percent* +: Sets an upper limit on the number of old regions to be collected during a + mixed garbage collection cycle. The default is 10 percent of the Java heap. + +`-XX:G1ReservePercent=`*percent* +: Sets the percentage of the heap (0 to 50) that's reserved as a false + ceiling to reduce the possibility of promotion failure for the G1 + collector. When you increase or decrease the percentage, ensure that you + adjust the total Java heap by the same amount. By default, this option is + set to 10%. + + The following example sets the reserved heap to 20%: + + > `-XX:G1ReservePercent=20` + +`-XX:+G1UseAdaptiveIHOP` +: Controls adaptive calculation of the old generation occupancy to start + background work preparing for an old generation collection. If enabled, + G1 uses `-XX:InitiatingHeapOccupancyPercent` for the first few times as + specified by the value of `-XX:G1AdaptiveIHOPNumInitialSamples`, and after + that adaptively calculates a new optimum value for the initiating + occupancy automatically. + Otherwise, the old generation collection process always starts at the + old generation occupancy determined by + `-XX:InitiatingHeapOccupancyPercent`. + + The default is enabled. + +`-XX:InitialHeapSize=`*size* +: Sets the initial size (in bytes) of the memory allocation pool. This value + must be either 0, or a multiple of 1024 and greater than 1 MB. Append the + letter `k` or `K` to indicate kilobytes, `m` or `M` to indicate megabytes, + or `g` or `G` to indicate gigabytes. The default value is selected at run + time based on the system configuration. + + The following examples show how to set the size of allocated memory to 6 MB + using various units: + + ``` + -XX:InitialHeapSize=6291456 + -XX:InitialHeapSize=6144k + -XX:InitialHeapSize=6m + ``` + + If you set this option to 0, then the initial size is set as the sum of the + sizes allocated for the old generation and the young generation. The size + of the heap for the young generation can be set using the `-XX:NewSize` + option. Note that the `-Xms` option sets both the minimum and the initial + heap size of the heap. If `-Xms` appears after `-XX:InitialHeapSize` on the + command line, then the initial heap size gets set to the value specified + with `-Xms`. + +`-XX:InitialRAMPercentage=`*percent* +: Sets the initial amount of memory that the JVM will use for the Java heap + before applying ergonomics heuristics as a percentage of the maximum amount + determined as described in the `-XX:MaxRAM` option. The default value is + 1.5625 percent. + + The following example shows how to set the percentage of the initial + amount of memory used for the Java heap: + + > `-XX:InitialRAMPercentage=5` + +`-XX:InitialSurvivorRatio=`*ratio* +: Sets the initial survivor space ratio used by the throughput garbage + collector (which is enabled by the `-XX:+UseParallelGC` option). Adaptive + sizing is enabled by default with the throughput garbage collector by + using the `-XX:+UseParallelGC` option, and the survivor space is resized + according to the application behavior, starting with the initial value. If + adaptive sizing is disabled (using the `-XX:-UseAdaptiveSizePolicy` + option), then the `-XX:SurvivorRatio` option should be used to set the size + of the survivor space for the entire execution of the application. + + The following formula can be used to calculate the initial size of survivor + space (S) based on the size of the young generation (Y), and the initial + survivor space ratio (R): + + > `S=Y/(R+2)` + + The 2 in the equation denotes two survivor spaces. The larger the value + specified as the initial survivor space ratio, the smaller the initial + survivor space size. + + By default, the initial survivor space ratio is set to 8. If the default + value for the young generation space size is used (2 MB), then the initial + size of the survivor space is 0.2 MB. + + The following example shows how to set the initial survivor space ratio to + 4: + + > `-XX:InitialSurvivorRatio=4` + +`-XX:InitiatingHeapOccupancyPercent=`*percent* +: Sets the percentage of the old generation occupancy (0 to 100) at which to + start the first few concurrent marking cycles for the G1 garbage collector. + + By default, the initiating value is set to 45%. A value of 0 implies + nonstop concurrent GC cycles from the beginning until G1 adaptively sets this + value. + + See also the `-XX:G1UseAdaptiveIHOP` and `-XX:G1AdaptiveIHOPNumInitialSamples` + options. + + The following example shows how to set the initiating heap occupancy to 75%: + + > `-XX:InitiatingHeapOccupancyPercent=75` + +`-XX:MaxGCPauseMillis=`*time* +: Sets a target for the maximum GC pause time (in milliseconds). This is a + soft goal, and the JVM will make its best effort to achieve it. The + specified value doesn't adapt to your heap size. By default, for G1 the + maximum pause time target is 200 milliseconds. The other generational + collectors do not use a pause time goal by default. + + The following example shows how to set the maximum target pause time to 500 + ms: + + > `-XX:MaxGCPauseMillis=500` + +`-XX:MaxHeapSize=`*size* +: Sets the maximum size (in byes) of the memory allocation pool. This value + must be a multiple of 1024 and greater than 2 MB. Append the letter `k` or + `K` to indicate kilobytes, `m` or `M` to indicate megabytes, or `g` or `G` + to indicate gigabytes. The default value is selected at run time based on + the system configuration. For server deployments, the options + `-XX:InitialHeapSize` and `-XX:MaxHeapSize` are often set to the same + value. + + The following examples show how to set the maximum allowed size of + allocated memory to 80 MB using various units: + + ``` + -XX:MaxHeapSize=83886080 + -XX:MaxHeapSize=81920k + -XX:MaxHeapSize=80m + ``` + + The `-XX:MaxHeapSize` option is equivalent to `-Xmx`. + +`-XX:MaxHeapFreeRatio=`*percent* +: Sets the maximum allowed percentage of free heap space (0 to 100) after a + GC event. If free heap space expands above this value, then the heap is + shrunk. By default, this value is set to 70%. + + Minimize the Java heap size by lowering the values of the parameters + `MaxHeapFreeRatio` (default value is 70%) and `MinHeapFreeRatio` (default + value is 40%) with the command-line options `-XX:MaxHeapFreeRatio` and + `-XX:MinHeapFreeRatio`. Lowering `MaxHeapFreeRatio` to as low as 10% and + `MinHeapFreeRatio` to 5% has successfully reduced the heap size without too + much performance regression; however, results may vary greatly depending on + your application. Try different values for these parameters until they're + as low as possible yet still retain acceptable performance. + + > `-XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=5` + + Customers trying to keep the heap small should also add the option + `-XX:-ShrinkHeapInSteps`. See [Performance Tuning Examples] for a + description of using this option to keep the Java heap small by reducing + the dynamic footprint for embedded applications. + +`-XX:MaxMetaspaceSize=`*size* +: Sets the maximum amount of native memory that can be allocated for class + metadata. By default, the size isn't limited. The amount of metadata for an + application depends on the application itself, other running applications, + and the amount of memory available on the system. + + The following example shows how to set the maximum class metadata size to + 256 MB: + + > `-XX:MaxMetaspaceSize=256m` + +`-XX:MaxNewSize=`*size* +: Sets the maximum size (in bytes) of the heap for the young generation + (nursery). The default value is set ergonomically. + +`-XX:MaxRAM=`*size* +: Sets the maximum amount of memory that the JVM may use for the Java heap + before applying ergonomics heuristics. The default value is the maximum + amount of available memory to the JVM process or 128 GB, whichever is lower. + + The maximum amount of available memory to the JVM process is the minimum + of the machine's physical memory and any constraints set by the environment + (e.g. container). + + Specifying this option disables automatic use of compressed oops if + the combined result of this and other options influencing the maximum amount + of memory is larger than the range of memory addressable by compressed oops. + See `-XX:UseCompressedOops` for further information about compressed oops. + + The following example shows how to set the maximum amount of available + memory for sizing the Java heap to 2 GB: + + > `-XX:MaxRAM=2G` + +`-XX:MaxRAMPercentage=`*percent* +: Sets the maximum amount of memory that the JVM may use for the Java heap + before applying ergonomics heuristics as a percentage of the maximum amount + determined as described in the `-XX:MaxRAM` option. The default value is 25 + percent. + + Specifying this option disables automatic use of compressed oops if + the combined result of this and other options influencing the maximum amount + of memory is larger than the range of memory addressable by compressed oops. + See `-XX:UseCompressedOops` for further information about compressed oops. + + The following example shows how to set the percentage of the maximum amount + of memory used for the Java heap: + + > `-XX:MaxRAMPercentage=75` + +`-XX:MinRAMPercentage=`*percent* +: Sets the maximum amount of memory that the JVM may use for the Java heap + before applying ergonomics heuristics as a percentage of the maximum amount + determined as described in the `-XX:MaxRAM` option for small heaps. A small + heap is a heap of approximately 125 MB. The default value is 50 percent. + + The following example shows how to set the percentage of the maximum amount + of memory used for the Java heap for small heaps: + + > `-XX:MinRAMPercentage=75` + +`-XX:MaxTenuringThreshold=`*threshold* +: Sets the maximum tenuring threshold for use in adaptive GC sizing. The + largest value is 15. The default value is 15 for the parallel (throughput) + collector. + + The following example shows how to set the maximum tenuring threshold to + 10: + + > `-XX:MaxTenuringThreshold=10` + +`-XX:MetaspaceSize=`*size* +: Sets the size of the allocated class metadata space that triggers a garbage + collection the first time it's exceeded. This threshold for a garbage + collection is increased or decreased depending on the amount of metadata + used. The default size depends on the platform. + +`-XX:MinHeapFreeRatio=`*percent* +: Sets the minimum allowed percentage of free heap space (0 to 100) after a + GC event. If free heap space falls below this value, then the heap is + expanded. By default, this value is set to 40%. + + Minimize Java heap size by lowering the values of the parameters + `MaxHeapFreeRatio` (default value is 70%) and `MinHeapFreeRatio` (default + value is 40%) with the command-line options `-XX:MaxHeapFreeRatio` and + `-XX:MinHeapFreeRatio`. Lowering `MaxHeapFreeRatio` to as low as 10% and + `MinHeapFreeRatio` to 5% has successfully reduced the heap size without too + much performance regression; however, results may vary greatly depending on + your application. Try different values for these parameters until they're + as low as possible, yet still retain acceptable performance. + + > `-XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=5` + + Customers trying to keep the heap small should also add the option + `-XX:-ShrinkHeapInSteps`. See [Performance Tuning Examples] for a + description of using this option to keep the Java heap small by reducing + the dynamic footprint for embedded applications. + +`-XX:MinHeapSize=`*size* +: Sets the minimum size (in bytes) of the memory allocation pool. This value + must be either 0, or a multiple of 1024 and greater than 1 MB. Append the + letter `k` or `K` to indicate kilobytes, `m` or `M` to indicate megabytes, + or `g` or `G` to indicate gigabytes. The default value is selected at run + time based on the system configuration. + + The following examples show how to set the minimum size of allocated memory + to 6 MB using various units: + + ``` + -XX:MinHeapSize=6291456 + -XX:MinHeapSize=6144k + -XX:MinHeapSize=6m + ``` + + If you set this option to 0, then the minimum size is set to the same value + as the initial size. + +`-XX:NewRatio=`*ratio* +: Sets the ratio between young and old generation sizes. By default, this + option is set to 2. The following example shows how to set the young-to-old + ratio to 1: + + > `-XX:NewRatio=1` + +`-XX:NewSize=`*size* +: Sets the initial size (in bytes) of the heap for the young generation + (nursery). Append the letter `k` or `K` to indicate kilobytes, `m` or `M` + to indicate megabytes, or `g` or `G` to indicate gigabytes. + + The young generation region of the heap is used for new objects. GC is + performed in this region more often than in other regions. If the size for + the young generation is too low, then a large number of minor GCs are + performed. If the size is too high, then only full GCs are performed, which + can take a long time to complete. It is recommended that you keep the size + for the young generation greater than 25% and less than 50% of the overall + heap size. + + The following examples show how to set the initial size of the young + generation to 256 MB using various units: + + ``` + -XX:NewSize=256m + -XX:NewSize=262144k + -XX:NewSize=268435456 + ``` + + The `-XX:NewSize` option is equivalent to `-Xmn`. + +`-XX:ParallelGCThreads=`*threads* +: Sets the number of the stop-the-world (STW) worker threads. The default value + depends on the number of CPUs available to the JVM and the garbage collector + selected. + + For example, to set the number of threads for G1 GC to 2, specify the + following option: + + > `-XX:ParallelGCThreads=2` + +`-XX:+ParallelRefProcEnabled` +: Enables parallel reference processing. By default, this option is disabled. + +`-XX:+PrintAdaptiveSizePolicy` +: Enables printing of information about adaptive-generation sizing. By + default, this option is disabled. + +`-XX:SoftRefLRUPolicyMSPerMB=`*time* +: Sets the amount of time (in milliseconds) a softly reachable object is + kept active on the heap after the last time it was referenced. The default + value is one second of lifetime per free megabyte in the heap. The + `-XX:SoftRefLRUPolicyMSPerMB` option accepts integer values representing + milliseconds per one megabyte of the current heap size (for Java HotSpot + Client VM) or the maximum possible heap size (for Java HotSpot Server VM). + This difference means that the Client VM tends to flush soft references + rather than grow the heap, whereas the Server VM tends to grow the heap + rather than flush soft references. In the latter case, the value of the + `-Xmx` option has a significant effect on how quickly soft references are + garbage collected. + + The following example shows how to set the value to 2.5 seconds: + + `-XX:SoftRefLRUPolicyMSPerMB=2500` + +`-XX:-ShrinkHeapInSteps` +: Incrementally reduces the Java heap to the target size, specified by the + option `-XX:MaxHeapFreeRatio`. This option is enabled by default. If + disabled, then it immediately reduces the Java heap to the target size + instead of requiring multiple garbage collection cycles. Disable this + option if you want to minimize the Java heap size. You will likely + encounter performance degradation when this option is disabled. + + See [Performance Tuning Examples] for a description of using the + `MaxHeapFreeRatio` option to keep the Java heap small by reducing the + dynamic footprint for embedded applications. + +`-XX:StringDeduplicationAgeThreshold=`*threshold* +: Identifies `String` objects reaching the specified age that are considered + candidates for deduplication. An object's age is a measure of how many + times it has survived garbage collection. This is sometimes referred to as + tenuring. + + > **Note:** `String` objects that are promoted to an old heap region before this age + has been reached are always considered candidates for deduplication. The + default value for this option is `3`. See the `-XX:+UseStringDeduplication` + option. + +`-XX:SurvivorRatio=`*ratio* +: Sets the ratio between eden space size and survivor space size. By default, + this option is set to 8. The following example shows how to set the + eden/survivor space ratio to 4: + + > `-XX:SurvivorRatio=4` + +`-XX:TargetSurvivorRatio=`*percent* +: Sets the desired percentage of survivor space (0 to 100) used after young + garbage collection. By default, this option is set to 50%. + + The following example shows how to set the target survivor space ratio to + 30%: + + > `-XX:TargetSurvivorRatio=30` + +`-XX:TLABSize=`*size* +: Sets the initial size (in bytes) of a thread-local allocation buffer + (TLAB). Append the letter `k` or `K` to indicate kilobytes, `m` or `M` to + indicate megabytes, or `g` or `G` to indicate gigabytes. If this option is + set to 0, then the JVM selects the initial size automatically. + + The following example shows how to set the initial TLAB size to 512 KB: + + > `-XX:TLABSize=512k` + +`-XX:+UseAdaptiveSizePolicy` +: Enables the use of adaptive generation sizing. This option is enabled by + default. To disable adaptive generation sizing, specify + `-XX:-UseAdaptiveSizePolicy` and set the size of the memory allocation pool + explicitly. See the `-XX:SurvivorRatio` option. + +`-XX:+UseG1GC` +: Enables the use of the garbage-first (G1) garbage collector. It's a + server-style garbage collector, targeted for multiprocessor machines with a + large amount of RAM. This option meets GC pause time goals with high + probability, while maintaining good throughput. The G1 collector is + recommended for applications requiring large heaps (sizes of around 6 GB or + larger) with limited GC latency requirements (a stable and predictable + pause time below 0.5 seconds). By default, this option is enabled and G1 is + used as the default garbage collector. + +`-XX:+UseGCOverheadLimit` +: Enables the use of a policy that limits the proportion of time spent by the + JVM on GC before an `OutOfMemoryError` exception is thrown. This option is + enabled, by default, and the parallel GC will throw an `OutOfMemoryError` + if more than 98% of the total time is spent on garbage collection and less + than 2% of the heap is recovered. When the heap is small, this feature can + be used to prevent applications from running for long periods of time with + little or no progress. To disable this option, specify the option + `-XX:-UseGCOverheadLimit`. + +`-XX:+UseNUMA` +: Enables performance optimization of an application on a machine with + nonuniform memory architecture (NUMA) by increasing the application's use + of lower latency memory. By default, this option is disabled and no + optimization for NUMA is made. The option is available only when the + parallel garbage collector is used (`-XX:+UseParallelGC`). + +`-XX:+UseParallelGC` +: Enables the use of the parallel scavenge garbage collector (also known as + the throughput collector) to improve the performance of your application by + leveraging multiple processors. + + By default, this option is disabled and the default collector is used. + +`-XX:+UseSerialGC` +: Enables the use of the serial garbage collector. This is generally the best + choice for small and simple applications that don't require any special + functionality from garbage collection. By default, this option is disabled + and the default collector is used. + +`-XX:+UseStringDeduplication` +: Enables string deduplication. By default, this option is disabled. To use + this option, you must enable the garbage-first (G1) garbage collector. + + String deduplication reduces the memory footprint of `String` objects on + the Java heap by taking advantage of the fact that many `String` objects + are identical. Instead of each `String` object pointing to its own + character array, identical `String` objects can point to and share the same + character array. + +`-XX:+UseTLAB` +: Enables the use of thread-local allocation blocks (TLABs) in the young + generation space. This option is enabled by default. To disable the use of + TLABs, specify the option `-XX:-UseTLAB`. + +`-XX:+UseZGC` +: Enables the use of the Z garbage collector (ZGC). This is a low latency + garbage collector, providing max pause times of a few milliseconds, at + some throughput cost. Pause times are independent of what heap size is + used. Supports heap sizes from 8MB to 16TB. + +`-XX:ZAllocationSpikeTolerance=`*factor* +: Sets the allocation spike tolerance for ZGC. By default, this option is + set to 2.0. This factor describes the level of allocation spikes to expect. + For example, using a factor of 3.0 means the current allocation rate can + be expected to triple at any time. + +`-XX:ZCollectionInterval=`*seconds* +: Sets the maximum interval (in seconds) between two GC cycles when using + ZGC. By default, this option is set to 0 (disabled). + +`-XX:ZFragmentationLimit=`*percent* +: Sets the maximum acceptable heap fragmentation (in percent) for ZGC. + By default, this option is set to 25. Using a lower value will cause the + heap to be compacted more aggressively, to reclaim more memory at the cost + of using more CPU time. + +`-XX:+ZProactive` +: Enables proactive GC cycles when using ZGC. By default, this option is + enabled. ZGC will start a proactive GC cycle if doing so is expected to + have minimal impact on the running application. This is useful if the + application is mostly idle or allocates very few objects, but you still + want to keep the heap size down and allow reference processing to happen + even when there are a lot of free space on the heap. + +`-XX:+ZUncommit` +: Enables uncommitting of unused heap memory when using ZGC. By default, + this option is enabled. Uncommitting unused heap memory will lower the + memory footprint of the JVM, and make that memory available for other + processes to use. + +`-XX:ZUncommitDelay=`*seconds* +: Sets the amount of time (in seconds) that heap memory must have been + unused before being uncommitted. By default, this option is set to 300 + (5 minutes). Committing and uncommitting memory are relatively + expensive operations. Using a lower value will cause heap memory to be + uncommitted earlier, at the risk of soon having to commit it again. + +## Deprecated Java Options + +These `java` options are deprecated and might be removed in a future JDK +release. They're still accepted and acted upon, but a warning is issued when +they're used. + +`-Xloggc:`*filename* +: Sets the file to which verbose GC events information should be redirected + for logging. The `-Xloggc` option overrides `-verbose:gc` if both are given + with the same java command. `-Xloggc:`*filename* is replaced by + `-Xlog:gc:`*filename*. See Enable Logging with the JVM Unified Logging + Framework. + + Example: + + `-Xlog:gc:garbage-collection.log` + +`-XX:+FlightRecorder` +: Enables the use of Java Flight Recorder (JFR) during the runtime of the + application. Since JDK 8u40 this option has not been required to use JFR. + +## Obsolete Java Options + +These `java` options are still accepted but ignored, and a warning is issued +when they're used. + +`--illegal-access=`*parameter* +: Controlled _relaxed strong encapsulation_, as defined in [JEP + 261](https://openjdk.org/jeps/261#Relaxed-strong-encapsulation). + This option was deprecated in JDK 16 by [JEP + 396](https://openjdk.org/jeps/396) and made obsolete in JDK 17 + by [JEP 403](https://openjdk.org/jeps/403). + +`-XX:RTMAbortRatio=`*abort\_ratio* +: Specifies the RTM abort ratio is specified as a percentage (%) of all + executed RTM transactions. If a number of aborted transactions becomes + greater than this ratio, then the compiled code is deoptimized. This ratio + is used when the `-XX:+UseRTMDeopt` option is enabled. The default value of + this option is 50. This means that the compiled code is deoptimized if 50% + of all transactions are aborted. + +`-XX:RTMRetryCount=`*number\_of\_retries* +: Specifies the number of times that the RTM locking code is retried, when it + is aborted or busy, before falling back to the normal locking mechanism. + The default value for this option is 5. The `-XX:UseRTMLocking` option must + be enabled. + +`-XX:+UseRTMDeopt` +: Autotunes RTM locking depending on the abort ratio. This ratio is specified + by the `-XX:RTMAbortRatio` option. If the number of aborted transactions + exceeds the abort ratio, then the method containing the lock is deoptimized + and recompiled with all locks as normal locks. This option is disabled by + default. The `-XX:+UseRTMLocking` option must be enabled. + +`-XX:+UseRTMLocking` +: Generates Restricted Transactional Memory (RTM) locking code for all + inflated locks, with the normal locking mechanism as the fallback handler. + This option is disabled by default. Options related to RTM are available + only on x86 CPUs that support Transactional Synchronization Extensions (TSX). + + RTM is part of Intel's TSX, which is an x86 instruction set extension and + facilitates the creation of multithreaded applications. RTM introduces the + new instructions `XBEGIN`, `XABORT`, `XEND`, and `XTEST`. The `XBEGIN` and + `XEND` instructions enclose a set of instructions to run as a transaction. + If no conflict is found when running the transaction, then the memory and + register modifications are committed together at the `XEND` instruction. + The `XABORT` instruction can be used to explicitly abort a transaction and + the `XTEST` instruction checks if a set of instructions is being run in a + transaction. + + A lock on a transaction is inflated when another thread tries to access the + same transaction, thereby blocking the thread that didn't originally + request access to the transaction. RTM requires that a fallback set of + operations be specified in case a transaction aborts or fails. An RTM lock + is a lock that has been delegated to the TSX's system. + + RTM improves performance for highly contended locks with low conflict in a + critical region (which is code that must not be accessed by more than one + thread concurrently). RTM also improves the performance of coarse-grain + locking, which typically doesn't perform well in multithreaded + applications. (Coarse-grain locking is the strategy of holding locks for + long periods to minimize the overhead of taking and releasing locks, while + fine-grained locking is the strategy of trying to achieve maximum + parallelism by locking only when necessary and unlocking as soon as + possible.) Also, for lightly contended locks that are used by different + threads, RTM can reduce false cache line sharing, also known as cache line + ping-pong. This occurs when multiple threads from different processors are + accessing different resources, but the resources share the same cache line. + As a result, the processors repeatedly invalidate the cache lines of other + processors, which forces them to read from main memory instead of their + cache. + +## Removed Java Options + +These `java` options have been removed in JDK @@VERSION_SPECIFICATION@@ and using them results in an error of: + +> `Unrecognized VM option` *option-name* + +`-XX:InitialRAMFraction=`*ratio* +: Sets the initial amount of memory that the JVM may use for the Java heap + before applying ergonomics heuristics as a ratio of the maximum amount + determined as described in the `-XX:MaxRAM` option. The default value is + 64. + + Use the option `-XX:InitialRAMPercentage` instead. + +`-XX:MaxRAMFraction=`*ratio* +: Sets the maximum amount of memory that the JVM may use for the Java heap + before applying ergonomics heuristics as a fraction of the maximum amount + determined as described in the `-XX:MaxRAM` option. The default value is 4. + + Specifying this option disables automatic use of compressed oops if + the combined result of this and other options influencing the maximum amount + of memory is larger than the range of memory addressable by compressed oops. + See `-XX:UseCompressedOops` for further information about compressed oops. + + Use the option `-XX:MaxRAMPercentage` instead. + +`-XX:MinRAMFraction=`*ratio* +: Sets the maximum amount of memory that the JVM may use for the Java heap + before applying ergonomics heuristics as a fraction of the maximum amount + determined as described in the `-XX:MaxRAM` option for small heaps. A small + heap is a heap of approximately 125 MB. The default value is 2. + + Use the option `-XX:MinRAMPercentage` instead. + +`-XX:+ScavengeBeforeFullGC` +: Enables GC of the young generation before each full GC. This option is + enabled by default. It is recommended that you *don't* disable it, because + scavenging the young generation before a full GC can reduce the number of + objects reachable from the old generation space into the young generation + space. To disable GC of the young generation before each full GC, specify + the option `-XX:-ScavengeBeforeFullGC`. + +`-Xfuture` +: Enables strict class-file format checks that enforce close conformance to + the class-file format specification. Developers should use this flag when + developing new code. Stricter checks may become the default in future + releases. + + Use the option `-Xverify:all` instead. + +For the lists and descriptions of options removed in previous releases see the *Removed Java Options* section in: + +- [The `java` Command, Release 23](https://docs.oracle.com/en/java/javase/23/docs/specs/man/java.html) + +- [The `java` Command, Release 22](https://docs.oracle.com/en/java/javase/22/docs/specs/man/java.html) + +- [The `java` Command, Release 21](https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html) + +- [The `java` Command, Release 20](https://docs.oracle.com/en/java/javase/20/docs/specs/man/java.html) + +- [The `java` Command, Release 19](https://docs.oracle.com/en/java/javase/19/docs/specs/man/java.html) + +- [The `java` Command, Release 18](https://docs.oracle.com/en/java/javase/18/docs/specs/man/java.html) + +- [The `java` Command, Release 17](https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html) + +- [The `java` Command, Release 16](https://docs.oracle.com/en/java/javase/16/docs/specs/man/java.html) + +- [The `java` Command, Release 15](https://docs.oracle.com/en/java/javase/15/docs/specs/man/java.html) + +- [The `java` Command, Release 14](https://docs.oracle.com/en/java/javase/14/docs/specs/man/java.html) + +- [The `java` Command, Release 13](https://docs.oracle.com/en/java/javase/13/docs/specs/man/java.html) + +- [Java Platform, Standard Edition Tools Reference, Release 12]( + https://docs.oracle.com/en/java/javase/12/tools/java.html#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE) + +- [Java Platform, Standard Edition Tools Reference, Release 11]( + https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-741FC470-AA3E-494A-8D2B-1B1FE4A990D1) + +- [Java Platform, Standard Edition Tools Reference, Release 10]( + https://docs.oracle.com/javase/10/tools/java.htm#JSWOR624) + +- [Java Platform, Standard Edition Tools Reference, Release 9]( + https://docs.oracle.com/javase/9/tools/java.htm#JSWOR624) + +- [Java Platform, Standard Edition Tools Reference, Release 8 for Oracle JDK + on Windows]( + https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html#BGBCIEFC) + +- [Java Platform, Standard Edition Tools Reference, Release 8 for Oracle JDK + on Solaris, Linux, and macOS]( + https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BGBCIEFC) + +## java Command-Line Argument Files + +You can shorten or simplify the `java` command by using `@` argument files to +specify one or more text files that contain arguments, such as options and +class names, which are passed to the `java` command. This let's you to create +`java` commands of any length on any operating system. + +In the command line, use the at sign (`@`) prefix to identify an argument file +that contains `java` options and class names. When the `java` command +encounters a file beginning with the at sign (`@`), it expands the contents of +that file into an argument list just as they would be specified on the command +line. + +The `java` launcher expands the argument file contents until it encounters the +`--disable-@files` option. You can use the `--disable-@files` option anywhere +on the command line, including in an argument file, to stop `@` argument files +expansion. + +The following items describe the syntax of `java` argument files: + +- The argument file must contain only ASCII characters or characters in + system default encoding that's ASCII friendly, such as UTF-8. + +- The argument file size must not exceed MAXINT (2,147,483,647) bytes. + +- The launcher doesn't expand wildcards that are present within an argument + file. That means, an asterisk `*` is passed on as-is to the starting VM. + For example `*.java` stays `*.java` and is not expanded to `Foo.java`, + `Bar.java`, etc. like on some command line shell. + +- Use white space or new line characters to separate arguments included in + the file. + +- White space includes a white space character, `\t`, `\n`, `\r`, and `\f`. + + For example, it is possible to have a path with a space, such as + `c:\Program Files` that can be specified as either `"c:\\Program Files"` or, + to avoid an escape, `c:\Program" "Files`. + +- Any option that contains spaces, such as a path component, must be within + quotation marks using quotation ('\"') characters in its entirety. + +- A string within quotation marks may contain the characters `\n`, `\r`, + `\t`, and `\f`. They are converted to their respective ASCII codes. + +- If a file name contains embedded spaces, then put the whole file name in + double quotation marks. + +- File names in an argument file are relative to the current directory, not + to the location of the argument file. + +- Use the number sign `#` in the argument file to identify comments. All + characters following the `#` are ignored until the end of line. + +- Additional at sign `@` prefixes to `@` prefixed options act as an escape, + (the first `@` is removed and the rest of the arguments are presented to + the launcher literally). + +- Lines may be continued using the continuation character (`\`) at the + end-of-line. The two lines are concatenated with the leading white spaces + trimmed. To prevent trimming the leading white spaces, a continuation + character (`\`) may be placed at the first column. + +- Because backslash (\\) is an escape character, a backslash character must + be escaped with another backslash character. + +- Partial quote is allowed and is closed by an end-of-file. + +- An open quote stops at end-of-line unless `\` is the last character, which + then joins the next line by removing all leading white space characters. + +- Wildcards (\*) aren't allowed in these lists (such as specifying `*.java`). + +- Use of the at sign (`@`) to recursively interpret files isn't supported. + +### Example of Open or Partial Quotes in an Argument File + +In the argument file, + +``` +-cp "lib/ +cool/ +app/ +jars +``` + +this is interpreted as: + +> `-cp lib/cool/app/jars` + +### Example of a Backslash Character Escaped with Another Backslash Character in an Argument File + +To output the following: + +> `-cp c:\Program Files (x86)\Java\jre\lib\ext;c:\Program + Files\Java\jre9\lib\ext` + +The backslash character must be specified in the argument file as: + +> `-cp "c:\\Program Files (x86)\\Java\\jre\\lib\\ext;c:\\Program + Files\\Java\\jre9\\lib\\ext"` + +### Example of an EOL Escape Used to Force Concatenation of Lines in an Argument File + +In the argument file, + +``` +-cp "/lib/cool app/jars:\ + /lib/another app/jars" +``` + +This is interpreted as: + +> `-cp /lib/cool app/jars:/lib/another app/jars` + +### Example of Line Continuation with Leading Spaces in an Argument File + +In the argument file, + +``` +-cp "/lib/cool\ +\app/jars" +``` + +This is interpreted as: + +`-cp /lib/cool app/jars` + +### Examples of Using Single Argument File + +You can use a single argument file, such as `myargumentfile` in the following +example, to hold all required `java` arguments: + +> `java @myargumentfile` + +### Examples of Using Argument Files with Paths + +You can include relative paths in argument files; however, they're relative to +the current working directory and not to the paths of the argument files +themselves. In the following example, `path1/options` and `path2/options` +represent argument files with different paths. Any relative paths that they +contain are relative to the current working directory and not to the argument +files: + +> `java @path1/options @path2/classes` + +## Code Heap State Analytics + +### Overview + +There are occasions when having insight into the current state of the JVM code +heap would be helpful to answer questions such as: + +- Why was the JIT turned off and then on again and again? + +- Where has all the code heap space gone? + +- Why is the method sweeper not working effectively? + +To provide this insight, a code heap state analytics feature has been +implemented that enables on-the-fly analysis of the code heap. The analytics +process is divided into two parts. The first part examines the entire code heap +and aggregates all information that is believed to be useful or important. The +second part consists of several independent steps that print the collected +information with an emphasis on different aspects of the data. Data collection +and printing are done on an "on request" basis. + +### Syntax + +Requests for real-time, on-the-fly analysis can be issued with the following +command: + +> `jcmd` *pid* `Compiler.CodeHeap_Analytics` \[*function*\] \[*granularity*\] + +If you are only interested in how the code heap looks like after running a +sample workload, you can use the command line option: + +> `-Xlog:codecache=Trace` + +To see the code heap state when a "CodeCache full" condition exists, start the +VM with the command line option: + +> `-Xlog:codecache=Debug` + +See [CodeHeap State Analytics (OpenJDK)]( +https://bugs.openjdk.org/secure/attachment/75649/JVM_CodeHeap_StateAnalytics_V2.pdf) +for a detailed description of the code heap state analytics feature, the +supported functions, and the granularity options. + +## Enable Logging with the JVM Unified Logging Framework + +You use the `-Xlog` option to configure or enable logging with the Java Virtual +Machine (JVM) unified logging framework. + +### Synopsis + +> `-Xlog`\[`:`\[*what*\]\[`:`\[*output*\]\[`:`\[*decorators*\]\[`:`*output-options*\[`,`...\]\]\]\]\] +> +> `-Xlog:`*directive* + +*what* +: Specifies a combination of tags and levels of the form + *tag1*\[`+`*tag2*...\]\[`*`\]\[`=`*level*\]\[`,`...\]. Unless the wildcard + (`*`) is specified, only log messages tagged with exactly the tags + specified are matched. See [-Xlog Tags and Levels]. + +*output* +: Sets the type of output. Omitting the *output* type defaults to `stdout`. + See [-Xlog Output]. + +*decorators* +: Configures the output to use a custom set of decorators. Omitting + *decorators* defaults to `uptime`, `level`, and `tags`. See + [Decorations]. + +*output-options* +: Sets the `-Xlog` logging output options. + +*directive* +: A global option or subcommand: help, disable, async + +### Description + +The Java Virtual Machine (JVM) unified logging framework provides a common +logging system for all components of the JVM. GC logging for the JVM has been +changed to use the new logging framework. The mapping of old GC flags to the +corresponding new Xlog configuration is described in [Convert GC Logging Flags +to Xlog]. In addition, runtime logging has also been changed to use the JVM +unified logging framework. The mapping of legacy runtime logging flags to the +corresponding new Xlog configuration is described in [Convert Runtime Logging +Flags to Xlog]. + +The following provides quick reference to the `-Xlog` command and syntax for +options: + +`-Xlog` +: Enables JVM logging on an `info` level. + +`-Xlog:help` +: Prints `-Xlog` usage syntax and available tags, levels, and decorators + along with example command lines with explanations. + +`-Xlog:disable` +: Turns off all logging and clears all configuration of the logging framework + including the default configuration for warnings and errors. + +`-Xlog`\[`:`*option*\] +: Applies multiple arguments in the order that they appear on the command + line. Multiple `-Xlog` arguments for the same output override each other in + their given order. + + The *option* is set as: + + > \[*tag-selection*\]\[`:`\[*output*\]\[`:`\[*decorators*\]\[`:`*output-options*\]\]\] + + Omitting the *tag-selection* defaults to a tag-set of `all` and a level of + `info`. + + > *tag*\[`+`...\] `all` + + The `all` tag is a meta tag consisting of all tag-sets available. The + asterisk `*` in a tag set definition denotes a wildcard tag match. Matching + with a wildcard selects all tag sets that contain *at least* the specified + tags. Without the wildcard, only exact matches of the specified tag sets + are selected. + + *output-options* is + + > `filecount=`*file-count* `filesize=`*file size with optional K, M or G + suffix* `foldmultilines=`** + + When `foldmultilines` is true, a log event that consists of + multiple lines will be folded into a single line by replacing newline characters + with the sequence `'\'` and `'n'` in the output. + Existing single backslash characters will also be replaced with a sequence of + two backslashes so that the conversion can be reversed. + This option is safe to use with UTF-8 character encodings, but other encodings may not work. + For example, it may incorrectly convert multi-byte sequences in Shift JIS and BIG5. + +### Default Configuration + +When the `-Xlog` option and nothing else is specified on the command line, the +default configuration is used. The default configuration logs all messages with +a level that matches either warning or error regardless of what tags the +message is associated with. The default configuration is equivalent to entering +the following on the command line: + +> `-Xlog:all=warning:stdout:uptime,level,tags` + +### Controlling Logging at Runtime + +Logging can also be controlled at run time through Diagnostic Commands (with +the [jcmd](jcmd.html) utility). Everything that can be specified on the command line can +also be specified dynamically with the `VM.log` command. As the diagnostic +commands are automatically exposed as MBeans, you can use JMX to change logging +configuration at run time. + +### -Xlog Tags and Levels + +Each log message has a level and a tag set associated with it. The level of +the message corresponds to its details, and the tag set corresponds to what +the message contains or which JVM component it involves (such as, `gc`, +`jit`, or `os`). Mapping GC flags to the Xlog configuration is described +in [Convert GC Logging Flags to Xlog]. Mapping legacy runtime logging flags to +the corresponding Xlog configuration is described in [Convert Runtime Logging +Flags to Xlog]. + +**Available log levels:** + +- `off` +- `trace` +- `debug` +- `info` +- `warning` +- `error` + +**Available log tags:** + +There are literally dozens of log tags, which in the right combinations, will enable +a range of logging output. The full set of available log tags can be seen using `-Xlog:help`. +Specifying `all` instead of a tag combination matches all tag combinations. + +### -Xlog Output + +The `-Xlog` option supports the following types of outputs: + +- `stdout` --- Sends output to stdout +- `stderr` --- Sends output to stderr +- `file=`*filename* --- Sends output to text file(s). + +When using `file=`*filename*, specifying `%p`, `%t` and/or `%hn` in the file name +expands to the JVM's PID, startup timestamp and host name, respectively. You can also +configure text files to handle file rotation based on file size and a number of +files to rotate. For example, to rotate the log file every 10 MB and keep 5 +files in rotation, specify the options `filesize=10M, filecount=5`. The target +size of the files isn't guaranteed to be exact, it's just an approximate value. +Files are rotated by default with up to 5 rotated files of target size 20 MB, +unless configured otherwise. Specifying `filecount=0` means that the log file +shouldn't be rotated. There's a possibility of the pre-existing log file +getting overwritten. + +### -Xlog Output Mode + +By default logging messages are output synchronously - each log message is written to +the designated output when the logging call is made. But you can instead use asynchronous +logging mode by specifying: + +`-Xlog:async` +: Write all logging asynchronously. + +In asynchronous logging mode, log sites enqueue all logging messages to an intermediate buffer +and a standalone thread is responsible for flushing them to the corresponding outputs. The +intermediate buffer is bounded and on buffer exhaustion the enqueuing message is discarded. +Log entry write operations are guaranteed non-blocking. + +The option `-XX:AsyncLogBufferSize=N` specifies the memory budget in bytes for the intermediate buffer. +The default value should be big enough to cater for most cases. Users can provide a custom value to +trade memory overhead for log accuracy if they need to. + +### Decorations + +Logging messages are decorated with information about the message. You can +configure each output to use a custom set of decorators. The order of the +output is always the same as listed in the table. You can configure the +decorations to be used at run time. Decorations are prepended to the log +message. For example: + +``` +[6.567s][info][gc,old] Old collection complete +``` + +Omitting `decorators` defaults to `uptime`, `level`, and `tags`. The `none` +decorator is special and is used to turn off all decorations. + +`time` (`t`), `utctime` (`utc`), `uptime` (`u`), `timemillis` (`tm`), +`uptimemillis` (`um`), `timenanos` (`tn`), `uptimenanos` (`un`), `hostname` +(`hn`), `pid` (`p`), `tid` (`ti`), `level` (`l`), `tags` (`tg`) decorators can +also be specified as `none` for no decoration. + +Table: Logging Messages Decorations + +--------------- -------------------------------------------------------------- +Decorations Description +--------------- -------------------------------------------------------------- +`time` or `t` Current time and date in ISO-8601 format. + +`utctime` Universal Time Coordinated or Coordinated Universal Time. +or `utc` + +`uptime` or `u` Time since the start of the JVM in seconds and milliseconds. + For example, 6.567s. + +`timemillis` The same value as generated by `System.currentTimeMillis()` +or `tm` + +`uptimemillis` Milliseconds since the JVM started. +or `um` + +`timenanos` The same value generated by `System.nanoTime()`. +or `tn` + +`uptimenanos` Nanoseconds since the JVM started. +or `un` + +`hostname` The host name. +or `hn` + +`pid` or `p` The process identifier. + +`tid` or `ti` The thread identifier. + +`level` or `l` The level associated with the log message. + +`tags` or `tg` The tag-set associated with the log message. +--------------- -------------------------------------------------------------- + +### Convert GC Logging Flags to Xlog + +Table: Legacy GC Logging Flags to Xlog Configuration Mapping + +------------------------------------ -------------------------- ---------------------------------------------------- +Legacy Garbage Collection (GC) Flag Xlog Configuration Comment +------------------------------------ -------------------------- ---------------------------------------------------- +`G1PrintHeapRegions` `-Xlog:gc+region=trace` Not Applicable + +`GCLogFileSize` No configuration Log rotation is handled by the framework. + available + +`NumberOfGCLogFiles` Not Applicable Log rotation is handled by the framework. + +`PrintAdaptiveSizePolicy` `-Xlog:gc+ergo*=`*level* Use a *level* of `debug` for most of the information, + or a *level* of `trace` for all of what was logged + for `PrintAdaptiveSizePolicy`. + +`PrintGC` `-Xlog:gc` Not Applicable + +`PrintGCApplicationConcurrentTime` `-Xlog:safepoint` Note that `PrintGCApplicationConcurrentTime` and + `PrintGCApplicationStoppedTime` are logged on the + same tag and aren't separated in the new logging. + +`PrintGCApplicationStoppedTime` `-Xlog:safepoint` Note that `PrintGCApplicationConcurrentTime` and + `PrintGCApplicationStoppedTime` are logged on the + same tag and not separated in the new logging. + +`PrintGCCause` Not Applicable GC cause is now always logged. + +`PrintGCDateStamps` Not Applicable Date stamps are logged by the framework. + +`PrintGCDetails` `-Xlog:gc*` Not Applicable + +`PrintGCID` Not Applicable GC ID is now always logged. + +`PrintGCTaskTimeStamps` `-Xlog:gc+task*=debug` Not Applicable + +`PrintGCTimeStamps` Not Applicable Time stamps are logged by the framework. + +`PrintHeapAtGC` `-Xlog:gc+heap=trace` Not Applicable + +`PrintReferenceGC` `-Xlog:gc+ref*=debug` Note that in the old logging, `PrintReferenceGC` had + an effect only if `PrintGCDetails` was also enabled. + +`PrintStringDeduplicationStatistics` `-Xlog:gc+stringdedup*=debug` Not Applicable + +`PrintTenuringDistribution` `-Xlog:gc+age*=`*level* Use a *level* of `debug` for the most relevant + information, or a *level* of `trace` for all of what + was logged for `PrintTenuringDistribution`. + +`UseGCLogFileRotation` Not Applicable What was logged for `PrintTenuringDistribution`. +------------------------------------ -------------------------- ---------------------------------------------------- + +### Convert Runtime Logging Flags to Xlog + +These legacy flags are no longer recognized and will cause an error if used directly. Use their unified logging equivalent +instead. + +Table: Runtime Logging Flags to Xlog Configuration Mapping + +--------------------------- ------------------------------------- ------------------------------------------------------------------ +Legacy Runtime Flag Xlog Configuration Comment +--------------------------- ------------------------------------- ------------------------------------------------------------------ +`TraceExceptions` `-Xlog:exceptions=info` Not Applicable + +`TraceClassLoading` `-Xlog:class+load=`*level* Use *level*=`info` for regular information, or *level*=`debug` + for additional information. In Unified Logging syntax, + `-verbose:class` equals `-Xlog:class+load=info,class+unload=info`. + +`TraceClassLoadingPreorder` `-Xlog:class+preorder=debug` Not Applicable + +`TraceClassUnloading` `-Xlog:class+unload=`*level* Use *level*=`info` for regular information, or *level*=`trace` + for additional information. In Unified Logging syntax, + `-verbose:class` equals `-Xlog:class+load=info,class+unload=info`. + +`VerboseVerification` `-Xlog:verification=info` Not Applicable + +`TraceClassPaths` `-Xlog:class+path=info` Not Applicable + +`TraceClassResolution` `-Xlog:class+resolve=debug` Not Applicable + +`TraceClassInitialization` `-Xlog:class+init=info` Not Applicable + +`TraceLoaderConstraints` `-Xlog:class+loader+constraints=info` Not Applicable + + +`TraceClassLoaderData` `-Xlog:class+loader+data=`*level* Use *level*=`debug` for regular information or *level*=`trace` for + additional information. + +`TraceSafepointCleanupTime` `-Xlog:safepoint+cleanup=info` Not Applicable + +`TraceSafepoint` `-Xlog:safepoint=debug` Not Applicable + +`TraceMonitorInflation` `-Xlog:monitorinflation=debug` Not Applicable + +`TraceRedefineClasses` `-Xlog:redefine+class*=`*level* *level*=`info`, `debug`, and `trace` provide increasing amounts + of information. +--------------------------- ------------------------------------- ------------------------------------------------------------------ + +### -Xlog Usage Examples + +The following are `-Xlog` examples. + +`-Xlog` +: Logs all messages by using the `info` level to `stdout` with `uptime`, + `levels`, and `tags` decorations. This is equivalent to using: + + > `-Xlog:all=info:stdout:uptime,levels,tags` + +`-Xlog:gc` +: Logs messages tagged with the `gc` tag using `info` level to `stdout`. The + default configuration for all other messages at level `warning` is in + effect. + +`-Xlog:gc,safepoint` +: Logs messages tagged either with the `gc` or `safepoint` tags, both using + the `info` level, to `stdout`, with default decorations. Messages tagged + with both `gc` and `safepoint` won't be logged. + +`-Xlog:gc+ref=debug` +: Logs messages tagged with both `gc` and `ref` tags, using the `debug` level + to `stdout`, with default decorations. Messages tagged only with one of the + two tags won't be logged. + +`-Xlog:gc=debug:file=gc.txt:none` +: Logs messages tagged with the `gc` tag using the `debug` level to a file + called `gc.txt` with no decorations. The default configuration for all + other messages at level `warning` is still in effect. + +`-Xlog:gc=trace:file=gctrace.txt:uptimemillis,pid:filecount=5,filesize=1024` +: Logs messages tagged with the `gc` tag using the `trace` level to a + rotating file set with 5 files with size 1 MB with the base name + `gctrace.txt` and uses decorations `uptimemillis` and `pid`. + + The default configuration for all other messages at level `warning` is + still in effect. + +`-Xlog:gc::uptime,tid` +: Logs messages tagged with the `gc` tag using the default 'info' level to + default the output `stdout` and uses decorations `uptime` and `tid`. The + default configuration for all other messages at level `warning` is still in + effect. + +`-Xlog:gc*=info,safepoint*=off` +: Logs messages tagged with at least `gc` using the `info` level, but turns + off logging of messages tagged with `safepoint`. Messages tagged with both + `gc` and `safepoint` won't be logged. + +`-Xlog:disable -Xlog:safepoint=trace:safepointtrace.txt` +: Turns off all logging, including warnings and errors, and then enables + messages tagged with `safepoint`using `trace`level to the file + `safepointtrace.txt`. The default configuration doesn't apply, because the + command line started with `-Xlog:disable`. + +### Complex -Xlog Usage Examples + +The following describes a few complex examples of using the `-Xlog` option. + +`-Xlog:gc+class*=debug` +: Logs messages tagged with at least `gc` and `class` tags using the `debug` + level to `stdout`. The default configuration for all other messages at the + level `warning` is still in effect + +`-Xlog:gc+meta*=trace,class*=off:file=gcmetatrace.txt` +: Logs messages tagged with at least the `gc` and `meta` tags using the + `trace` level to the file `metatrace.txt` but turns off all messages tagged + with `class`. Messages tagged with `gc`, `meta`, and `class` aren't be + logged as `class*` is set to off. The default configuration for all other + messages at level `warning` is in effect except for those that include + `class`. + +`-Xlog:gc+meta=trace` +: Logs messages tagged with exactly the `gc` and `meta` tags using the + `trace` level to `stdout`. The default configuration for all other messages + at level `warning` is still be in effect. + +`-Xlog:gc+class+heap*=debug,meta*=warning,threads*=off` +: Logs messages tagged with at least `gc`, `class`, and `heap` tags using the + `trace` level to `stdout` but only log messages tagged with `meta` with + level. The default configuration for all other messages at the level + `warning` is in effect except for those that include `threads`. + +## Validate Java Virtual Machine Flag Arguments + +You use values provided to all Java Virtual Machine (JVM) command-line flags +for validation and, if the input value is invalid or out-of-range, then an +appropriate error message is displayed. + +Whether they're set ergonomically, in a command line, by an input tool, or +through the APIs (for example, classes contained in the package +`java.lang.management`) the values provided to all Java Virtual Machine (JVM) +command-line flags are validated. Ergonomics are described in Java Platform, +Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide. + +Range and constraints are validated either when all flags have their values set +during JVM initialization or a flag's value is changed during runtime (for +example using the `jcmd` tool). The JVM is terminated if a value violates +either the range or constraint check and an appropriate error message is +printed on the error stream. + +For example, if a flag violates a range or a constraint check, then the JVM +exits with an error: + +``` +java -XX:AllocatePrefetchStyle=5 -version +intx AllocatePrefetchStyle=5 is outside the allowed range [ 0 ... 3 ] +Improperly specified VM option 'AllocatePrefetchStyle=5' +Error: Could not create the Java Virtual Machine. +Error: A fatal exception has occurred. Program will exit. +``` + +The flag `-XX:+PrintFlagsRanges` prints the range of all the flags. This flag +allows automatic testing of the flags by the values provided by the ranges. For +the flags that have the ranges specified, the type, name, and the actual range +is printed in the output. + +For example, + +``` +intx ThreadStackSize [ 0 ... 9007199254740987 ] {pd product} +``` + +For the flags that don't have the range specified, the values aren't displayed +in the print out. For example: + +``` +size_t NewSize [ ... ] {product} +``` + +This helps to identify the flags that need to be implemented. The automatic +testing framework can skip those flags that don't have values and aren't +implemented. + +## Large Pages + +You use large pages, also known as huge pages, as memory pages that are +significantly larger than the standard memory page size (which varies depending +on the processor and operating system). Large pages optimize processor +Translation-Lookaside Buffers. + +A Translation-Lookaside Buffer (TLB) is a page translation cache that holds the +most-recently used virtual-to-physical address translations. A TLB is a scarce +system resource. A TLB miss can be costly because the processor must then read +from the hierarchical page table, which may require multiple memory accesses. +By using a larger memory page size, a single TLB entry can represent a larger +memory range. This results in less pressure on a TLB, and memory-intensive +applications may have better performance. + +However, using large pages can negatively affect system performance. For +example, when a large amount of memory is pinned by an application, it may +create a shortage of regular memory and cause excessive paging in other +applications and slow down the entire system. Also, a system that has been up +for a long time could produce excessive fragmentation, which could make it +impossible to reserve enough large page memory. When this happens, either the +OS or JVM reverts to using regular pages. + +Linux and Windows support large pages. + +### Large Pages Support for Linux + +Linux supports large pages since version 2.6. To check if your environment +supports large pages, try the following: + +``` +# cat /proc/meminfo | grep Huge +HugePages_Total: 0 +HugePages_Free: 0 +... +Hugepagesize: 2048 kB +``` + +If the output contains items prefixed with "Huge", then your system supports +large pages. The values may vary depending on environment. The `Hugepagesize` +field shows the default large page size in your environment, and the other +fields show details for large pages of this size. Newer kernels have support +for multiple large page sizes. To list the supported page sizes, run this: + +``` +# ls /sys/kernel/mm/hugepages/ +hugepages-1048576kB hugepages-2048kB +``` + +The above environment supports 2 MB and 1 GB large pages, but they need to be +configured so that the JVM can use them. When using large pages and not +enabling transparent huge pages (option `-XX:+UseTransparentHugePages`), the +number of large pages must be pre-allocated. For example, to enable 8 GB of +memory to be backed by 2 MB large pages, login as `root` and run: + +> `# echo 4096 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages` + +It is always recommended to check the value of `nr_hugepages` after the request +to make sure the kernel was able to allocate the requested number of large +pages. + +> **Note:** The values contained in `/proc` and `/sys` reset after you + reboot your system, so may want to set them in an initialization script + (for example, `rc.local` or `sysctl.conf`). + +If you configure the OS kernel parameters to enable use of large pages, the +Java processes may allocate large pages for the Java heap as well as other +internal areas, for example: + +* Code cache +* Marking bitmaps + +Consequently, if you configure the `nr_hugepages` parameter to the size of the +Java heap, then the JVM can still fail to allocate the heap using large pages +because other areas such as the code cache might already have used some of the +configured large pages. + +### Large Pages Support for Windows + +To use large pages support on Windows, the +administrator must first assign additional privileges to the user who is running +the application: + +1. Select **Control Panel**, **Administrative Tools**, and then **Local + Security Policy**. +2. Select **Local Policies** and then **User Rights Assignment**. +3. Double-click **Lock pages in memory**, then add users and/or groups. +4. Reboot your system. + +Note that these steps are required even if it's the administrator who's running +the application, because administrators by default don't have the privilege to +lock pages in memory. + +## Application Class Data Sharing + +Application Class Data Sharing (AppCDS) stores classes used +by your applications in an archive file. Since these classes are +stored in a format that can be loaded very quickly (compared +to classes stored in a JAR file), AppCDS can improve the start-up +time of your applications. In addition, AppCDS can reduce the runtime +memory footprint by sharing parts of these classes across multiple +processes. + +Classes in the CDS archive are stored in an optimized format that's +about 2 to 5 times larger than classes stored in JAR files or the JDK +runtime image. Therefore, it's a good idea to archive only those +classes that are actually used by your application. These usually +are just a small portion of all available classes. For example, your +application may use only a few APIs provided by a large library. + +### Using CDS Archives + +By default, in most JDK distributions, unless `-Xshare:off` is +specified, the JVM starts up with a default CDS archive, which +is usually located in `JAVA_HOME/lib/server/classes.jsa` (or +`JAVA_HOME\bin\server\classes.jsa` on Windows). This +archive contains about 1300 core library classes that are used +by most applications. + +To use CDS for the exact set of classes used by your application, +you can use the `-XX:SharedArchiveFile` option, which has the +general form: + +> `-XX:SharedArchiveFile=:` + +- The `` overrides the default CDS archive. +- The `` provides additional classes that can + be loaded on top of those in the ``. +- On Windows, the above path delimiter `:` should be replaced with `;` + +(The names "static" and "dynamic" are used for historical reasons. +The only significance is that the "static" archive is loaded first and +the "dynamic" archive is loaded second). + +The JVM can use up to two archives. To use only a single ``, +you can omit the `` portion: + +> `-XX:SharedArchiveFile=` + +For convenience, the `` records the location of the +``. Therefore, you can omit the `` by saying only: + +> `-XX:SharedArchiveFile=` + +### Manually Creating CDS Archives + +CDS archives can be created manually using several methods: + +- `-Xshare:dump` +- `-XX:ArchiveClassesAtExit` +- `jcmd VM.cds` + +One common operation in all these methods is a "trial run", where you run +the application once to determine the classes that should be stored +in the archive. + +#### Creating a Static CDS Archive File with -Xshare:dump + +The following steps create a static CDS archive file that contains all the classes +used by the `test.Hello` application. + +1. Create a list of all classes used by the `test.Hello` application. The + following command creates a file named `hello.classlist` that contains a + list of all classes used by this application: + + > `java -Xshare:off -XX:DumpLoadedClassList=hello.classlist -cp hello.jar test.Hello` + + The classpath specified by the `-cp` parameter must contain only + JAR files. + +2. Create a static archive, named `hello.jsa`, that contains all the classes + in `hello.classlist`: + + > `java -Xshare:dump -XX:SharedArchiveFile=hello.jsa -XX:SharedClassListFile=hello.classlist -cp hello.jar` + +3. Run the application `test.Hello` with the archive `hello.jsa`: + + > `java -XX:SharedArchiveFile=hello.jsa -cp hello.jar test.Hello` + +4. **Optional** Verify that the `test.Hello` application is using the class + contained in the `hello.jsa` shared archive: + + > `java -XX:SharedArchiveFile=hello.jsa -cp hello.jar -Xlog:class+load test.Hello` + + The output of this command should contain the following text: + + > `[info][class,load] test.Hello source: shared objects file` + +By default, when the `-Xshare:dump` option is used, the JVM runs in interpreter-only mode +(as if the `-Xint` option were specified). This is required for generating deterministic output +in the shared archive file. I.e., the exact same archive will be generated, bit-for-bit, every time +you dump it. However, if deterministic output is not needed, and you have a large classlist, you can +explicitly add `-Xmixed` to the command-line to enable the JIT compiler. This will speed up +the archive creation. + +#### Creating a Dynamic CDS Archive File with -XX:ArchiveClassesAtExit + +Advantages of dynamic CDS archives are: + +- They usually use less disk space, since they don't need to store the + classes that are already in the static archive. +- They are created with one fewer step than the comparable static archive. + +The following steps create a dynamic CDS archive file that contains the classes +that are used by the `test.Hello` application, excluding those that are already in +the default CDS archive. + +1. Create a dynamic CDS archive, named `hello.jsa`, that contains all the classes + in `hello.jar` loaded by the application `test.Hello`: + + > `java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello` + +2. Run the application `test.Hello` with the shared archive `hello.jsa`: + + > `java -XX:SharedArchiveFile=hello.jsa -cp hello.jar test.Hello` + +3. **Optional** Repeat step 4 of the previous section to verify that the `test.Hello` application is using the class + contained in the `hello.jsa` shared archive. + +It's also possible to create a dynamic CDS archive with a non-default static CDS archive. E.g., + +> `java -XX:SharedArchiveFile=base.jsa -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello` + +To run the application using this dynamic CDS archive: + +> `java -XX:SharedArchiveFile=base.jsa:hello.jsa -cp hello.jar Hello` + +(On Windows, the above path delimiter `:` should be replaced with `;`) + +As mention above, the name of the static archive can be skipped: + +> `java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello` + +#### Creating CDS Archive Files with jcmd + +The previous two sections require you to modify the application's start-up script +in order to create a CDS archive. Sometimes this could be difficult, for example, +if the application's class path is set up by complex routines. + +The `jcmd VM.cds` command provides a less intrusive way for creating a CDS +archive by connecting to a running JVM process. You can create either a +static: + +> `jcmd VM.cds static_dump my_static_archive.jsa` + +or a dynamic archive: + +> `jcmd VM.cds dynamic_dump my_dynamic_archive.jsa` + +To use the resulting archive file in a subsequent run of the application +without modifying the application's start-up script, you can use the +following technique: + +> `env JAVA_TOOL_OPTIONS=-XX:SharedArchiveFile=my_static_archive.jsa bash app_start.sh` + +Note: to use `jcmd VM.cds dynamic_dump`, the JVM process identified by `` +must be started with `-XX:+RecordDynamicDumpInfo`, which can also be passed to the +application start-up script with the same technique: + +> `env JAVA_TOOL_OPTIONS=-XX:+RecordDynamicDumpInfo bash app_start.sh` + + +### Creating Dynamic CDS Archive File with -XX:+AutoCreateSharedArchive + +`-XX:+AutoCreateSharedArchive` is a more convenient way of creating/using +CDS archives. Unlike the methods of manual CDS archive creation described +in the previous section, with `-XX:+AutoCreateSharedArchive`, it's no longer +necessary to have a separate trial run. Instead, you can always run the +application with the same command-line and enjoy the benefits of CDS automatically. + +> `java -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello` + +If the specified archive file exists and was created by the same version of the JDK, +then it will be loaded as a dynamic archive; otherwise it is ignored at VM startup. + +At VM exit, if the specified archive file does not exist, it will be created. +If it exists but was created with a different (but post JDK 19) version of the JDK, +then it will be replaced. In both cases the archive will be ready to be loaded the +next time the JVM is launched with the same command line. + +If the specified archive file exists but was created by a JDK version prior +to JDK 19, then it will be ignored: neither loaded at startup, nor replaced at exit. + +Developers should note that the contents of the CDS archive file are specific +to each build of the JDK. Therefore, if you switch to a different JDK build, +`-XX:+AutoCreateSharedArchive` will automatically recreate the archive to +match the JDK. If you intend to use this feature with an existing +archive, you should make sure that the archive is created by at least version +19 of the JDK. + + +### Restrictions on Class Path and Module Path + +- Neither the class path (`-classpath` and `-Xbootclasspath/a`) + nor the module path (`--module-path`) can contain non-empty directories. + +- Only modular JAR files are supported in `--module-path`. Exploded + modules are not supported. + +- The class path used at archive creation time must be the same as + (or a prefix of) the class path used at run time. (There's no + such requirement for the module path.) + +- The CDS archive cannot be loaded if any JAR files in the class path or + module path are modified after the archive is generated. + +- If any of the VM options `--upgrade-module-path`, `--patch-module` or + `--limit-modules` are specified, CDS is disabled. This means that the + JVM will execute without loading any CDS archives. In addition, if + you try to create a CDS archive with any of these 3 options specified, + the JVM will report an error. + +## Performance Tuning Examples + +You can use the Java advanced runtime options to optimize the performance of +your applications. + +### Tuning for Higher Throughput + +Use the following commands and advanced options to achieve higher +throughput performance for your application: + +> `java -server -XX:+UseParallelGC -XX:+UseLargePages -Xmn10g -Xms26g -Xmx26g` + +### Tuning for Lower Response Time + +Use the following commands and advanced options to achieve lower +response times for your application: + +> `java -XX:+UseG1GC -XX:MaxGCPauseMillis=100` + +### Keeping the Java Heap Small and Reducing the Dynamic Footprint of Embedded Applications + +Use the following advanced runtime options to keep the Java heap small and +reduce the dynamic footprint of embedded applications: + +> `-XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=5` + +> **Note:** The defaults for these two options are 70% and 40% respectively. Because +performance sacrifices can occur when using these small settings, you should +optimize for a small footprint by reducing these settings as much as possible +without introducing unacceptable performance degradation. + +## Exit Status + +The following exit values are typically returned by the launcher when the +launcher is called with the wrong arguments, serious errors, or exceptions +thrown by the JVM. However, a Java application may choose to return any value +by using the API call `System.exit(exitValue)`. The values are: + +- `0`: Successful completion + +- `>0`: An error occurred diff --git a/src/java.base/share/man/keytool.1 b/src/java.base/share/man/keytool.1 deleted file mode 100644 index 63a134eb932..00000000000 --- a/src/java.base/share/man/keytool.1 +++ /dev/null @@ -1,2991 +0,0 @@ -.\" Copyright (c) 1998, 2024, 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. -.\" -'\" t -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "KEYTOOL" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -keytool - a key and certificate management utility -.SH SYNOPSIS -.PP -\f[V]keytool\f[R] [\f[I]commands\f[R]] -.TP -\f[I]commands\f[R] -Commands for \f[V]keytool\f[R] include the following: -.RS -.IP \[bu] 2 -\f[V]-certreq\f[R]: Generates a certificate request -.IP \[bu] 2 -\f[V]-changealias\f[R]: Changes an entry\[aq]s alias -.IP \[bu] 2 -\f[V]-delete\f[R]: Deletes an entry -.IP \[bu] 2 -\f[V]-exportcert\f[R]: Exports certificate -.IP \[bu] 2 -\f[V]-genkeypair\f[R]: Generates a key pair -.IP \[bu] 2 -\f[V]-genseckey\f[R]: Generates a secret key -.IP \[bu] 2 -\f[V]-gencert\f[R]: Generates a certificate from a certificate request -.IP \[bu] 2 -\f[V]-importcert\f[R]: Imports a certificate or a certificate chain -.IP \[bu] 2 -\f[V]-importpass\f[R]: Imports a password -.IP \[bu] 2 -\f[V]-importkeystore\f[R]: Imports one or all entries from another -keystore -.IP \[bu] 2 -\f[V]-keypasswd\f[R]: Changes the key password of an entry -.IP \[bu] 2 -\f[V]-list\f[R]: Lists entries in a keystore -.IP \[bu] 2 -\f[V]-printcert\f[R]: Prints the content of a certificate -.IP \[bu] 2 -\f[V]-printcertreq\f[R]: Prints the content of a certificate request -.IP \[bu] 2 -\f[V]-printcrl\f[R]: Prints the content of a Certificate Revocation List -(CRL) file -.IP \[bu] 2 -\f[V]-storepasswd\f[R]: Changes the store password of a keystore -.IP \[bu] 2 -\f[V]-showinfo\f[R]: Displays security-related information -.IP \[bu] 2 -\f[V]-version\f[R]: Prints the program version -.PP -See \f[B]Commands and Options\f[R] for a description of these commands -with their options. -.RE -.SH DESCRIPTION -.PP -The \f[V]keytool\f[R] command is a key and certificate management -utility. -It enables users to administer their own public/private key pairs and -associated certificates for use in self-authentication (where a user -authenticates themselves to other users and services) or data integrity -and authentication services, by using digital signatures. -The \f[V]keytool\f[R] command also enables users to cache the public -keys (in the form of certificates) of their communicating peers. -.PP -A certificate is a digitally signed statement from one entity (person, -company, and so on), which says that the public key (and some other -information) of some other entity has a particular value. -When data is digitally signed, the signature can be verified to check -the data integrity and authenticity. -Integrity means that the data hasn\[aq]t been modified or tampered with, -and authenticity means that the data comes from the individual who -claims to have created and signed it. -.PP -The \f[V]keytool\f[R] command also enables users to administer secret -keys and passphrases used in symmetric encryption and decryption (Data -Encryption Standard). -It can also display other security-related information. -.PP -The \f[V]keytool\f[R] command stores the keys and certificates in a -keystore. -.PP -The \f[V]keytool\f[R] command uses the -\f[V]jdk.certpath.disabledAlgorithms\f[R] and -\f[V]jdk.security.legacyAlgorithms\f[R] security properties to determine -which algorithms are considered a security risk. -It emits warnings when disabled or legacy algorithms are being used. -The \f[V]jdk.certpath.disabledAlgorithms\f[R] and -\f[V]jdk.security.legacyAlgorithms\f[R] security properties are defined -in the \f[V]java.security\f[R] file (located in the JDK\[aq]s -\f[V]$JAVA_HOME/conf/security\f[R] directory). -.SH COMMAND AND OPTION NOTES -.PP -The following notes apply to the descriptions in \f[B]Commands and -Options\f[R]: -.IP \[bu] 2 -All command and option names are preceded by a hyphen sign -(\f[V]-\f[R]). -.IP \[bu] 2 -Only one command can be provided. -.IP \[bu] 2 -Options for each command can be provided in any order. -.IP \[bu] 2 -There are two kinds of options, one is single-valued which should be -only provided once. -If a single-valued option is provided multiple times, the value of the -last one is used. -The other type is multi-valued, which can be provided multiple times and -all values are used. -The only multi-valued option currently supported is the \f[V]-ext\f[R] -option used to generate X.509v3 certificate extensions. -.IP \[bu] 2 -All items not italicized or in braces ({ }) or brackets ([ ]) are -required to appear as is. -.IP \[bu] 2 -Braces surrounding an option signify that a default value is used when -the option isn\[aq]t specified on the command line. -Braces are also used around the \f[V]-v\f[R], \f[V]-rfc\f[R], and -\f[V]-J\f[R] options, which have meaning only when they appear on the -command line. -They don\[aq]t have any default values. -.IP \[bu] 2 -Brackets surrounding an option signify that the user is prompted for the -values when the option isn\[aq]t specified on the command line. -For the \f[V]-keypass\f[R] option, if you don\[aq]t specify the option -on the command line, then the \f[V]keytool\f[R] command first attempts -to use the keystore password to recover the private/secret key. -If this attempt fails, then the \f[V]keytool\f[R] command prompts you -for the private/secret key password. -.IP \[bu] 2 -Items in italics (option values) represent the actual values that must -be supplied. -For example, here is the format of the \f[V]-printcert\f[R] command: -.RS 2 -.RS -.PP -\f[V]keytool -printcert\f[R] {\f[V]-file\f[R] \f[I]cert_file\f[R]} -{\f[V]-v\f[R]} -.RE -.PP -When you specify a \f[V]-printcert\f[R] command, replace -\f[I]cert_file\f[R] with the actual file name, as follows: -\f[V]keytool -printcert -file VScert.cer\f[R] -.RE -.IP \[bu] 2 -Option values must be enclosed in quotation marks when they contain a -blank (space). -.SH COMMANDS AND OPTIONS -.PP -The keytool commands and their options can be grouped by the tasks that -they perform. -.PP -\f[B]Commands for Creating or Adding Data to the Keystore\f[R]: -.IP \[bu] 2 -\f[V]-gencert\f[R] -.IP \[bu] 2 -\f[V]-genkeypair\f[R] -.IP \[bu] 2 -\f[V]-genseckey\f[R] -.IP \[bu] 2 -\f[V]-importcert\f[R] -.IP \[bu] 2 -\f[V]-importpass\f[R] -.PP -\f[B]Commands for Importing Contents from Another Keystore\f[R]: -.IP \[bu] 2 -\f[V]-importkeystore\f[R] -.PP -\f[B]Commands for Generating a Certificate Request\f[R]: -.IP \[bu] 2 -\f[V]-certreq\f[R] -.PP -\f[B]Commands for Exporting Data\f[R]: -.IP \[bu] 2 -\f[V]-exportcert\f[R] -.PP -\f[B]Commands for Displaying Data\f[R]: -.IP \[bu] 2 -\f[V]-list\f[R] -.IP \[bu] 2 -\f[V]-printcert\f[R] -.IP \[bu] 2 -\f[V]-printcertreq\f[R] -.IP \[bu] 2 -\f[V]-printcrl\f[R] -.PP -\f[B]Commands for Managing the Keystore\f[R]: -.IP \[bu] 2 -\f[V]-storepasswd\f[R] -.IP \[bu] 2 -\f[V]-keypasswd\f[R] -.IP \[bu] 2 -\f[V]-delete\f[R] -.IP \[bu] 2 -\f[V]-changealias\f[R] -.PP -\f[B]Commands for Displaying Security-related Information\f[R]: -.IP \[bu] 2 -\f[V]-showinfo\f[R] -.PP -\f[B]Commands for Displaying Program Version\f[R]: -.IP \[bu] 2 -\f[V]-version\f[R] -.SH COMMANDS FOR CREATING OR ADDING DATA TO THE KEYSTORE -.TP -\f[V]-gencert\f[R] -The following are the available options for the \f[V]-gencert\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-rfc\f[R]}: Output in RFC (Request For Comment) style -.IP \[bu] 2 -{\f[V]-infile\f[R] \f[I]infile\f[R]}: Input file name -.IP \[bu] 2 -{\f[V]-outfile\f[R] \f[I]outfile\f[R]}: Output file name -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -{\f[V]-sigalg\f[R] \f[I]sigalg\f[R]}: Signature algorithm name -.IP \[bu] 2 -{\f[V]-dname\f[R] \f[I]dname\f[R]}: Distinguished name -.IP \[bu] 2 -{\f[V]-startdate\f[R] \f[I]startdate\f[R]}: Certificate validity start -date and time -.IP \[bu] 2 -{\f[V]-ext\f[R] \f[I]ext\f[R]}*: X.509 extension -.IP \[bu] 2 -{\f[V]-validity\f[R] \f[I]days\f[R]}: Validity number of days -.IP \[bu] 2 -[\f[V]-keypass\f[R] \f[I]arg\f[R]]: Key password -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Adds a security provider by name (such as SunPKCS11) -with an optional configure argument. -The value of the security provider is the name of a security provider -that is defined in a module. -.RS 2 -.PP -For example, -.RS -.PP -\f[V]keytool -addprovider SunPKCS11 -providerarg some.cfg ...\f[R] -.RE -.PP -\f[B]Note:\f[R] -.PP -For compatibility reasons, the SunPKCS11 provider can still be loaded -with \f[V]-providerclass sun.security.pkcs11.SunPKCS11\f[R] even if it -is now defined in a module. -This is the only module included in the JDK that needs a configuration, -and therefore the most widely used with the \f[V]-providerclass\f[R] -option. -For legacy security providers located on classpath and loaded by -reflection, \f[V]-providerclass\f[R] should still be used. -.RE -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.RS 2 -.PP -For example, if \f[V]MyProvider\f[R] is a legacy provider loaded via -reflection, -.RS -.PP -\f[V]keytool -providerclass com.example.MyProvider ...\f[R] -.RE -.RE -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-gencert\f[R] command to generate a certificate as a -response to a certificate request file (which can be created by the -\f[V]keytool -certreq\f[R] command). -The command reads the request either from \f[I]infile\f[R] or, if -omitted, from the standard input, signs it by using the alias\[aq]s -private key, and outputs the X.509 certificate into either -\f[I]outfile\f[R] or, if omitted, to the standard output. -When \f[V]-rfc\f[R] is specified, the output format is Base64-encoded -PEM; otherwise, a binary DER is created. -.PP -The \f[V]-sigalg\f[R] value specifies the algorithm that should be used -to sign the certificate. -The \f[I]startdate\f[R] argument is the start time and date that the -certificate is valid. -The \f[I]days\f[R] argument tells the number of days for which the -certificate should be considered valid. -.PP -When \f[I]dname\f[R] is provided, it is used as the subject of the -generated certificate. -Otherwise, the one from the certificate request is used. -.PP -The \f[V]-ext\f[R] value shows what X.509 extensions will be embedded in -the certificate. -Read \f[B]Common Command Options\f[R] for the grammar of \f[V]-ext\f[R]. -.PP -The \f[V]-gencert\f[R] option enables you to create certificate chains. -The following example creates a certificate, \f[V]e1\f[R], that contains -three certificates in its certificate chain. -.PP -The following commands creates four key pairs named \f[V]ca\f[R], -\f[V]ca1\f[R], \f[V]ca2\f[R], and \f[V]e1\f[R]: -.IP -.nf -\f[CB] -keytool -alias ca -dname CN=CA -genkeypair -keyalg rsa -keytool -alias ca1 -dname CN=CA -genkeypair -keyalg rsa -keytool -alias ca2 -dname CN=CA -genkeypair -keyalg rsa -keytool -alias e1 -dname CN=E1 -genkeypair -keyalg rsa -\f[R] -.fi -.PP -The following two commands create a chain of signed certificates; -\f[V]ca\f[R] signs \f[V]ca1\f[R] and \f[V]ca1\f[R] signs \f[V]ca2\f[R], -all of which are self-issued: -.IP -.nf -\f[CB] -keytool -alias ca1 -certreq | - keytool -alias ca -gencert -ext san=dns:ca1 | - keytool -alias ca1 -importcert - -keytool -alias ca2 -certreq | - keytool -alias ca1 -gencert -ext san=dns:ca2 | - keytool -alias ca2 -importcert -\f[R] -.fi -.PP -The following command creates the certificate \f[V]e1\f[R] and stores it -in the \f[V]e1.cert\f[R] file, which is signed by \f[V]ca2\f[R]. -As a result, \f[V]e1\f[R] should contain \f[V]ca\f[R], \f[V]ca1\f[R], -and \f[V]ca2\f[R] in its certificate chain: -.RS -.PP -\f[V]keytool -alias e1 -certreq | keytool -alias ca2 -gencert > e1.cert\f[R] -.RE -.RE -.TP -\f[V]-genkeypair\f[R] -The following are the available options for the \f[V]-genkeypair\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -\f[V]-keyalg\f[R] \f[I]alg\f[R]: Key algorithm name -.IP \[bu] 2 -{\f[V]-keysize\f[R] \f[I]size\f[R]}: Key bit size -.IP \[bu] 2 -{\f[V]-groupname\f[R] \f[I]name\f[R]}: Group name. -For example, an Elliptic Curve name. -.IP \[bu] 2 -{\f[V]-sigalg\f[R] \f[I]alg\f[R]}: Signature algorithm name -.IP \[bu] 2 -{\f[V]-signer\f[R] \f[I]alias\f[R]}: Signer alias -.IP \[bu] 2 -[\f[V]-signerkeypass\f[R] \f[I]arg\f[R]]: Signer key password -.IP \[bu] 2 -[\f[V]-dname\f[R] \f[I]name\f[R]]: Distinguished name -.IP \[bu] 2 -{\f[V]-startdate\f[R] \f[I]date\f[R]}: Certificate validity start date -and time -.IP \[bu] 2 -{\f[V]-ext\f[R] \f[I]value\f[R]}*: X.509 extension -.IP \[bu] 2 -{\f[V]-validity\f[R] \f[I]days\f[R]}: Validity number of days -.IP \[bu] 2 -[\f[V]-keypass\f[R] \f[I]arg\f[R]]: Key password -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]] }: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-genkeypair\f[R] command to generate a key pair (a public -key and associated private key). -When the \f[V]-signer\f[R] option is not specified, the public key is -wrapped in an X.509 v3 self-signed certificate and stored as a -single-element certificate chain. -When the \f[V]-signer\f[R] option is specified, a new certificate is -generated and signed by the designated signer and stored as a -multiple-element certificate chain (containing the generated certificate -itself, and the signer\[aq]s certificate chain). -The certificate chain and private key are stored in a new keystore entry -that is identified by its alias. -.PP -The \f[V]-keyalg\f[R] value specifies the algorithm to be used to -generate the key pair. -The \f[V]-keysize\f[R] value specifies the size of each key to be -generated. -The \f[V]-groupname\f[R] value specifies the named group (for example, -the standard or predefined name of an Elliptic Curve) of the key to be -generated. -.PP -When a \f[V]-keysize\f[R] value is provided, it will be used to -initialize a \f[V]KeyPairGenerator\f[R] object using the -\f[V]initialize(int keysize)\f[R] method. -When a \f[V]-groupname\f[R] value is provided, it will be used to -initialize a \f[V]KeyPairGenerator\f[R] object using the -\f[V]initialize(AlgorithmParameterSpec params)\f[R] method where -\f[V]params\f[R] is \f[V]new NamedParameterSpec(groupname)\f[R]. -.PP -Only one of \f[V]-groupname\f[R] and \f[V]-keysize\f[R] can be -specified. -If an algorithm has multiple named groups that have the same key size, -the \f[V]-groupname\f[R] option should usually be used. -In this case, if \f[V]-keysize\f[R] is specified, it\[aq]s up to the -security provider to determine which named group is chosen when -generating a key pair. -.PP -The \f[V]-sigalg\f[R] value specifies the algorithm that should be used -to sign the certificate. -This algorithm must be compatible with the \f[V]-keyalg\f[R] value. -.PP -The \f[V]-signer\f[R] value specifies the alias of a -\f[V]PrivateKeyEntry\f[R] for the signer that already exists in the -keystore. -This option is used to sign the certificate with the signer\[aq]s -private key. -This is especially useful for key agreement algorithms (i.e. -the \f[V]-keyalg\f[R] value is \f[V]XDH\f[R], \f[V]X25519\f[R], -\f[V]X448\f[R], or \f[V]DH\f[R]) as these keys cannot be used for -digital signatures, and therefore a self-signed certificate cannot be -created. -.PP -The \f[V]-signerkeypass\f[R] value specifies the password of the -signer\[aq]s private key. -It can be specified if the private key of the signer entry is protected -by a password different from the store password. -.PP -The \f[V]-dname\f[R] value specifies the X.500 Distinguished Name to be -associated with the value of \f[V]-alias\f[R]. -If the \f[V]-signer\f[R] option is not specified, the issuer and subject -fields of the self-signed certificate are populated with the specified -distinguished name. -If the \f[V]-signer\f[R] option is specified, the subject field of the -certificate is populated with the specified distinguished name and the -issuer field is populated with the subject field of the signer\[aq]s -certificate. -If a distinguished name is not provided at the command line, then the -user is prompted for one. -.PP -The value of \f[V]-keypass\f[R] is a password used to protect the -private key of the generated key pair. -If a password is not provided, then the user is prompted for it. -If you press the \f[B]Return\f[R] key at the prompt, then the key -password is set to the same password as the keystore password. -The \f[V]-keypass\f[R] value must have at least six characters. -.PP -The value of \f[V]-startdate\f[R] specifies the issue time of the -certificate, also known as the \[dq]Not Before\[dq] value of the X.509 -certificate\[aq]s Validity field. -.PP -The option value can be set in one of these two forms: -.PP -([\f[V]+-\f[R]]\f[I]nnn\f[R][\f[V]ymdHMS\f[R]])+ -.PP -[\f[I]yyyy\f[R]\f[V]/\f[R]\f[I]mm\f[R]\f[V]/\f[R]\f[I]dd\f[R]] -[\f[I]HH\f[R]\f[V]:\f[R]\f[I]MM\f[R]\f[V]:\f[R]\f[I]SS\f[R]] -.PP -With the first form, the issue time is shifted by the specified value -from the current time. -The value is a concatenation of a sequence of subvalues. -Inside each subvalue, the plus sign (+) means shift forward, and the -minus sign (-) means shift backward. -The time to be shifted is \f[I]nnn\f[R] units of years, months, days, -hours, minutes, or seconds (denoted by a single character of -\f[V]y\f[R], \f[V]m\f[R], \f[V]d\f[R], \f[V]H\f[R], \f[V]M\f[R], or -\f[V]S\f[R] respectively). -The exact value of the issue time is calculated by using the -\f[V]java.util.GregorianCalendar.add(int field, int amount)\f[R] method -on each subvalue, from left to right. -For example, the issue time can be specified by: -.IP -.nf -\f[CB] -Calendar c = new GregorianCalendar(); -c.add(Calendar.YEAR, -1); -c.add(Calendar.MONTH, 1); -c.add(Calendar.DATE, -1); -return c.getTime() -\f[R] -.fi -.PP -With the second form, the user sets the exact issue time in two parts, -year/month/day and hour:minute:second (using the local time zone). -The user can provide only one part, which means the other part is the -same as the current date (or time). -The user must provide the exact number of digits shown in the format -definition (padding with 0 when shorter). -When both date and time are provided, there is one (and only one) space -character between the two parts. -The hour should always be provided in 24-hour format. -.PP -When the option isn\[aq]t provided, the start date is the current time. -The option can only be provided one time. -.PP -The value of \f[I]date\f[R] specifies the number of days (starting at -the date specified by \f[V]-startdate\f[R], or the current date when -\f[V]-startdate\f[R] isn\[aq]t specified) for which the certificate -should be considered valid. -.RE -.TP -\f[V]-genseckey\f[R] -The following are the available options for the \f[V]-genseckey\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -[\f[V]-keypass\f[R] \f[I]arg\f[R]]: Key password -.IP \[bu] 2 -\f[V]-keyalg\f[R] \f[I]alg\f[R]: Key algorithm name -.IP \[bu] 2 -{\f[V]-keysize\f[R] \f[I]size\f[R]}: Key bit size -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-genseckey\f[R] command to generate a secret key and store -it in a new \f[V]KeyStore.SecretKeyEntry\f[R] identified by -\f[V]alias\f[R]. -.PP -The value of \f[V]-keyalg\f[R] specifies the algorithm to be used to -generate the secret key, and the value of \f[V]-keysize\f[R] specifies -the size of the key that is generated. -The \f[V]-keypass\f[R] value is a password that protects the secret key. -If a password is not provided, then the user is prompted for it. -If you press the \f[B]Return\f[R] key at the prompt, then the key -password is set to the same password that is used for the -\f[V]-keystore\f[R]. -The \f[V]-keypass\f[R] value must contain at least six characters. -.RE -.TP -\f[V]-importcert\f[R] -The following are the available options for the \f[V]-importcert\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-noprompt\f[R]}: Do not prompt -.IP \[bu] 2 -{\f[V]-trustcacerts\f[R]}: Trust certificates from cacerts -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password is provided through protected mechanism -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -{\f[V]-file\f[R] \f[I]file\f[R]}: Input file name -.IP \[bu] 2 -[\f[V]-keypass\f[R] \f[I]arg\f[R]]: Key password -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-cacerts\f[R]}: Access the cacerts keystore -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.PP -Use the \f[V]-importcert\f[R] command to read the certificate or -certificate chain (where the latter is supplied in a PKCS#7 formatted -reply or in a sequence of X.509 certificates) from \f[V]-file\f[R] -\f[I]file\f[R], and store it in the \f[V]keystore\f[R] entry identified -by \f[V]-alias\f[R]. -If \f[V]-file\f[R] \f[I]file\f[R] is not specified, then the certificate -or certificate chain is read from \f[V]stdin\f[R]. -.PP -The \f[V]keytool\f[R] command can import X.509 v1, v2, and v3 -certificates, and PKCS#7 formatted certificate chains consisting of -certificates of that type. -The data to be imported must be provided either in binary encoding -format or in printable encoding format (also known as Base64 encoding) -as defined by the Internet RFC 1421 standard. -In the latter case, the encoding must be bounded at the beginning by a -string that starts with \f[V]-----BEGIN\f[R], and bounded at the end by -a string that starts with \f[V]-----END\f[R]. -.PP -You import a certificate for two reasons: To add it to the list of -trusted certificates, and to import a certificate reply received from a -certificate authority (CA) as the result of submitting a Certificate -Signing Request (CSR) to that CA. -See the \f[V]-certreq\f[R] command in \f[B]Commands for Generating a -Certificate Request\f[R]. -.PP -The type of import is indicated by the value of the \f[V]-alias\f[R] -option. -If the alias doesn\[aq]t point to a key entry, then the -\f[V]keytool\f[R] command assumes you are adding a trusted certificate -entry. -In this case, the alias shouldn\[aq]t already exist in the keystore. -If the alias does exist, then the \f[V]keytool\f[R] command outputs an -error because a trusted certificate already exists for that alias, and -doesn\[aq]t import the certificate. -If \f[V]-alias\f[R] points to a key entry, then the \f[V]keytool\f[R] -command assumes that you\[aq]re importing a certificate reply. -.RE -.TP -\f[V]-importpass\f[R] -The following are the available options for the \f[V]-importpass\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -[\f[V]-keypass\f[R] \f[I]arg\f[R]]: Key password -.IP \[bu] 2 -{\f[V]-keyalg\f[R] \f[I]alg\f[R]}: Key algorithm name -.IP \[bu] 2 -{\f[V]-keysize\f[R] \f[I]size\f[R]}: Key bit size -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-importpass\f[R] command to imports a passphrase and store -it in a new \f[V]KeyStore.SecretKeyEntry\f[R] identified by -\f[V]-alias\f[R]. -The passphrase may be supplied via the standard input stream; otherwise -the user is prompted for it. -The \f[V]-keypass\f[R] option provides a password to protect the -imported passphrase. -If a password is not provided, then the user is prompted for it. -If you press the \f[B]Return\f[R] key at the prompt, then the key -password is set to the same password as that used for the -\f[V]keystore\f[R]. -The \f[V]-keypass\f[R] value must contain at least six characters. -.RE -.SH COMMANDS FOR IMPORTING CONTENTS FROM ANOTHER KEYSTORE -.TP -\f[V]-importkeystore\f[R] -The following are the available options for the -\f[V]-importkeystore\f[R] command: -.RS -.IP \[bu] 2 -\f[V]-srckeystore\f[R] \f[I]keystore\f[R]: Source keystore name -.IP \[bu] 2 -{\f[V]-destkeystore\f[R] \f[I]keystore\f[R]}: Destination keystore name -.IP \[bu] 2 -{\f[V]-srcstoretype\f[R] \f[I]type\f[R]}: Source keystore type -.IP \[bu] 2 -{\f[V]-deststoretype\f[R] \f[I]type\f[R]}: Destination keystore type -.IP \[bu] 2 -[\f[V]-srcstorepass\f[R] \f[I]arg\f[R]]: Source keystore password -.IP \[bu] 2 -[\f[V]-deststorepass\f[R] \f[I]arg\f[R]]: Destination keystore password -.IP \[bu] 2 -{\f[V]-srcprotected\f[R]}: Source keystore password protected -.IP \[bu] 2 -{\f[V]-destprotected\f[R]}: Destination keystore password protected -.IP \[bu] 2 -{\f[V]-srcprovidername\f[R] \f[I]name\f[R]}: Source keystore provider -name -.IP \[bu] 2 -{\f[V]-destprovidername\f[R] \f[I]name\f[R]}: Destination keystore -provider name -.IP \[bu] 2 -{\f[V]-srcalias\f[R] \f[I]alias\f[R]}: Source alias -.IP \[bu] 2 -{\f[V]-destalias\f[R] \f[I]alias\f[R]}: Destination alias -.IP \[bu] 2 -[\f[V]-srckeypass\f[R] \f[I]arg\f[R]]: Source key password -.IP \[bu] 2 -[\f[V]-destkeypass\f[R] \f[I]arg\f[R]]: Destination key password -.IP \[bu] 2 -{\f[V]-noprompt\f[R]}: Do not prompt -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.PP -\f[B]Note:\f[R] -.PP -This is the first line of all options: -.RS -.PP -\f[V]-srckeystore\f[R] \f[I]keystore\f[R] \f[V]-destkeystore\f[R] -\f[I]keystore\f[R] -.RE -.PP -Use the \f[V]-importkeystore\f[R] command to import a single entry or -all entries from a source keystore to a destination keystore. -.PP -\f[B]Note:\f[R] -.PP -If you do not specify \f[V]-destkeystore\f[R] when using the -\f[V]keytool -importkeystore\f[R] command, then the default keystore -used is \f[V]$HOME/.keystore\f[R]. -.PP -When the \f[V]-srcalias\f[R] option is provided, the command imports the -single entry identified by the alias to the destination keystore. -If a destination alias isn\[aq]t provided with \f[V]-destalias\f[R], -then \f[V]-srcalias\f[R] is used as the destination alias. -If the source entry is protected by a password, then -\f[V]-srckeypass\f[R] is used to recover the entry. -If \f[V]-srckeypass\f[R] isn\[aq]t provided, then the \f[V]keytool\f[R] -command attempts to use \f[V]-srcstorepass\f[R] to recover the entry. -If \f[V]-srcstorepass\f[R] is not provided or is incorrect, then the -user is prompted for a password. -The destination entry is protected with \f[V]-destkeypass\f[R]. -If \f[V]-destkeypass\f[R] isn\[aq]t provided, then the destination entry -is protected with the source entry password. -For example, most third-party tools require \f[V]storepass\f[R] and -\f[V]keypass\f[R] in a PKCS #12 keystore to be the same. -To create a PKCS#12 keystore for these tools, always specify a -\f[V]-destkeypass\f[R] that is the same as \f[V]-deststorepass\f[R]. -.PP -If the \f[V]-srcalias\f[R] option isn\[aq]t provided, then all entries -in the source keystore are imported into the destination keystore. -Each destination entry is stored under the alias from the source entry. -If the source entry is protected by a password, then -\f[V]-srcstorepass\f[R] is used to recover the entry. -If \f[V]-srcstorepass\f[R] is not provided or is incorrect, then the -user is prompted for a password. -If a source keystore entry type isn\[aq]t supported in the destination -keystore, or if an error occurs while storing an entry into the -destination keystore, then the user is prompted either to skip the entry -and continue or to quit. -The destination entry is protected with the source entry password. -.PP -If the destination alias already exists in the destination keystore, -then the user is prompted either to overwrite the entry or to create a -new entry under a different alias name. -.PP -If the \f[V]-noprompt\f[R] option is provided, then the user isn\[aq]t -prompted for a new destination alias. -Existing entries are overwritten with the destination alias name. -Entries that can\[aq]t be imported are skipped and a warning is -displayed. -.RE -.SH COMMANDS FOR GENERATING A CERTIFICATE REQUEST -.TP -\f[V]-certreq\f[R] -The following are the available options for the \f[V]-certreq\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -{\f[V]-sigalg\f[R] \f[I]alg\f[R]}: Signature algorithm name -.IP \[bu] 2 -{\f[V]-file\f[R] \f[I]file\f[R]}: Output file name -.IP \[bu] 2 -[ \f[V]-keypass\f[R] \f[I]arg\f[R]]: Key password -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-dname\f[R] \f[I]name\f[R]}: Distinguished name -.IP \[bu] 2 -{\f[V]-ext\f[R] \f[I]value\f[R]}: X.509 extension -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-certreq\f[R] command to generate a Certificate Signing -Request (CSR) using the PKCS #10 format. -.PP -A CSR is intended to be sent to a CA. -The CA authenticates the certificate requestor (usually offline) and -returns a certificate or certificate chain to replace the existing -certificate chain (initially a self-signed certificate) in the keystore. -.PP -The private key associated with \f[I]alias\f[R] is used to create the -PKCS #10 certificate request. -To access the private key, the correct password must be provided. -If \f[V]-keypass\f[R] isn\[aq]t provided at the command line and is -different from the password used to protect the integrity of the -keystore, then the user is prompted for it. -If \f[V]-dname\f[R] is provided, then it is used as the subject in the -CSR. -Otherwise, the X.500 Distinguished Name associated with alias is used. -.PP -The \f[V]-sigalg\f[R] value specifies the algorithm that should be used -to sign the CSR. -.PP -The CSR is stored in the \f[V]-file\f[R] \f[I]file\f[R]. -If a file is not specified, then the CSR is output to \f[V]-stdout\f[R]. -.PP -Use the \f[V]-importcert\f[R] command to import the response from the -CA. -.RE -.SH COMMANDS FOR EXPORTING DATA -.TP -\f[V]-exportcert\f[R] -The following are the available options for the \f[V]-exportcert\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-rfc\f[R]}: Output in RFC style -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -{\f[V]-file\f[R] \f[I]file\f[R]}: Output file name -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-cacerts\f[R]}: Access the cacerts keystore -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]] }: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-exportcert\f[R] command to read a certificate from the -keystore that is associated with \f[V]-alias\f[R] \f[I]alias\f[R] and -store it in the \f[V]-file\f[R] \f[I]file\f[R]. -When a file is not specified, the certificate is output to -\f[V]stdout\f[R]. -.PP -By default, the certificate is output in binary encoding. -If the \f[V]-rfc\f[R] option is specified, then the output in the -printable encoding format defined by the Internet RFC 1421 Certificate -Encoding Standard. -.PP -If \f[V]-alias\f[R] refers to a trusted certificate, then that -certificate is output. -Otherwise, \f[V]-alias\f[R] refers to a key entry with an associated -certificate chain. -In that case, the first certificate in the chain is returned. -This certificate authenticates the public key of the entity addressed by -\f[V]-alias\f[R]. -.RE -.SH COMMANDS FOR DISPLAYING DATA -.TP -\f[V]-list\f[R] -The following are the available options for the \f[V]-list\f[R] command: -.RS -.IP \[bu] 2 -{\f[V]-rfc\f[R]}: Output in RFC style -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-cacerts\f[R]}: Access the cacerts keystore -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]] }: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-list\f[R] command to print the contents of the keystore -entry identified by \f[V]-alias\f[R] to \f[V]stdout\f[R]. -If \f[V]-alias\f[R] \f[I]alias\f[R] is not specified, then the contents -of the entire keystore are printed. -.PP -By default, this command prints the SHA-256 fingerprint of a -certificate. -If the \f[V]-v\f[R] option is specified, then the certificate is printed -in human-readable format, with additional information such as the owner, -issuer, serial number, and any extensions. -If the \f[V]-rfc\f[R] option is specified, then the certificate contents -are printed by using the printable encoding format, as defined by the -Internet RFC 1421 Certificate Encoding Standard. -.PP -\f[B]Note:\f[R] -.PP -You can\[aq]t specify both \f[V]-v\f[R] and \f[V]-rfc\f[R] in the same -command. -Otherwise, an error is reported. -.RE -.TP -\f[V]-printcert\f[R] -The following are the available options for the \f[V]-printcert\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-rfc\f[R]}: Output in RFC style -.IP \[bu] 2 -{\f[V]-file\f[R] \f[I]cert_file\f[R]}: Input file name -.IP \[bu] 2 -{\f[V]-sslserver\f[R] \f[I]server\f[R][\f[V]:\f[R]\f[I]port\f[R]]}:: -Secure Sockets Layer (SSL) server host and port -.IP \[bu] 2 -{\f[V]-jarfile\f[R] \f[I]JAR_file\f[R]}: Signed \f[V].jar\f[R] file -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-trustcacerts\f[R]}: Trust certificates from cacerts -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password is provided through protected mechanism -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.PP -Use the \f[V]-printcert\f[R] command to read and print the certificate -from \f[V]-file\f[R] \f[I]cert_file\f[R], the SSL server located at -\f[V]-sslserver\f[R] \f[I]server\f[R][\f[V]:\f[R]\f[I]port\f[R]], or the -signed JAR file specified by \f[V]-jarfile\f[R] \f[I]JAR_file\f[R]. -It prints its contents in a human-readable format. -When a port is not specified, the standard HTTPS port 443 is assumed. -.PP -\f[B]Note:\f[R] -.PP -The \f[V]-sslserver\f[R] and \f[V]-file\f[R] options can\[aq]t be -provided in the same command. -Otherwise, an error is reported. -If you don\[aq]t specify either option, then the certificate is read -from \f[V]stdin\f[R]. -.PP -When\f[V]-rfc\f[R] is specified, the \f[V]keytool\f[R] command prints -the certificate in PEM mode as defined by the Internet RFC 1421 -Certificate Encoding standard. -.PP -If the certificate is read from a file or \f[V]stdin\f[R], then it might -be either binary encoded or in printable encoding format, as defined by -the RFC 1421 Certificate Encoding standard. -.PP -If the SSL server is behind a firewall, then the -\f[V]-J-Dhttps.proxyHost=proxyhost\f[R] and -\f[V]-J-Dhttps.proxyPort=proxyport\f[R] options can be specified on the -command line for proxy tunneling. -.PP -\f[B]Note:\f[R] -.PP -This command can be used independently of a keystore. -This command does not check for the weakness of a certificate\[aq]s -signature algorithm if it is a trusted certificate in the user keystore -(specified by \f[V]-keystore\f[R]) or in the \f[V]cacerts\f[R] keystore -(if \f[V]-trustcacerts\f[R] is specified). -.RE -.TP -\f[V]-printcertreq\f[R] -The following are the available options for the \f[V]-printcertreq\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-file\f[R] \f[I]file\f[R]}: Input file name -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.PP -Use the \f[V]-printcertreq\f[R] command to print the contents of a PKCS -#10 format certificate request, which can be generated by the -\f[V]keytool -certreq\f[R] command. -The command reads the request from file. -If there is no file, then the request is read from the standard input. -.RE -.TP -\f[V]-printcrl\f[R] -The following are the available options for the \f[V]-printcrl\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-file crl\f[R]}: Input file name -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-trustcacerts\f[R]}: Trust certificates from cacerts -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password is provided through protected mechanism -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.PP -Use the \f[V]-printcrl\f[R] command to read the Certificate Revocation -List (CRL) from \f[V]-file crl\f[R] . -A CRL is a list of the digital certificates that were revoked by the CA -that issued them. -The CA generates the \f[V]crl\f[R] file. -.PP -\f[B]Note:\f[R] -.PP -This command can be used independently of a keystore. -This command attempts to verify the CRL using a certificate from the -user keystore (specified by \f[V]-keystore\f[R]) or the -\f[V]cacerts\f[R] keystore (if \f[V]-trustcacerts\f[R] is specified), -and will print out a warning if it cannot be verified. -.RE -.SH COMMANDS FOR MANAGING THE KEYSTORE -.TP -\f[V]-storepasswd\f[R] -The following are the available options for the \f[V]-storepasswd\f[R] -command: -.RS -.IP \[bu] 2 -[\f[V]-new\f[R] \f[I]arg\f[R]]: New password -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-cacerts\f[R]}: Access the cacerts keystore -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.PP -Use the \f[V]-storepasswd\f[R] command to change the password used to -protect the integrity of the keystore contents. -The new password is set by \f[V]-new\f[R] \f[I]arg\f[R] and must contain -at least six characters. -.RE -.TP -\f[V]-keypasswd\f[R] -The following are the available options for the \f[V]-keypasswd\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -[\f[V]-keypass\f[R] \f[I]old_keypass\f[R]]: Key password -.IP \[bu] 2 -[\f[V]-new\f[R] \f[I]new_keypass\f[R]]: New password -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-storepass\f[R] \f[I]arg\f[R]}: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.PP -Use the \f[V]-keypasswd\f[R] command to change the password (under which -private/secret keys identified by \f[V]-alias\f[R] are protected) from -\f[V]-keypass\f[R] \f[I]old_keypass\f[R] to \f[V]-new\f[R] -\f[I]new_keypass\f[R]. -The password value must contain at least six characters. -.PP -If the \f[V]-keypass\f[R] option isn\[aq]t provided at the command line -and the \f[V]-keypass\f[R] password is different from the keystore -password (\f[V]-storepass\f[R] \f[I]arg\f[R]), then the user is prompted -for it. -.PP -If the \f[V]-new\f[R] option isn\[aq]t provided at the command line, -then the user is prompted for it. -.RE -.TP -\f[V]-delete\f[R] -The following are the available options for the \f[V]-delete\f[R] -command: -.RS -.IP \[bu] 2 -[\f[V]-alias\f[R] \f[I]alias\f[R]]: Alias name of the entry to process -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-cacerts\f[R]}: Access the cacerts keystore -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-delete\f[R] command to delete the \f[V]-alias\f[R] -\f[I]alias\f[R] entry from the keystore. -When not provided at the command line, the user is prompted for the -\f[V]alias\f[R]. -.RE -.TP -\f[V]-changealias\f[R] -The following are the available options for the \f[V]-changealias\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-alias\f[R] \f[I]alias\f[R]}: Alias name of the entry to process -.IP \[bu] 2 -[\f[V]-destalias\f[R] \f[I]alias\f[R]]: Destination alias -.IP \[bu] 2 -[\f[V]-keypass\f[R] \f[I]arg\f[R]]: Key password -.IP \[bu] 2 -{\f[V]-keystore\f[R] \f[I]keystore\f[R]}: Keystore name -.IP \[bu] 2 -{\f[V]-cacerts\f[R]}: Access the cacerts keystore -.IP \[bu] 2 -[\f[V]-storepass\f[R] \f[I]arg\f[R]]: Keystore password -.IP \[bu] 2 -{\f[V]-storetype\f[R] \f[I]type\f[R]}: Keystore type -.IP \[bu] 2 -{\f[V]-providername\f[R] \f[I]name\f[R]}: Provider name -.IP \[bu] 2 -{\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by name (such as SunPKCS11) with -an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerclass\f[R] \f[I]class\f[R] [\f[V]-providerarg\f[R] -\f[I]arg\f[R]]}: Add security provider by fully qualified class name -with an optional configure argument. -.IP \[bu] 2 -{\f[V]-providerpath\f[R] \f[I]list\f[R]}: Provider classpath -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.IP \[bu] 2 -{\f[V]-protected\f[R]}: Password provided through a protected mechanism -.PP -Use the \f[V]-changealias\f[R] command to move an existing keystore -entry from \f[V]-alias\f[R] \f[I]alias\f[R] to a new -\f[V]-destalias\f[R] \f[I]alias\f[R]. -If a destination alias is not provided, then the command prompts you for -one. -If the original entry is protected with an entry password, then the -password can be supplied with the \f[V]-keypass\f[R] option. -If a key password is not provided, then the \f[V]-storepass\f[R] (if -provided) is attempted first. -If the attempt fails, then the user is prompted for a password. -.RE -.SH COMMANDS FOR DISPLAYING SECURITY-RELATED INFORMATION -.TP -\f[V]-showinfo\f[R] -The following are the available options for the \f[V]-showinfo\f[R] -command: -.RS -.IP \[bu] 2 -{\f[V]-tls\f[R]}: Displays TLS configuration information -.IP \[bu] 2 -{\f[V]-v\f[R]}: Verbose output -.PP -Use the \f[V]-showinfo\f[R] command to display various security-related -information. -The \f[V]-tls\f[R] option displays TLS configurations, such as the list -of enabled protocols and cipher suites. -.RE -.SH COMMANDS FOR DISPLAYING PROGRAM VERSION -.PP -You can use \f[V]-version\f[R] to print the program version of -\f[V]keytool\f[R]. -.SH COMMANDS FOR DISPLAYING HELP INFORMATION -.PP -You can use \f[V]--help\f[R] to display a list of \f[V]keytool\f[R] -commands or to display help information about a specific -\f[V]keytool\f[R] command. -.IP \[bu] 2 -To display a list of \f[V]keytool\f[R] commands, enter: -.RS 2 -.RS -.PP -\f[V]keytool --help\f[R] -.RE -.RE -.IP \[bu] 2 -To display help information about a specific \f[V]keytool\f[R] command, -enter: -.RS 2 -.RS -.PP -\f[V]keytool - --help\f[R] -.RE -.RE -.SH COMMON COMMAND OPTIONS -.PP -The \f[V]-v\f[R] option can appear for all commands except -\f[V]--help\f[R]. -When the \f[V]-v\f[R] option appears, it signifies verbose mode, which -means that more information is provided in the output. -.PP -The \f[V]-J\f[R]\f[I]option\f[R] argument can appear for any command. -When the \f[V]-J\f[R]\f[I]option\f[R] is used, the specified -\f[I]option\f[R] string is passed directly to the Java interpreter. -This option doesn\[aq]t contain any spaces. -It\[aq]s useful for adjusting the execution environment or memory usage. -For a list of possible interpreter options, enter \f[V]java -h\f[R] or -\f[V]java -X\f[R] at the command line. -.PP -These options can appear for all commands operating on a keystore: -.TP -\f[V]-storetype\f[R] \f[I]storetype\f[R] -This qualifier specifies the type of keystore to be instantiated. -.TP -\f[V]-keystore\f[R] \f[I]keystore\f[R] -The keystore location. -.RS -.PP -If the JKS \f[V]storetype\f[R] is used and a keystore file doesn\[aq]t -yet exist, then certain \f[V]keytool\f[R] commands can result in a new -keystore file being created. -For example, if \f[V]keytool -genkeypair\f[R] is called and the -\f[V]-keystore\f[R] option isn\[aq]t specified, the default keystore -file named \f[V].keystore\f[R] is created in the user\[aq]s home -directory if it doesn\[aq]t already exist. -Similarly, if the \f[V]-keystore ks_file\f[R] option is specified but -\f[V]ks_file\f[R] doesn\[aq]t exist, then it is created. -For more information on the JKS \f[V]storetype\f[R], see the -\f[B]KeyStore Implementation\f[R] section in \f[B]KeyStore aliases\f[R]. -.PP -Note that the input stream from the \f[V]-keystore\f[R] option is passed -to the \f[V]KeyStore.load\f[R] method. -If \f[V]NONE\f[R] is specified as the URL, then a null stream is passed -to the \f[V]KeyStore.load\f[R] method. -\f[V]NONE\f[R] should be specified if the keystore isn\[aq]t file-based. -For example, when the keystore resides on a hardware token device. -.RE -.TP -\f[V]-cacerts\f[R] \f[I]cacerts\f[R] -Operates on the \f[I]cacerts\f[R] keystore . -This option is equivalent to \f[V]-keystore\f[R] -\f[I]path_to_cacerts\f[R] \f[V]-storetype\f[R] -\f[I]type_of_cacerts\f[R]. -An error is reported if the \f[V]-keystore\f[R] or \f[V]-storetype\f[R] -option is used with the \f[V]-cacerts\f[R] option. -.TP -\f[V]-storepass\f[R] [\f[V]:env\f[R] | \f[V]:file\f[R] ] \f[I]argument\f[R] -The password that is used to protect the integrity of the keystore. -.RS -.PP -If the modifier \f[V]env\f[R] or \f[V]file\f[R] isn\[aq]t specified, -then the password has the value \f[I]argument\f[R], which must contain -at least six characters. -Otherwise, the password is retrieved as follows: -.IP \[bu] 2 -\f[V]env\f[R]: Retrieve the password from the environment variable named -\f[I]argument\f[R]. -.IP \[bu] 2 -\f[V]file\f[R]: Retrieve the password from the file named -\f[I]argument\f[R]. -.PP -\f[B]Note:\f[R] All other options that require passwords, such as -\f[V]-keypass\f[R], \f[V]-srckeypass\f[R], \f[V]-destkeypass\f[R], -\f[V]-srcstorepass\f[R], and \f[V]-deststorepass\f[R], accept the -\f[V]env\f[R] and \f[V]file\f[R] modifiers. -Remember to separate the password option and the modifier with a colon -(:). -.PP -The password must be provided to all commands that access the keystore -contents. -For such commands, when the \f[V]-storepass\f[R] option isn\[aq]t -provided at the command line, the user is prompted for it. -.PP -When retrieving information from the keystore, the password is optional. -If a password is not specified, then the integrity of the retrieved -information can\[aq]t be verified and a warning is displayed. -.RE -.TP -\f[V]-providername\f[R] \f[I]name\f[R] -Used to identify a cryptographic service provider\[aq]s name when listed -in the security properties file. -.TP -\f[V]-addprovider\f[R] \f[I]name\f[R] -Used to add a security provider by name (such as SunPKCS11) . -.TP -\f[V]-providerclass\f[R] \f[I]class\f[R] -Used to specify the name of a cryptographic service provider\[aq]s -master class file when the service provider isn\[aq]t listed in the -security properties file. -.TP -\f[V]-providerpath\f[R] \f[I]list\f[R] -Used to specify the provider classpath. -.TP -\f[V]-providerarg\f[R] \f[I]arg\f[R] -Used with the \f[V]-addprovider\f[R] or \f[V]-providerclass\f[R] option -to represent an optional string input argument for the constructor of -\f[I]class\f[R] name. -.TP -\f[V]-protected=true\f[R]|\f[V]false\f[R] -Specify this value as \f[V]true\f[R] when a password must be specified -by way of a protected authentication path, such as a dedicated PIN -reader. -Because there are two keystores involved in the -\f[V]-importkeystore\f[R] command, the following two options, -\f[V]-srcprotected\f[R] and \f[V]-destprotected\f[R], are provided for -the source keystore and the destination keystore respectively. -.TP -\f[V]-ext\f[R] {\f[I]name\f[R]{\f[V]:critical\f[R]} {\f[V]=\f[R]\f[I]value\f[R]}} -Denotes an X.509 certificate extension. -The option can be used in \f[V]-genkeypair\f[R] and \f[V]-gencert\f[R] -to embed extensions into the generated certificate, or in -\f[V]-certreq\f[R] to show what extensions are requested in the -certificate request. -The option can appear multiple times. -The \f[I]name\f[R] argument can be a supported extension name (see -\f[B]Supported Named Extensions\f[R]) or an arbitrary OID number. -The \f[I]value\f[R] argument, when provided, denotes the argument for -the extension. -When \f[I]value\f[R] is omitted, the default value of the extension or -the extension itself requires no argument. -The \f[V]:critical\f[R] modifier, when provided, means the -extension\[aq]s \f[V]isCritical\f[R] attribute is \f[V]true\f[R]; -otherwise, it is \f[V]false\f[R]. -You can use \f[V]:c\f[R] in place of \f[V]:critical\f[R]. -.TP -\f[V]-conf\f[R] \f[I]file\f[R] -Specifies a pre-configured options file. -.SH PRE-CONFIGURED OPTIONS FILE -.PP -A pre-configured options file is a Java properties file that can be -specified with the \f[V]-conf\f[R] option. -Each property represents the default option(s) for a keytool command -using \[dq]keytool.\f[I]command_name\f[R]\[dq] as the property name. -A special property named \[dq]keytool.all\[dq] represents the default -option(s) applied to all commands. -A property value can include \f[V]${prop}\f[R] which will be expanded to -the system property associated with it. -If an option value includes white spaces inside, it should be surrounded -by quotation marks (\[dq] or \[aq]). -All property names must be in lower case. -.PP -When \f[V]keytool\f[R] is launched with a pre-configured options file, -the value for \[dq]keytool.all\[dq] (if it exists) is prepended to the -\f[V]keytool\f[R] command line first, with the value for the command -name (if it exists) comes next, and the existing options on the command -line at last. -For a single-valued option, this allows the property for a specific -command to override the \[dq]keytool.all\[dq] value, and the value -specified on the command line to override both. -For multiple-valued options, all of them will be used by -\f[V]keytool\f[R]. -.PP -For example, given the following file named \f[V]preconfig\f[R]: -.IP -.nf -\f[CB] - # A tiny pre-configured options file - keytool.all = -keystore ${user.home}/ks - keytool.list = -v - keytool.genkeypair = -keyalg rsa -\f[R] -.fi -.PP -\f[V]keytool -conf preconfig -list\f[R] is identical to -.RS -.PP -\f[V]keytool -keystore \[ti]/ks -v -list\f[R] -.RE -.PP -\f[V]keytool -conf preconfig -genkeypair -alias me\f[R] is identical to -.RS -.PP -\f[V]keytool -keystore \[ti]/ks -keyalg rsa -genkeypair -alias me\f[R] -.RE -.PP -\f[V]keytool -conf preconfig -genkeypair -alias you -keyalg ec\f[R] is -identical to -.RS -.PP -\f[V]keytool -keystore \[ti]/ks -keyalg rsa -genkeypair -alias you -keyalg ec\f[R] -.RE -.PP -which is equivalent to -.RS -.PP -\f[V]keytool -keystore \[ti]/ks -genkeypair -alias you -keyalg ec\f[R] -.RE -.PP -because \f[V]-keyalg\f[R] is a single-valued option and the \f[V]ec\f[R] -value specified on the command line overrides the preconfigured options -file. -.SH EXAMPLES OF OPTION VALUES -.PP -The following examples show the defaults for various option values: -.IP -.nf -\f[CB] --alias \[dq]mykey\[dq] - --keysize - 2048 (when using -genkeypair and -keyalg is \[dq]DSA\[dq]) - 3072 (when using -genkeypair and -keyalg is \[dq]RSA\[dq], \[dq]RSASSA-PSS\[dq], or \[dq]DH\[dq]) - 384 (when using -genkeypair and -keyalg is \[dq]EC\[dq]) - 56 (when using -genseckey and -keyalg is \[dq]DES\[dq]) - 168 (when using -genseckey and -keyalg is \[dq]DESede\[dq]) - --groupname - ed25519 (when using -genkeypair and -keyalg is \[dq]EdDSA\[dq], key size is 255) - x25519 (when using -genkeypair and -keyalg is \[dq]XDH\[dq], key size is 255) - --validity 90 - --keystore - --destkeystore - --storetype - --file - stdin (if reading) - stdout (if writing) - --protected false -\f[R] -.fi -.PP -When generating a certificate or a certificate request, the default -signature algorithm (\f[V]-sigalg\f[R] option) is derived from the -algorithm of the underlying private key to provide an appropriate level -of security strength as follows: -.PP -Default Signature Algorithms -.TS -tab(@); -l l l. -T{ -keyalg -T}@T{ -key size -T}@T{ -default sigalg -T} -_ -T{ -DSA -T}@T{ -any size -T}@T{ -SHA256withDSA -T} -T{ -RSA -T}@T{ -< 624 -T}@T{ -SHA256withRSA (key size is too small for using SHA-384) -T} -T{ -T}@T{ -<= 7680 -T}@T{ -SHA384withRSA -T} -T{ -T}@T{ -> 7680 -T}@T{ -SHA512withRSA -T} -T{ -EC -T}@T{ -< 512 -T}@T{ -SHA384withECDSA -T} -T{ -T}@T{ ->= 512 -T}@T{ -SHA512withECDSA -T} -T{ -RSASSA-PSS -T}@T{ -< 624 -T}@T{ -RSASSA-PSS (with SHA-256, key size is too small for -T} -T{ -T}@T{ -T}@T{ -using SHA-384) -T} -T{ -T}@T{ -<= 7680 -T}@T{ -RSASSA-PSS (with SHA-384) -T} -T{ -T}@T{ -> 7680 -T}@T{ -RSASSA-PSS (with SHA-512) -T} -T{ -EdDSA -T}@T{ -255 -T}@T{ -Ed25519 -T} -T{ -T}@T{ -448 -T}@T{ -Ed448 -T} -T{ -Ed25519 -T}@T{ -255 -T}@T{ -Ed25519 -T} -T{ -Ed448 -T}@T{ -448 -T}@T{ -Ed448 -T} -.TE -.IP \[bu] 2 -The key size, measured in bits, corresponds to the size of the private -key. -This size is determined by the value of the \f[V]-keysize\f[R] or -\f[V]-groupname\f[R] options or the value derived from a default -setting. -.IP \[bu] 2 -An RSASSA-PSS signature algorithm uses a \f[V]MessageDigest\f[R] -algorithm as its hash and MGF1 algorithms. -.IP \[bu] 2 -If neither a default \f[V]-keysize\f[R] or \f[V]-groupname\f[R] is -defined for an algorithm, the security provider will choose a default -setting. -.PP -\f[B]Note:\f[R] -.PP -To improve out of the box security, default keysize, groupname, and -signature algorithm names are periodically updated to stronger values -with each release of the JDK. -If interoperability with older releases of the JDK is important, make -sure that the defaults are supported by those releases. -Alternatively, you can use the \f[V]-keysize\f[R], \f[V]-groupname\f[R], -or \f[V]-sigalg\f[R] options to override the default values at your own -risk. -.SH SUPPORTED NAMED EXTENSIONS -.PP -The \f[V]keytool\f[R] command supports these named extensions. -The names aren\[aq]t case-sensitive. -.TP -\f[V]BC\f[R] or \f[V]BasicConstraints\f[R] -Values: -.RS -.PP -The full form is -\f[V]ca:\f[R]{\f[V]true\f[R]|\f[V]false\f[R]}[\f[V],pathlen:\f[R]\f[I]len\f[R]] -or \f[I]len\f[R], which is short for -\f[V]ca:true,pathlen:\f[R]\f[I]len\f[R]. -.PP -When \f[I]len\f[R] is omitted, the resulting value is \f[V]ca:true\f[R]. -.RE -.TP -\f[V]KU\f[R] or \f[V]KeyUsage\f[R] -Values: -.RS -.PP -\f[I]usage\f[R](\f[V],\f[R] \f[I]usage\f[R])* -.PP -\f[I]usage\f[R] can be one of the following: -.IP \[bu] 2 -\f[V]digitalSignature\f[R] -.IP \[bu] 2 -\f[V]nonRepudiation\f[R] (\f[V]contentCommitment\f[R]) -.IP \[bu] 2 -\f[V]keyEncipherment\f[R] -.IP \[bu] 2 -\f[V]dataEncipherment\f[R] -.IP \[bu] 2 -\f[V]keyAgreement\f[R] -.IP \[bu] 2 -\f[V]keyCertSign\f[R] -.IP \[bu] 2 -\f[V]cRLSign\f[R] -.IP \[bu] 2 -\f[V]encipherOnly\f[R] -.IP \[bu] 2 -\f[V]decipherOnly\f[R] -.PP -Provided there is no ambiguity, the \f[I]usage\f[R] argument can be -abbreviated with the first few letters (such as \f[V]dig\f[R] for -\f[V]digitalSignature\f[R]) or in camel-case style (such as \f[V]dS\f[R] -for \f[V]digitalSignature\f[R] or \f[V]cRLS\f[R] for \f[V]cRLSign\f[R]). -The \f[I]usage\f[R] values are case-sensitive. -.RE -.TP -\f[V]EKU\f[R] or \f[V]ExtendedKeyUsage\f[R] -Values: -.RS -.PP -\f[I]usage\f[R](\f[V],\f[R] \f[I]usage\f[R])* -.PP -\f[I]usage\f[R] can be one of the following: -.IP \[bu] 2 -\f[V]anyExtendedKeyUsage\f[R] -.IP \[bu] 2 -\f[V]serverAuth\f[R] -.IP \[bu] 2 -\f[V]clientAuth\f[R] -.IP \[bu] 2 -\f[V]codeSigning\f[R] -.IP \[bu] 2 -\f[V]emailProtection\f[R] -.IP \[bu] 2 -\f[V]timeStamping\f[R] -.IP \[bu] 2 -\f[V]OCSPSigning\f[R] -.IP \[bu] 2 -Any OID string -.PP -Provided there is no ambiguity, the \f[I]usage\f[R] argument can be -abbreviated with the first few letters or in camel-case style. -The \f[I]usage\f[R] values are case-sensitive. -.RE -.TP -\f[V]SAN\f[R] or \f[V]SubjectAlternativeName\f[R] -Values: -.RS -.PP -\f[I]type\f[R]\f[V]:\f[R]\f[I]value\f[R](\f[V],\f[R] -\f[I]type\f[R]\f[V]:\f[R]\f[I]value\f[R])* -.PP -\f[I]type\f[R] can be one of the following: -.IP \[bu] 2 -\f[V]EMAIL\f[R] -.IP \[bu] 2 -\f[V]URI\f[R] -.IP \[bu] 2 -\f[V]DNS\f[R] -.IP \[bu] 2 -\f[V]IP\f[R] -.IP \[bu] 2 -\f[V]OID\f[R] -.PP -The \f[I]value\f[R] argument is the string format value for the -\f[I]type\f[R]. -.RE -.TP -\f[V]IAN\f[R] or \f[V]IssuerAlternativeName\f[R] -Values: -.RS -.PP -Same as \f[V]SAN\f[R] or \f[V]SubjectAlternativeName\f[R]. -.RE -.TP -\f[V]SIA\f[R] or \f[V]SubjectInfoAccess\f[R] -Values: -.RS -.PP -\f[I]method\f[R]\f[V]:\f[R]\f[I]location-type\f[R]\f[V]:\f[R]\f[I]location-value\f[R](\f[V],\f[R] -\f[I]method\f[R]\f[V]:\f[R]\f[I]location-type\f[R]\f[V]:\f[R]\f[I]location-value\f[R])* -.PP -\f[I]method\f[R] can be one of the following: -.IP \[bu] 2 -\f[V]timeStamping\f[R] -.IP \[bu] 2 -\f[V]caRepository\f[R] -.IP \[bu] 2 -Any OID -.PP -The \f[I]location-type\f[R] and \f[I]location-value\f[R] arguments can -be any \f[I]type\f[R]\f[V]:\f[R]\f[I]value\f[R] supported by the -\f[V]SubjectAlternativeName\f[R] extension. -.RE -.TP -\f[V]AIA\f[R] or \f[V]AuthorityInfoAccess\f[R] -Values: -.RS -.PP -Same as \f[V]SIA\f[R] or \f[V]SubjectInfoAccess\f[R]. -.PP -The \f[I]method\f[R] argument can be one of the following: -.IP \[bu] 2 -\f[V]ocsp\f[R] -.IP \[bu] 2 -\f[V]caIssuers\f[R] -.IP \[bu] 2 -Any OID -.RE -.PP -When \f[I]name\f[R] is OID, the value is the hexadecimal dumped Definite -Encoding Rules (DER) encoding of the \f[V]extnValue\f[R] for the -extension excluding the OCTET STRING type and length bytes. -Other than standard hexadecimal numbers (0-9, a-f, A-F), any extra -characters are ignored in the HEX string. -Therefore, both 01:02:03:04 and 01020304 are accepted as identical -values. -When there is no value, the extension has an empty value field. -.PP -A special name \f[V]honored\f[R], used only in \f[V]-gencert\f[R], -denotes how the extensions included in the certificate request should be -honored. -The value for this name is a comma-separated list of \f[V]all\f[R] (all -requested extensions are honored), -\f[I]name\f[R]{\f[V]:\f[R][\f[V]critical\f[R]|\f[V]non-critical\f[R]]} -(the named extension is honored, but it uses a different -\f[V]isCritical\f[R] attribute), and \f[V]-name\f[R] (used with -\f[V]all\f[R], denotes an exception). -Requested extensions aren\[aq]t honored by default. -.PP -If, besides the\f[V]-ext honored\f[R] option, another named or OID -\f[V]-ext\f[R] option is provided, this extension is added to those -already honored. -However, if this name (or OID) also appears in the honored value, then -its value and criticality override that in the request. -If an extension of the same type is provided multiple times through -either a name or an OID, only the last extension is used. -.PP -The \f[V]subjectKeyIdentifier\f[R] extension is always created. -For non-self-signed certificates, the \f[V]authorityKeyIdentifier\f[R] -is created. -.PP -\f[B]CAUTION:\f[R] -.PP -Users should be aware that some combinations of extensions (and other -certificate fields) may not conform to the Internet standard. -See \f[B]Certificate Conformance Warning\f[R]. -.SH EXAMPLES OF TASKS IN CREATING A KEYSTORE -.PP -The following examples describe the sequence actions in creating a -keystore for managing public/private key pairs and certificates from -trusted entities. -.IP \[bu] 2 -\f[B]Generating the Key Pair\f[R] -.IP \[bu] 2 -\f[B]Requesting a Signed Certificate from a CA\f[R] -.IP \[bu] 2 -\f[B]Importing a Certificate for the CA\f[R] -.IP \[bu] 2 -\f[B]Importing the Certificate Reply from the CA\f[R] -.IP \[bu] 2 -\f[B]Exporting a Certificate That Authenticates the Public Key\f[R] -.IP \[bu] 2 -\f[B]Importing the Keystore\f[R] -.IP \[bu] 2 -\f[B]Generating Certificates for an SSL Server\f[R] -.SH GENERATING THE KEY PAIR -.PP -Create a keystore and then generate the key pair. -.PP -You can enter the command as a single line such as the following: -.RS -.PP -\f[V]keytool -genkeypair -dname \[dq]cn=myname, ou=mygroup, o=mycompany, c=mycountry\[dq] -alias business -keyalg rsa -keypass\f[R] -\f[I]password\f[R] -\f[V]-keystore /working/mykeystore -storepass password -validity 180\f[R] -.RE -.PP -The command creates the keystore named \f[V]mykeystore\f[R] in the -working directory (provided it doesn\[aq]t already exist), and assigns -it the password specified by \f[V]-keypass\f[R]. -It generates a public/private key pair for the entity whose -distinguished name is \f[V]myname\f[R], \f[V]mygroup\f[R], -\f[V]mycompany\f[R], and a two-letter country code of -\f[V]mycountry\f[R]. -It uses the RSA key generation algorithm to create the keys; both are -3072 bits. -.PP -The command uses the default SHA384withRSA signature algorithm to create -a self-signed certificate that includes the public key and the -distinguished name information. -The certificate is valid for 180 days, and is associated with the -private key in a keystore entry referred to by -\f[V]-alias business\f[R]. -The private key is assigned the password specified by -\f[V]-keypass\f[R]. -.PP -The command is significantly shorter when the option defaults are -accepted. -In this case, only \f[V]-keyalg\f[R] is required, and the defaults are -used for unspecified options that have default values. -You are prompted for any required values. -You could have the following: -.RS -.PP -\f[V]keytool -genkeypair -keyalg rsa\f[R] -.RE -.PP -In this case, a keystore entry with the alias \f[V]mykey\f[R] is -created, with a newly generated key pair and a certificate that is valid -for 90 days. -This entry is placed in your home directory in a keystore named -\f[V].keystore\f[R] . -\f[V].keystore\f[R] is created if it doesn\[aq]t already exist. -You are prompted for the distinguished name information, the keystore -password, and the private key password. -.PP -\f[B]Note:\f[R] -.PP -The rest of the examples assume that you responded to the prompts with -values equal to those specified in the first \f[V]-genkeypair\f[R] -command. -For example, a distinguished name of -\f[V]cn=\f[R]\f[I]myname\f[R]\f[V], ou=\f[R]\f[I]mygroup\f[R]\f[V], o=\f[R]\f[I]mycompany\f[R]\f[V], c=\f[R]\f[I]mycountry\f[R]). -.SH REQUESTING A SIGNED CERTIFICATE FROM A CA -.PP -\f[B]Note:\f[R] -.PP -Generating the key pair created a self-signed certificate; however, a -certificate is more likely to be trusted by others when it is signed by -a CA. -.PP -To get a CA signature, complete the following process: -.IP "1." 3 -Generate a CSR: -.RS 4 -.RS -.PP -\f[V]keytool -certreq -file myname.csr\f[R] -.RE -.PP -This creates a CSR for the entity identified by the default alias -\f[V]mykey\f[R] and puts the request in the file named -\f[V]myname.csr\f[R]. -.RE -.IP "2." 3 -Submit \f[V]myname.csr\f[R] to a CA, such as DigiCert. -.PP -The CA authenticates you, the requestor (usually offline), and returns a -certificate, signed by them, authenticating your public key. -In some cases, the CA returns a chain of certificates, each one -authenticating the public key of the signer of the previous certificate -in the chain. -.SH IMPORTING A CERTIFICATE FOR THE CA -.PP -To import a certificate for the CA, complete the following process: -.IP "1." 3 -Before you import the certificate reply from a CA, you need one or more -trusted certificates either in your keystore or in the \f[V]cacerts\f[R] -keystore file. -See \f[V]-importcert\f[R] in \f[B]Commands\f[R]. -.RS 4 -.IP \[bu] 2 -If the certificate reply is a certificate chain, then you need the top -certificate of the chain. -The root CA certificate that authenticates the public key of the CA. -.IP \[bu] 2 -If the certificate reply is a single certificate, then you need a -certificate for the issuing CA (the one that signed it). -If that certificate isn\[aq]t self-signed, then you need a certificate -for its signer, and so on, up to a self-signed root CA certificate. -.PP -The \f[V]cacerts\f[R] keystore ships with a set of root certificates -issued by the CAs of \f[B]the Oracle Java Root Certificate program\f[R] -[http://www.oracle.com/technetwork/java/javase/javasecarootcertsprogram-1876540.html]. -If you request a signed certificate from a CA, and a certificate -authenticating that CA\[aq]s public key hasn\[aq]t been added to -\f[V]cacerts\f[R], then you must import a certificate from that CA as a -trusted certificate. -.PP -A certificate from a CA is usually self-signed or signed by another CA. -If it is signed by another CA, you need a certificate that authenticates -that CA\[aq]s public key. -.PP -For example, you have obtained a \f[I]X\f[R]\f[V].cer\f[R] file from a -company that is a CA and the file is supposed to be a self-signed -certificate that authenticates that CA\[aq]s public key. -Before you import it as a trusted certificate, you should ensure that -the certificate is valid by: -.IP "1." 3 -Viewing it with the \f[V]keytool -printcert\f[R] command or the -\f[V]keytool -importcert\f[R] command without using the -\f[V]-noprompt\f[R] option. -Make sure that the displayed certificate fingerprints match the expected -fingerprints. -.IP "2." 3 -Calling the person who sent the certificate, and comparing the -fingerprints that you see with the ones that they show or that a secure -public key repository shows. -.PP -Only when the fingerprints are equal is it assured that the certificate -wasn\[aq]t replaced in transit with somebody else\[aq]s certificate -(such as an attacker\[aq]s certificate). -If such an attack takes place, and you didn\[aq]t check the certificate -before you imported it, then you would be trusting anything that the -attacker signed. -.RE -.IP "2." 3 -Replace the self-signed certificate with a certificate chain, where each -certificate in the chain authenticates the public key of the signer of -the previous certificate in the chain, up to a root CA. -.RS 4 -.PP -If you trust that the certificate is valid, then you can add it to your -keystore by entering the following command: -.RS -.PP -\f[V]keytool -importcert -alias\f[R] \f[I]alias\f[R] -\f[V]-file *X*\f[R].cer\[ga] -.RE -.PP -This command creates a trusted certificate entry in the keystore from -the data in the CA certificate file and assigns the values of the -\f[I]alias\f[R] to the entry. -.RE -.SH IMPORTING THE CERTIFICATE REPLY FROM THE CA -.PP -After you import a certificate that authenticates the public key of the -CA that you submitted your certificate signing request to (or there is -already such a certificate in the \f[V]cacerts\f[R] file), you can -import the certificate reply and replace your self-signed certificate -with a certificate chain. -.PP -The certificate chain is one of the following: -.IP \[bu] 2 -Returned by the CA when the CA reply is a chain. -.IP \[bu] 2 -Constructed when the CA reply is a single certificate. -This certificate chain is constructed by using the certificate reply and -trusted certificates available either in the keystore where you import -the reply or in the \f[V]cacerts\f[R] keystore file. -.PP -For example, if you sent your certificate signing request to DigiCert, -then you can import their reply by entering the following command: -.PP -\f[B]Note:\f[R] -.PP -In this example, the returned certificate is named -\f[V]DCmyname.cer\f[R]. -.RS -.PP -\f[V]keytool -importcert -trustcacerts -file DCmyname.cer\f[R] -.RE -.SH EXPORTING A CERTIFICATE THAT AUTHENTICATES THE PUBLIC KEY -.PP -\f[B]Note:\f[R] -.PP -If you used the \f[V]jarsigner\f[R] command to sign a Java Archive (JAR) -file, then clients that use the file will want to authenticate your -signature. -.PP -One way that clients can authenticate you is by importing your public -key certificate into their keystore as a trusted entry. -You can then export the certificate and supply it to your clients. -.PP -For example: -.IP "1." 3 -Copy your certificate to a file named \f[V]myname.cer\f[R] by entering -the following command: -.RS 4 -.PP -\f[B]Note:\f[R] -.PP -In this example, the entry has an alias of \f[V]mykey\f[R]. -.RS -.PP -\f[V]keytool -exportcert -alias mykey -file myname.cer\f[R] -.RE -.RE -.IP "2." 3 -With the certificate and the signed JAR file, a client can use the -\f[V]jarsigner\f[R] command to authenticate your signature. -.SH IMPORTING THE KEYSTORE -.PP -Use the \f[V]importkeystore\f[R] command to import an entire keystore -into another keystore. -This imports all entries from the source keystore, including keys and -certificates, to the destination keystore with a single command. -You can use this command to import entries from a different type of -keystore. -During the import, all new entries in the destination keystore will have -the same alias names and protection passwords (for secret keys and -private keys). -If the \f[V]keytool\f[R] command can\[aq]t recover the private keys or -secret keys from the source keystore, then it prompts you for a -password. -If it detects alias duplication, then it asks you for a new alias, and -you can specify a new alias or simply allow the \f[V]keytool\f[R] -command to overwrite the existing one. -.PP -For example, import entries from a typical JKS type keystore -\f[V]key.jks\f[R] into a PKCS #11 type hardware-based keystore, by -entering the following command: -.RS -.PP -\f[V]keytool -importkeystore -srckeystore key.jks -destkeystore NONE -srcstoretype JKS -deststoretype PKCS11 -srcstorepass\f[R] -\f[I]password\f[R] \f[V]-deststorepass\f[R] \f[I]password\f[R] -.RE -.PP -The \f[V]importkeystore\f[R] command can also be used to import a single -entry from a source keystore to a destination keystore. -In this case, besides the options you used in the previous example, you -need to specify the alias you want to import. -With the \f[V]-srcalias\f[R] option specified, you can also specify the -destination alias name, protection password for a secret or private key, -and the destination protection password you want as follows: -.RS -.PP -\f[V]keytool -importkeystore -srckeystore key.jks -destkeystore NONE -srcstoretype JKS -deststoretype PKCS11 -srcstorepass\f[R] -\f[I]password\f[R] \f[V]-deststorepass\f[R] \f[I]password\f[R] -\f[V]-srcalias myprivatekey -destalias myoldprivatekey -srckeypass\f[R] -\f[I]password\f[R] \f[V]-destkeypass\f[R] \f[I]password\f[R] -\f[V]-noprompt\f[R] -.RE -.SH GENERATING CERTIFICATES FOR AN SSL SERVER -.PP -The following are \f[V]keytool\f[R] commands used to generate key pairs -and certificates for three entities: -.IP \[bu] 2 -Root CA (\f[V]root\f[R]) -.IP \[bu] 2 -Intermediate CA (\f[V]ca\f[R]) -.IP \[bu] 2 -SSL server (\f[V]server\f[R]) -.PP -Ensure that you store all the certificates in the same keystore. -.IP -.nf -\f[CB] -keytool -genkeypair -keystore root.jks -alias root -ext bc:c -keyalg rsa -keytool -genkeypair -keystore ca.jks -alias ca -ext bc:c -keyalg rsa -keytool -genkeypair -keystore server.jks -alias server -keyalg rsa - -keytool -keystore root.jks -alias root -exportcert -rfc > root.pem - -keytool -storepass password -keystore ca.jks -certreq -alias ca | - keytool -storepass password -keystore root.jks - -gencert -alias root -ext BC=0 -rfc > ca.pem -keytool -keystore ca.jks -importcert -alias ca -file ca.pem - -keytool -storepass password -keystore server.jks -certreq -alias server | - keytool -storepass password -keystore ca.jks -gencert -alias ca - -ext ku:c=dig,kE -rfc > server.pem -cat root.pem ca.pem server.pem | - keytool -keystore server.jks -importcert -alias server -\f[R] -.fi -.SH TERMS -.TP -Keystore -A keystore is a storage facility for cryptographic keys and -certificates. -.TP -Keystore entries -Keystores can have different types of entries. -The two most applicable entry types for the \f[V]keytool\f[R] command -include the following: -.RS -.PP -Key entries: Each entry holds very sensitive cryptographic key -information, which is stored in a protected format to prevent -unauthorized access. -Typically, a key stored in this type of entry is a secret key, or a -private key accompanied by the certificate chain for the corresponding -public key. -See \f[B]Certificate Chains\f[R]. -The \f[V]keytool\f[R] command can handle both types of entries, while -the \f[V]jarsigner\f[R] tool only handles the latter type of entry, that -is private keys and their associated certificate chains. -.PP -Trusted certificate entries: Each entry contains a single public key -certificate that belongs to another party. -The entry is called a trusted certificate because the keystore owner -trusts that the public key in the certificate belongs to the identity -identified by the subject (owner) of the certificate. -The issuer of the certificate vouches for this, by signing the -certificate. -.RE -.TP -Keystore aliases -All keystore entries (key and trusted certificate entries) are accessed -by way of unique aliases. -.RS -.PP -An alias is specified when you add an entity to the keystore with the -\f[V]-genseckey\f[R] command to generate a secret key, the -\f[V]-genkeypair\f[R] command to generate a key pair (public and private -key), or the \f[V]-importcert\f[R] command to add a certificate or -certificate chain to the list of trusted certificates. -Subsequent \f[V]keytool\f[R] commands must use this same alias to refer -to the entity. -.PP -For example, you can use the alias \f[V]duke\f[R] to generate a new -public/private key pair and wrap the public key into a self-signed -certificate with the following command. -See \f[B]Certificate Chains\f[R]. -.RS -.PP -\f[V]keytool -genkeypair -alias duke -keyalg rsa -keypass\f[R] -\f[I]passwd\f[R] -.RE -.PP -This example specifies an initial \f[I]passwd\f[R] required by -subsequent commands to access the private key associated with the alias -\f[V]duke\f[R]. -If you later want to change Duke\[aq]s private key password, use a -command such as the following: -.RS -.PP -\f[V]keytool -keypasswd -alias duke -keypass\f[R] \f[I]passwd\f[R] -\f[V]-new\f[R] \f[I]newpasswd\f[R] -.RE -.PP -This changes the initial \f[I]passwd\f[R] to \f[I]newpasswd\f[R]. -A password shouldn\[aq]t be specified on a command line or in a script -unless it is for testing purposes, or you are on a secure system. -If you don\[aq]t specify a required password option on a command line, -then you are prompted for it. -.RE -.TP -Keystore implementation -The \f[V]KeyStore\f[R] class provided in the \f[V]java.security\f[R] -package supplies well-defined interfaces to access and modify the -information in a keystore. -It is possible for there to be multiple different concrete -implementations, where each implementation is that for a particular type -of keystore. -.RS -.PP -Currently, two command-line tools (\f[V]keytool\f[R] and -\f[V]jarsigner\f[R]) make use of keystore implementations. -Because the \f[V]KeyStore\f[R] class is \f[V]public\f[R], users can -write additional security applications that use it. -.PP -In JDK 9 and later, the default keystore implementation is -\f[V]PKCS12\f[R]. -This is a cross platform keystore based on the RSA PKCS12 Personal -Information Exchange Syntax Standard. -This standard is primarily meant for storing or transporting a -user\[aq]s private keys, certificates, and miscellaneous secrets. -There is another built-in implementation, provided by Oracle. -It implements the keystore as a file with a proprietary keystore type -(format) named \f[V]JKS\f[R]. -It protects each private key with its individual password, and also -protects the integrity of the entire keystore with a (possibly -different) password. -.PP -Keystore implementations are provider-based. -More specifically, the application interfaces supplied by -\f[V]KeyStore\f[R] are implemented in terms of a Service Provider -Interface (SPI). -That is, there is a corresponding abstract \f[V]KeystoreSpi\f[R] class, -also in the \f[V]java.security package\f[R], which defines the Service -Provider Interface methods that providers must implement. -The term \f[I]provider\f[R] refers to a package or a set of packages -that supply a concrete implementation of a subset of services that can -be accessed by the Java Security API. -To provide a keystore implementation, clients must implement a provider -and supply a \f[V]KeystoreSpi\f[R] subclass implementation, as described -in Steps to Implement and Integrate a Provider. -.PP -Applications can choose different types of keystore implementations from -different providers, using the \f[V]getInstance\f[R] factory method -supplied in the \f[V]KeyStore\f[R] class. -A keystore type defines the storage and data format of the keystore -information, and the algorithms used to protect private/secret keys in -the keystore and the integrity of the keystore. -Keystore implementations of different types aren\[aq]t compatible. -.PP -The \f[V]keytool\f[R] command works on any file-based keystore -implementation. -It treats the keystore location that is passed to it at the command line -as a file name and converts it to a \f[V]FileInputStream\f[R], from -which it loads the keystore information.)The \f[V]jarsigner\f[R] -commands can read a keystore from any location that can be specified -with a URL. -.PP -For \f[V]keytool\f[R] and \f[V]jarsigner\f[R], you can specify a -keystore type at the command line, with the \f[V]-storetype\f[R] option. -.PP -If you don\[aq]t explicitly specify a keystore type, then the tools -choose a keystore implementation based on the value of the -\f[V]keystore.type\f[R] property specified in the security properties -file. -The security properties file is called \f[V]java.security\f[R], and -resides in the security properties directory: -.IP \[bu] 2 -\f[B]Linux and macOS:\f[R] \f[V]java.home/lib/security\f[R] -.IP \[bu] 2 -\f[B]Windows:\f[R] \f[V]java.home\[rs]lib\[rs]security\f[R] -.PP -Each tool gets the \f[V]keystore.type\f[R] value and then examines all -the currently installed providers until it finds one that implements a -keystores of that type. -It then uses the keystore implementation from that provider.The -\f[V]KeyStore\f[R] class defines a static method named -\f[V]getDefaultType\f[R] that lets applications retrieve the value of -the \f[V]keystore.type\f[R] property. -The following line of code creates an instance of the default keystore -type as specified in the \f[V]keystore.type\f[R] property: -.RS -.PP -\f[V]KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());\f[R] -.RE -.PP -The default keystore type is \f[V]pkcs12\f[R], which is a cross-platform -keystore based on the RSA PKCS12 Personal Information Exchange Syntax -Standard. -This is specified by the following line in the security properties file: -.RS -.PP -\f[V]keystore.type=pkcs12\f[R] -.RE -.PP -To have the tools utilize a keystore implementation other than the -default, you can change that line to specify a different keystore type. -For example, if you want to use the Oracle\[aq]s \f[V]jks\f[R] keystore -implementation, then change the line to the following: -.RS -.PP -\f[V]keystore.type=jks\f[R] -.RE -.PP -\f[B]Note:\f[R] -.PP -Case doesn\[aq]t matter in keystore type designations. -For example, \f[V]JKS\f[R] would be considered the same as -\f[V]jks\f[R]. -.RE -.TP -Certificate -A certificate (or public-key certificate) is a digitally signed -statement from one entity (the issuer), saying that the public key and -some other information of another entity (the subject) has some specific -value. -The following terms are related to certificates: -.RS -.IP \[bu] 2 -Public Keys: These are numbers associated with a particular entity, and -are intended to be known to everyone who needs to have trusted -interactions with that entity. -Public keys are used to verify signatures. -.IP \[bu] 2 -Digitally Signed: If some data is digitally signed, then it is stored -with the identity of an entity and a signature that proves that entity -knows about the data. -The data is rendered unforgeable by signing with the entity\[aq]s -private key. -.IP \[bu] 2 -Identity: A known way of addressing an entity. -In some systems, the identity is the public key, and in others it can be -anything from an Oracle Solaris UID to an email address to an X.509 -distinguished name. -.IP \[bu] 2 -Signature: A signature is computed over some data using the private key -of an entity. -The signer, which in the case of a certificate is also known as the -issuer. -.IP \[bu] 2 -Private Keys: These are numbers, each of which is supposed to be known -only to the particular entity whose private key it is (that is, it is -supposed to be kept secret). -Private and public keys exist in pairs in all public key cryptography -systems (also referred to as public key crypto systems). -In a typical public key crypto system, such as DSA, a private key -corresponds to exactly one public key. -Private keys are used to compute signatures. -.IP \[bu] 2 -Entity: An entity is a person, organization, program, computer, -business, bank, or something else you are trusting to some degree. -.PP -Public key cryptography requires access to users\[aq] public keys. -In a large-scale networked environment, it is impossible to guarantee -that prior relationships between communicating entities were established -or that a trusted repository exists with all used public keys. -Certificates were invented as a solution to this public key distribution -problem. -Now a Certification Authority (CA) can act as a trusted third party. -CAs are entities such as businesses that are trusted to sign (issue) -certificates for other entities. -It is assumed that CAs only create valid and reliable certificates -because they are bound by legal agreements. -There are many public Certification Authorities, such as DigiCert, -Comodo, Entrust, and so on. -.PP -You can also run your own Certification Authority using products such as -Microsoft Certificate Server or the Entrust CA product for your -organization. -With the \f[V]keytool\f[R] command, it is possible to display, import, -and export certificates. -It is also possible to generate self-signed certificates. -.PP -The \f[V]keytool\f[R] command currently handles X.509 certificates. -.RE -.TP -X.509 Certificates -The X.509 standard defines what information can go into a certificate -and describes how to write it down (the data format). -All the data in a certificate is encoded with two related standards -called ASN.1/DER. -Abstract Syntax Notation 1 describes data. -The Definite Encoding Rules describe a single way to store and transfer -that data. -.RS -.PP -All X.509 certificates have the following data, in addition to the -signature: -.IP \[bu] 2 -Version: This identifies which version of the X.509 standard applies to -this certificate, which affects what information can be specified in it. -Thus far, three versions are defined. -The \f[V]keytool\f[R] command can import and export v1, v2, and v3 -certificates. -It generates v3 certificates. -.RS 2 -.IP \[bu] 2 -X.509 Version 1 has been available since 1988, is widely deployed, and -is the most generic. -.IP \[bu] 2 -X.509 Version 2 introduced the concept of subject and issuer unique -identifiers to handle the possibility of reuse of subject or issuer -names over time. -Most certificate profile documents strongly recommend that names not be -reused and that certificates shouldn\[aq]t make use of unique -identifiers. -Version 2 certificates aren\[aq]t widely used. -.IP \[bu] 2 -X.509 Version 3 is the most recent (1996) and supports the notion of -extensions where anyone can define an extension and include it in the -certificate. -Some common extensions are: KeyUsage (limits the use of the keys to -particular purposes such as \f[V]signing-only\f[R]) and AlternativeNames -(allows other identities to also be associated with this public key, for -example. -DNS names, email addresses, IP addresses). -Extensions can be marked critical to indicate that the extension should -be checked and enforced or used. -For example, if a certificate has the KeyUsage extension marked critical -and set to \f[V]keyCertSign\f[R], then when this certificate is -presented during SSL communication, it should be rejected because the -certificate extension indicates that the associated private key should -only be used for signing certificates and not for SSL use. -.RE -.IP \[bu] 2 -Serial number: The entity that created the certificate is responsible -for assigning it a serial number to distinguish it from other -certificates it issues. -This information is used in numerous ways. -For example, when a certificate is revoked its serial number is placed -in a Certificate Revocation List (CRL). -.IP \[bu] 2 -Signature algorithm identifier: This identifies the algorithm used by -the CA to sign the certificate. -.IP \[bu] 2 -Issuer name: The X.500 Distinguished Name of the entity that signed the -certificate. -This is typically a CA. -Using this certificate implies trusting the entity that signed this -certificate. -In some cases, such as root or top-level CA certificates, the issuer -signs its own certificate. -.IP \[bu] 2 -Validity period: Each certificate is valid only for a limited amount of -time. -This period is described by a start date and time and an end date and -time, and can be as short as a few seconds or almost as long as a -century. -The validity period chosen depends on a number of factors, such as the -strength of the private key used to sign the certificate, or the amount -one is willing to pay for a certificate. -This is the expected period that entities can rely on the public value, -when the associated private key has not been compromised. -.IP \[bu] 2 -Subject name: The name of the entity whose public key the certificate -identifies. -This name uses the X.500 standard, so it is intended to be unique across -the Internet. -This is the X.500 Distinguished Name (DN) of the entity. -For example, -.RS 2 -.RS -.PP -\f[V]CN=Java Duke, OU=Java Software Division, O=Oracle Corporation, C=US\f[R] -.RE -.PP -These refer to the subject\[aq]s common name (CN), organizational unit -(OU), organization (O), and country (C). -.RE -.IP \[bu] 2 -Subject public key information: This is the public key of the entity -being named with an algorithm identifier that specifies which public key -crypto system this key belongs to and any associated key parameters. -.RE -.TP -Certificate Chains -The \f[V]keytool\f[R] command can create and manage keystore key entries -that each contain a private key and an associated certificate chain. -The first certificate in the chain contains the public key that -corresponds to the private key. -.RS -.PP -When keys are first generated, the chain usually starts off containing a -single element, a self-signed certificate. -See -genkeypair in \f[B]Commands\f[R]. -A self-signed certificate is one for which the issuer (signer) is the -same as the subject. -The subject is the entity whose public key is being authenticated by the -certificate. -When the \f[V]-genkeypair\f[R] command is called to generate a new -public/private key pair, it also wraps the public key into a self-signed -certificate (unless the \f[V]-signer\f[R] option is specified). -.PP -Later, after a Certificate Signing Request (CSR) was generated with the -\f[V]-certreq\f[R] command and sent to a Certification Authority (CA), -the response from the CA is imported with \f[V]-importcert\f[R], and the -self-signed certificate is replaced by a chain of certificates. -At the bottom of the chain is the certificate (reply) issued by the CA -authenticating the subject\[aq]s public key. -The next certificate in the chain is one that authenticates the CA\[aq]s -public key. -.PP -In many cases, this is a self-signed certificate, which is a certificate -from the CA authenticating its own public key, and the last certificate -in the chain. -In other cases, the CA might return a chain of certificates. -In this case, the bottom certificate in the chain is the same (a -certificate signed by the CA, authenticating the public key of the key -entry), but the second certificate in the chain is a certificate signed -by a different CA that authenticates the public key of the CA you sent -the CSR to. -The next certificate in the chain is a certificate that authenticates -the second CA\[aq]s key, and so on, until a self-signed root certificate -is reached. -Each certificate in the chain (after the first) authenticates the public -key of the signer of the previous certificate in the chain. -.PP -Many CAs only return the issued certificate, with no supporting chain, -especially when there is a flat hierarchy (no intermediates CAs). -In this case, the certificate chain must be established from trusted -certificate information already stored in the keystore. -.PP -A different reply format (defined by the PKCS #7 standard) includes the -supporting certificate chain in addition to the issued certificate. -Both reply formats can be handled by the \f[V]keytool\f[R] command. -.PP -The top-level (root) CA certificate is self-signed. -However, the trust into the root\[aq]s public key doesn\[aq]t come from -the root certificate itself, but from other sources such as a newspaper. -This is because anybody could generate a self-signed certificate with -the distinguished name of, for example, the DigiCert root CA. -The root CA public key is widely known. -The only reason it is stored in a certificate is because this is the -format understood by most tools, so the certificate in this case is only -used as a vehicle to transport the root CA\[aq]s public key. -Before you add the root CA certificate to your keystore, you should view -it with the \f[V]-printcert\f[R] option and compare the displayed -fingerprint with the well-known fingerprint obtained from a newspaper, -the root CA\[aq]s Web page, and so on. -.RE -.TP -cacerts Certificates File -A certificates file named \f[V]cacerts\f[R] resides in the security -properties directory: -.RS -.IP \[bu] 2 -\f[B]Linux and macOS:\f[R] \f[I]JAVA_HOME\f[R]\f[V]/lib/security\f[R] -.IP \[bu] 2 -\f[B]Windows:\f[R] \f[I]JAVA_HOME\f[R]\f[V]\[rs]lib\[rs]security\f[R] -.PP -The \f[V]cacerts\f[R] file represents a system-wide keystore with CA -certificates. -System administrators can configure and manage that file with the -\f[V]keytool\f[R] command by specifying \f[V]jks\f[R] as the keystore -type. -The \f[V]cacerts\f[R] keystore file ships with a default set of root CA -certificates. -For Linux, macOS, and Windows, you can list the default certificates -with the following command: -.RS -.PP -\f[V]keytool -list -cacerts\f[R] -.RE -.PP -The initial password of the \f[V]cacerts\f[R] keystore file is -\f[V]changeit\f[R]. -System administrators should change that password and the default access -permission of that file upon installing the SDK. -.PP -\f[B]Note:\f[R] -.PP -It is important to verify your \f[V]cacerts\f[R] file. -Because you trust the CAs in the \f[V]cacerts\f[R] file as entities for -signing and issuing certificates to other entities, you must manage the -\f[V]cacerts\f[R] file carefully. -The \f[V]cacerts\f[R] file should contain only certificates of the CAs -you trust. -It is your responsibility to verify the trusted root CA certificates -bundled in the \f[V]cacerts\f[R] file and make your own trust decisions. -.PP -To remove an untrusted CA certificate from the \f[V]cacerts\f[R] file, -use the \f[V]-delete\f[R] option of the \f[V]keytool\f[R] command. -You can find the \f[V]cacerts\f[R] file in the JDK\[aq]s -\f[V]$JAVA_HOME/lib/security\f[R] directory. -Contact your system administrator if you don\[aq]t have permission to -edit this file. -.RE -.TP -Internet RFC 1421 Certificate Encoding Standard -Certificates are often stored using the printable encoding format -defined by the Internet RFC 1421 standard, instead of their binary -encoding. -This certificate format, also known as Base64 encoding, makes it easy to -export certificates to other applications by email or through some other -mechanism. -.RS -.PP -Certificates read by the \f[V]-importcert\f[R] and \f[V]-printcert\f[R] -commands can be in either this format or binary encoded. -The \f[V]-exportcert\f[R] command by default outputs a certificate in -binary encoding, but will instead output a certificate in the printable -encoding format, when the \f[V]-rfc\f[R] option is specified. -.PP -The \f[V]-list\f[R] command by default prints the SHA-256 fingerprint of -a certificate. -If the \f[V]-v\f[R] option is specified, then the certificate is printed -in human-readable format. -If the \f[V]-rfc\f[R] option is specified, then the certificate is -output in the printable encoding format. -.PP -In its printable encoding format, the encoded certificate is bounded at -the beginning and end by the following text: -.IP -.nf -\f[CB] ------BEGIN CERTIFICATE----- - -encoded certificate goes here. - ------END CERTIFICATE----- -\f[R] -.fi -.RE -.TP -X.500 Distinguished Names -X.500 Distinguished Names are used to identify entities, such as those -that are named by the \f[V]subject\f[R] and \f[V]issuer\f[R] (signer) -fields of X.509 certificates. -The \f[V]keytool\f[R] command supports the following subparts: -.RS -.IP \[bu] 2 -commonName: The common name of a person such as Susan Jones. -.IP \[bu] 2 -organizationUnit: The small organization (such as department or -division) name. -For example, Purchasing. -.IP \[bu] 2 -localityName: The locality (city) name, for example, Palo Alto. -.IP \[bu] 2 -stateName: State or province name, for example, California. -.IP \[bu] 2 -country: Two-letter country code, for example, CH. -.PP -When you supply a distinguished name string as the value of a -\f[V]-dname\f[R] option, such as for the \f[V]-genkeypair\f[R] command, -the string must be in the following format: -.RS -.PP -\f[V]CN=cName, OU=orgUnit, O=org, L=city, S=state, C=countryCode\f[R] -.RE -.PP -All the following items represent actual values and the previous -keywords are abbreviations for the following: -.IP -.nf -\f[CB] -CN=commonName -OU=organizationUnit -O=organizationName -L=localityName -S=stateName -C=country -\f[R] -.fi -.PP -A sample distinguished name string is: -.RS -.PP -\f[V]CN=Mark Smith, OU=Java, O=Oracle, L=Cupertino, S=California, C=US\f[R] -.RE -.PP -A sample command using such a string is: -.RS -.PP -\f[V]keytool -genkeypair -dname \[dq]CN=Mark Smith, OU=Java, O=Oracle, L=Cupertino, S=California, C=US\[dq] -alias mark -keyalg rsa\f[R] -.RE -.PP -Case doesn\[aq]t matter for the keyword abbreviations. -For example, CN, cn, and Cn are all treated the same. -.PP -Order matters; each subcomponent must appear in the designated order. -However, it isn\[aq]t necessary to have all the subcomponents. -You can use a subset, for example: -.RS -.PP -\f[V]CN=Smith, OU=Java, O=Oracle, C=US\f[R] -.RE -.PP -If a distinguished name string value contains a comma, then the comma -must be escaped by a backslash (\[rs]) character when you specify the -string on a command line, as in: -.RS -.PP -\f[V]cn=Jack, ou=Java\[rs], Product Development, o=Oracle, c=US\f[R] -.RE -.PP -It is never necessary to specify a distinguished name string on a -command line. -When the distinguished name is needed for a command, but not supplied on -the command line, the user is prompted for each of the subcomponents. -In this case, a comma doesn\[aq]t need to be escaped by a backslash -(\[rs]). -.RE -.SH WARNINGS -.SH IMPORTING TRUSTED CERTIFICATES WARNING -.PP -\f[B]Important\f[R]: Be sure to check a certificate very carefully -before importing it as a trusted certificate. -.PP -\f[B]Windows Example:\f[R] -.PP -View the certificate first with the \f[V]-printcert\f[R] command or the -\f[V]-importcert\f[R] command without the \f[V]-noprompt\f[R] option. -Ensure that the displayed certificate fingerprints match the expected -ones. -For example, suppose someone sends or emails you a certificate that you -put it in a file named \f[V]\[rs]tmp\[rs]cert\f[R]. -Before you consider adding the certificate to your list of trusted -certificates, you can execute a \f[V]-printcert\f[R] command to view its -fingerprints, as follows: -.IP -.nf -\f[CB] - keytool -printcert -file \[rs]tmp\[rs]cert - Owner: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll - Issuer: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll - Serial Number: 59092b34 - Valid from: Thu Jun 24 18:01:13 PDT 2016 until: Wed Jun 23 17:01:13 PST 2016 - Certificate Fingerprints: - - SHA-1: 20:B6:17:FA:EF:E5:55:8A:D0:71:1F:E8:D6:9D:C0:37:13:0E:5E:FE - SHA-256: 90:7B:70:0A:EA:DC:16:79:92:99:41:FF:8A:FE:EB:90: - 17:75:E0:90:B2:24:4D:3A:2A:16:A6:E4:11:0F:67:A4 -\f[R] -.fi -.PP -\f[B]Linux Example:\f[R] -.PP -View the certificate first with the \f[V]-printcert\f[R] command or the -\f[V]-importcert\f[R] command without the \f[V]-noprompt\f[R] option. -Ensure that the displayed certificate fingerprints match the expected -ones. -For example, suppose someone sends or emails you a certificate that you -put it in a file named \f[V]/tmp/cert\f[R]. -Before you consider adding the certificate to your list of trusted -certificates, you can execute a \f[V]-printcert\f[R] command to view its -fingerprints, as follows: -.IP -.nf -\f[CB] - keytool -printcert -file /tmp/cert - Owner: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll - Issuer: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll - Serial Number: 59092b34 - Valid from: Thu Jun 24 18:01:13 PDT 2016 until: Wed Jun 23 17:01:13 PST 2016 - Certificate Fingerprints: - - SHA-1: 20:B6:17:FA:EF:E5:55:8A:D0:71:1F:E8:D6:9D:C0:37:13:0E:5E:FE - SHA-256: 90:7B:70:0A:EA:DC:16:79:92:99:41:FF:8A:FE:EB:90: - 17:75:E0:90:B2:24:4D:3A:2A:16:A6:E4:11:0F:67:A4 -\f[R] -.fi -.PP -Then call or otherwise contact the person who sent the certificate and -compare the fingerprints that you see with the ones that they show. -Only when the fingerprints are equal is it guaranteed that the -certificate wasn\[aq]t replaced in transit with somebody else\[aq]s -certificate such as an attacker\[aq]s certificate. -If such an attack took place, and you didn\[aq]t check the certificate -before you imported it, then you would be trusting anything the attacker -signed, for example, a JAR file with malicious class files inside. -.PP -\f[B]Note:\f[R] -.PP -It isn\[aq]t required that you execute a \f[V]-printcert\f[R] command -before importing a certificate. -This is because before you add a certificate to the list of trusted -certificates in the keystore, the \f[V]-importcert\f[R] command prints -out the certificate information and prompts you to verify it. -You can then stop the import operation. -However, you can do this only when you call the \f[V]-importcert\f[R] -command without the \f[V]-noprompt\f[R] option. -If the \f[V]-noprompt\f[R] option is specified, then there is no -interaction with the user. -.SH PASSWORDS WARNING -.PP -Most commands that operate on a keystore require the store password. -Some commands require a private/secret key password. -Passwords can be specified on the command line in the -\f[V]-storepass\f[R] and \f[V]-keypass\f[R] options. -However, a password shouldn\[aq]t be specified on a command line or in a -script unless it is for testing, or you are on a secure system. -When you don\[aq]t specify a required password option on a command line, -you are prompted for it. -.SH CERTIFICATE CONFORMANCE WARNING -.PP -\f[B]Internet X.509 Public Key Infrastructure Certificate and -Certificate Revocation List (CRL) Profile\f[R] -[https://tools.ietf.org/rfc/rfc5280.txt] defined a profile on conforming -X.509 certificates, which includes what values and value combinations -are valid for certificate fields and extensions. -.PP -The \f[V]keytool\f[R] command doesn\[aq]t enforce all of these rules so -it can generate certificates that don\[aq]t conform to the standard, -such as self-signed certificates that would be used for internal testing -purposes. -Certificates that don\[aq]t conform to the standard might be rejected by -the JDK or other applications. -Users should ensure that they provide the correct options for -\f[V]-dname\f[R], \f[V]-ext\f[R], and so on. -.SH IMPORT A NEW TRUSTED CERTIFICATE -.PP -Before you add the certificate to the keystore, the \f[V]keytool\f[R] -command verifies it by attempting to construct a chain of trust from -that certificate to a self-signed certificate (belonging to a root CA), -using trusted certificates that are already available in the keystore. -.PP -If the \f[V]-trustcacerts\f[R] option was specified, then additional -certificates are considered for the chain of trust, namely the -certificates in a file named \f[V]cacerts\f[R]. -.PP -If the \f[V]keytool\f[R] command fails to establish a trust path from -the certificate to be imported up to a self-signed certificate (either -from the keystore or the \f[V]cacerts\f[R] file), then the certificate -information is printed, and the user is prompted to verify it by -comparing the displayed certificate fingerprints with the fingerprints -obtained from some other (trusted) source of information, which might be -the certificate owner. -Be very careful to ensure the certificate is valid before importing it -as a trusted certificate. -The user then has the option of stopping the import operation. -If the \f[V]-noprompt\f[R] option is specified, then there is no -interaction with the user. -.SH IMPORT A CERTIFICATE REPLY -.PP -When you import a certificate reply, the certificate reply is validated -with trusted certificates from the keystore, and optionally, the -certificates configured in the \f[V]cacerts\f[R] keystore file when the -\f[V]-trustcacerts\f[R] option is specified. -.PP -The methods of determining whether the certificate reply is trusted are -as follows: -.IP \[bu] 2 -If the reply is a single X.509 certificate, then the \f[V]keytool\f[R] -command attempts to establish a trust chain, starting at the certificate -reply and ending at a self-signed certificate (belonging to a root CA). -The certificate reply and the hierarchy of certificates is used to -authenticate the certificate reply from the new certificate chain of -aliases. -If a trust chain can\[aq]t be established, then the certificate reply -isn\[aq]t imported. -In this case, the \f[V]keytool\f[R] command doesn\[aq]t print the -certificate and prompt the user to verify it, because it is very -difficult for a user to determine the authenticity of the certificate -reply. -.IP \[bu] 2 -If the reply is a PKCS #7 formatted certificate chain or a sequence of -X.509 certificates, then the chain is ordered with the user certificate -first followed by zero or more CA certificates. -If the chain ends with a self-signed root CA certificate and -the\f[V]-trustcacerts\f[R] option was specified, the \f[V]keytool\f[R] -command attempts to match it with any of the trusted certificates in the -keystore or the \f[V]cacerts\f[R] keystore file. -If the chain doesn\[aq]t end with a self-signed root CA certificate and -the \f[V]-trustcacerts\f[R] option was specified, the \f[V]keytool\f[R] -command tries to find one from the trusted certificates in the keystore -or the \f[V]cacerts\f[R] keystore file and add it to the end of the -chain. -If the certificate isn\[aq]t found and the \f[V]-noprompt\f[R] option -isn\[aq]t specified, the information of the last certificate in the -chain is printed, and the user is prompted to verify it. -.PP -If the public key in the certificate reply matches the user\[aq]s public -key already stored with \f[V]alias\f[R], then the old certificate chain -is replaced with the new certificate chain in the reply. -The old chain can only be replaced with a valid \f[V]keypass\f[R], and -so the password used to protect the private key of the entry is -supplied. -If no password is provided, and the private key password is different -from the keystore password, the user is prompted for it. -.PP -This command was named \f[V]-import\f[R] in earlier releases. -This old name is still supported in this release. -The new name, \f[V]-importcert\f[R], is preferred. diff --git a/src/java.base/share/man/keytool.md b/src/java.base/share/man/keytool.md new file mode 100644 index 00000000000..22b2877a3e7 --- /dev/null +++ b/src/java.base/share/man/keytool.md @@ -0,0 +1,2430 @@ +--- +# Copyright (c) 1998, 2024, 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. +# + +title: 'KEYTOOL(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +keytool - a key and certificate management utility + +## Synopsis + +`keytool` \[*commands*\] + +*commands* +: Commands for `keytool` include the following: + + - `-certreq`: Generates a certificate request + + - `-changealias`: Changes an entry's alias + + - `-delete`: Deletes an entry + + - `-exportcert`: Exports certificate + + - `-genkeypair`: Generates a key pair + + - `-genseckey`: Generates a secret key + + - `-gencert`: Generates a certificate from a certificate request + + - `-importcert`: Imports a certificate or a certificate chain + + - `-importpass`: Imports a password + + - `-importkeystore`: Imports one or all entries from another keystore + + - `-keypasswd`: Changes the key password of an entry + + - `-list`: Lists entries in a keystore + + - `-printcert`: Prints the content of a certificate + + - `-printcertreq`: Prints the content of a certificate request + + - `-printcrl`: Prints the content of a Certificate Revocation List (CRL) + file + + - `-storepasswd`: Changes the store password of a keystore + + - `-showinfo`: Displays security-related information + + - `-version`: Prints the program version + + See [Commands and Options] for a description of these commands with their + options. + +## Description + +The `keytool` command is a key and certificate management utility. It enables +users to administer their own public/private key pairs and associated +certificates for use in self-authentication (where a user authenticates +themselves to other users and services) or data integrity and authentication +services, by using digital signatures. The `keytool` command also enables users +to cache the public keys (in the form of certificates) of their communicating +peers. + +A certificate is a digitally signed statement from one entity (person, company, +and so on), which says that the public key (and some other information) of some +other entity has a particular value. When data is digitally signed, the +signature can be verified to check the data integrity and authenticity. +Integrity means that the data hasn't been modified or tampered with, and +authenticity means that the data comes from the individual who claims to have +created and signed it. + +The `keytool` command also enables users to administer secret keys and +passphrases used in symmetric encryption and decryption (Data Encryption +Standard). It can also display other security-related information. + +The `keytool` command stores the keys and certificates in a keystore. + +The `keytool` command uses the `jdk.certpath.disabledAlgorithms` and +`jdk.security.legacyAlgorithms` security properties to determine which +algorithms are considered a security risk. It emits warnings when +disabled or legacy algorithms are being used. +The `jdk.certpath.disabledAlgorithms` and `jdk.security.legacyAlgorithms` +security properties are defined in the `java.security` file (located in +the JDK's `$JAVA_HOME/conf/security` directory). + +## Command and Option Notes + +The following notes apply to the descriptions in [Commands and Options]\: + +- All command and option names are preceded by a hyphen sign (`-`). + +- Only one command can be provided. + +- Options for each command can be provided in any order. + +- There are two kinds of options, one is single-valued which should be + only provided once. If a single-valued option is provided multiple times, + the value of the last one is used. The other type is multi-valued, + which can be provided multiple times and all values are used. + The only multi-valued option currently supported is the `-ext` option used + to generate X.509v3 certificate extensions. + +- All items not italicized or in braces ({ }) or brackets (\[ \]) are + required to appear as is. + +- Braces surrounding an option signify that a default value is used when the + option isn't specified on the command line. Braces are also used around the + `-v`, `-rfc`, and `-J` options, which have meaning only when they appear on + the command line. They don't have any default values. + +- Brackets surrounding an option signify that the user is prompted for the + values when the option isn't specified on the command line. For the + `-keypass` option, if you don't specify the option on the command line, + then the `keytool` command first attempts to use the keystore password to + recover the private/secret key. If this attempt fails, then the `keytool` + command prompts you for the private/secret key password. + +- Items in italics (option values) represent the actual values that must be + supplied. For example, here is the format of the `-printcert` command: + + > `keytool -printcert` {`-file` *cert\_file*} {`-v`} + + When you specify a `-printcert` command, replace *cert\_file* with the + actual file name, as follows: `keytool -printcert -file VScert.cer` + +- Option values must be enclosed in quotation marks when they contain a blank + (space). + +## Commands and Options + +The keytool commands and their options can be grouped by the tasks that they +perform. + +[Commands for Creating or Adding Data to the Keystore]\: + +- `-gencert` + +- `-genkeypair` + +- `-genseckey` + +- `-importcert` + +- `-importpass` + +[Commands for Importing Contents from Another Keystore]\: + +- `-importkeystore` + +[Commands for Generating a Certificate Request]\: + +- `-certreq` + +[Commands for Exporting Data]\: + +- `-exportcert` + +[Commands for Displaying Data]\: + +- `-list` + +- `-printcert` + +- `-printcertreq` + +- `-printcrl` + +[Commands for Managing the Keystore]\: + +- `-storepasswd` + +- `-keypasswd` + +- `-delete` + +- `-changealias` + +[Commands for Displaying Security-related Information]\: + +- `-showinfo` + +[Commands for Displaying Program Version]\: + +- `-version` + +## Commands for Creating or Adding Data to the Keystore + +`-gencert` +: The following are the available options for the `-gencert` command: + + - {`-rfc`}: Output in RFC (Request For Comment) style + + - {`-infile` *infile*}: Input file name + + - {`-outfile` *outfile*}: Output file name + + - {`-alias` *alias*}: Alias name of the entry to process + + - {`-sigalg` *sigalg*}: Signature algorithm name + + - {`-dname` *dname*}: Distinguished name + + - {`-startdate` *startdate*}: Certificate validity start date and time + + - {`-ext` *ext*}\*: X.509 extension + + - {`-validity` *days*}: Validity number of days + + - \[`-keypass` *arg*\]: Key password + + - {`-keystore` *keystore*}: Keystore name + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Adds a security + provider by name (such as SunPKCS11) with an optional configure + argument. The value of the security provider is the name of a security + provider that is defined in a module. + + For example, + + > `keytool -addprovider SunPKCS11 -providerarg some.cfg ...` + + **Note:** + + For compatibility reasons, the SunPKCS11 provider can still be loaded + with `-providerclass sun.security.pkcs11.SunPKCS11` even if it is now + defined in a module. This is the only module included in the JDK that + needs a configuration, and therefore the most widely used with the + `-providerclass` option. For legacy security providers located on + classpath and loaded by reflection, `-providerclass` should still be + used. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + For example, if `MyProvider` is a legacy provider loaded via + reflection, + + > `keytool -providerclass com.example.MyProvider ...` + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-gencert` command to generate a certificate as a response to a + certificate request file (which can be created by the `keytool -certreq` + command). The command reads the request either from *infile* or, if + omitted, from the standard input, signs it by using the alias's private + key, and outputs the X.509 certificate into either *outfile* or, if + omitted, to the standard output. When `-rfc` is specified, the output + format is Base64-encoded PEM; otherwise, a binary DER is created. + + The `-sigalg` value specifies the algorithm that should be used to sign the + certificate. The *startdate* argument is the start time and date that the + certificate is valid. The *days* argument tells the number of days for + which the certificate should be considered valid. + + When *dname* is provided, it is used as the subject of the generated + certificate. Otherwise, the one from the certificate request is used. + + The `-ext` value shows what X.509 extensions will be embedded in the + certificate. Read [Common Command Options] for the grammar of `-ext`. + + The `-gencert` option enables you to create certificate chains. The + following example creates a certificate, `e1`, that contains three + certificates in its certificate chain. + + The following commands creates four key pairs named `ca`, `ca1`, `ca2`, and + `e1`: + + ``` + keytool -alias ca -dname CN=CA -genkeypair -keyalg rsa + keytool -alias ca1 -dname CN=CA -genkeypair -keyalg rsa + keytool -alias ca2 -dname CN=CA -genkeypair -keyalg rsa + keytool -alias e1 -dname CN=E1 -genkeypair -keyalg rsa + ``` + + The following two commands create a chain of signed certificates; `ca` + signs `ca1` and `ca1` signs `ca2`, all of which are self-issued: + + ``` + keytool -alias ca1 -certreq | + keytool -alias ca -gencert -ext san=dns:ca1 | + keytool -alias ca1 -importcert + + keytool -alias ca2 -certreq | + keytool -alias ca1 -gencert -ext san=dns:ca2 | + keytool -alias ca2 -importcert + ``` + + The following command creates the certificate `e1` and stores it in the + `e1.cert` file, which is signed by `ca2`. As a result, `e1` should contain + `ca`, `ca1`, and `ca2` in its certificate chain: + + > `keytool -alias e1 -certreq | keytool -alias ca2 -gencert > e1.cert` + +`-genkeypair` +: The following are the available options for the `-genkeypair` command: + + - {`-alias` *alias*}: Alias name of the entry to process + + - `-keyalg` *alg*: Key algorithm name + + - {`-keysize` *size*}: Key bit size + + - {`-groupname` *name*}: Group name. For example, an Elliptic Curve name. + + - {`-sigalg` *alg*}: Signature algorithm name + + - {`-signer` *alias*}: Signer alias + + - \[`-signerkeypass` *arg*\]: Signer key password + + - \[`-dname` *name*\]: Distinguished name + + - {`-startdate` *date*}: Certificate validity start date and time + + - {`-ext` *value*}\*: X.509 extension + + - {`-validity` *days*}: Validity number of days + + - \[`-keypass` *arg*\]: Key password + + - {`-keystore` *keystore*}: Keystore name + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\] }: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-genkeypair` command to generate a key pair (a public key and + associated private key). When the `-signer` option is not specified, + the public key is wrapped in an X.509 v3 self-signed certificate and + stored as a single-element certificate chain. When the `-signer` + option is specified, a new certificate is generated and signed by + the designated signer and stored as a multiple-element certificate + chain (containing the generated certificate itself, and the signer's + certificate chain). The certificate chain and private key are stored + in a new keystore entry that is identified by its alias. + + The `-keyalg` value specifies the algorithm to be used to generate the key + pair. The `-keysize` value specifies the size of each key to be generated. + The `-groupname` value specifies the named group (for example, the standard + or predefined name of an Elliptic Curve) of the key to be generated. + + When a `-keysize` value is provided, it will be used to initialize a + `KeyPairGenerator` object using the `initialize(int keysize)` + method. When a `-groupname` value is provided, it will be used to + initialize a `KeyPairGenerator` object using the + `initialize(AlgorithmParameterSpec params)` method where `params` + is `new NamedParameterSpec(groupname)`. + + Only one of `-groupname` and `-keysize` can be specified. If an algorithm + has multiple named groups that have the same key size, the `-groupname` + option should usually be used. In this case, if `-keysize` is specified, + it's up to the security provider to determine which named group is chosen + when generating a key pair. + + The `-sigalg` value specifies the algorithm that should be used + to sign the certificate. This algorithm must be compatible with + the `-keyalg` value. + + The `-signer` value specifies the alias of a `PrivateKeyEntry` for the + signer that already exists in the keystore. This option is used to + sign the certificate with the signer's private key. This is especially + useful for key agreement algorithms (i.e. the `-keyalg` value is `XDH`, + `X25519`, `X448`, or `DH`) as these keys cannot be used for digital + signatures, and therefore a self-signed certificate cannot be created. + + The `-signerkeypass` value specifies the password of the signer's private + key. It can be specified if the private key of the signer entry is + protected by a password different from the store password. + + The `-dname` value specifies the X.500 Distinguished Name to be associated + with the value of `-alias`. If the `-signer` option is not specified, the + issuer and subject fields of the self-signed certificate are populated + with the specified distinguished name. If the `-signer` option is + specified, the subject field of the certificate is populated with the + specified distinguished name and the issuer field is populated with the + subject field of the signer's certificate. If a distinguished name is not + provided at the command line, then the user is prompted for one. + + The value of `-keypass` is a password used to protect the private key of + the generated key pair. If a password is not provided, then the user is + prompted for it. If you press the **Return** key at the prompt, then the + key password is set to the same password as the keystore password. The + `-keypass` value must have at least six characters. + + The value of `-startdate` specifies the issue time of the certificate, also + known as the "Not Before" value of the X.509 certificate's Validity field. + + The option value can be set in one of these two forms: + + (\[`+-`\]*nnn*\[`ymdHMS`\])+ + + \[*yyyy*`/`*mm*`/`*dd*\] \[*HH*`:`*MM*`:`*SS*\] + + With the first form, the issue time is shifted by the specified value from + the current time. The value is a concatenation of a sequence of subvalues. + Inside each subvalue, the plus sign (+) means shift forward, and the minus + sign (-) means shift backward. The time to be shifted is *nnn* units of + years, months, days, hours, minutes, or seconds (denoted by a single + character of `y`, `m`, `d`, `H`, `M`, or `S` respectively). The exact value + of the issue time is calculated by using the + `java.util.GregorianCalendar.add(int field, int amount)` method on each + subvalue, from left to right. For example, the issue time can be specified + by: + + ``` + Calendar c = new GregorianCalendar(); + c.add(Calendar.YEAR, -1); + c.add(Calendar.MONTH, 1); + c.add(Calendar.DATE, -1); + return c.getTime() + ``` + + With the second form, the user sets the exact issue time in two parts, + year/month/day and hour:minute:second (using the local time zone). The user + can provide only one part, which means the other part is the same as the + current date (or time). The user must provide the exact number of digits + shown in the format definition (padding with 0 when shorter). When both + date and time are provided, there is one (and only one) space character + between the two parts. The hour should always be provided in 24-hour + format. + + When the option isn't provided, the start date is the current time. The + option can only be provided one time. + + The value of *date* specifies the number of days (starting at the date + specified by `-startdate`, or the current date when `-startdate` isn't + specified) for which the certificate should be considered valid. + +`-genseckey` +: The following are the available options for the `-genseckey` command: + + - {`-alias` *alias*}: Alias name of the entry to process + + - \[`-keypass` *arg*\]: Key password + + - `-keyalg` *alg*: Key algorithm name + + - {`-keysize` *size*}: Key bit size + + - {`-keystore` *keystore*}: Keystore name + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-genseckey` command to generate a secret key and store it in a new + `KeyStore.SecretKeyEntry` identified by `alias`. + + The value of `-keyalg` specifies the algorithm to be used to generate the + secret key, and the value of `-keysize` specifies the size of the key that + is generated. The `-keypass` value is a password that protects the secret + key. If a password is not provided, then the user is prompted for it. If + you press the **Return** key at the prompt, then the key password is set to + the same password that is used for the `-keystore`. The `-keypass` value + must contain at least six characters. + +`-importcert` +: The following are the available options for the `-importcert` command: + + - {`-noprompt`}: Do not prompt + + - {`-trustcacerts`}: Trust certificates from cacerts + + - {`-protected`}: Password is provided through protected mechanism + + - {`-alias` *alias*}: Alias name of the entry to process + + - {`-file` *file*}: Input file name + + - \[`-keypass` *arg*\]: Key password + + - {`-keystore` *keystore*}: Keystore name + + - {`-cacerts`}: Access the cacerts keystore + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + Use the `-importcert` command to read the certificate or certificate chain + (where the latter is supplied in a PKCS\#7 formatted reply or in a sequence + of X.509 certificates) from `-file` *file*, and store it in the `keystore` + entry identified by `-alias`. If `-file` *file* is not specified, then the + certificate or certificate chain is read from `stdin`. + + The `keytool` command can import X.509 v1, v2, and v3 certificates, and + PKCS\#7 formatted certificate chains consisting of certificates of that + type. The data to be imported must be provided either in binary encoding + format or in printable encoding format (also known as Base64 encoding) as + defined by the Internet RFC 1421 standard. In the latter case, the encoding + must be bounded at the beginning by a string that starts with `-----BEGIN`, + and bounded at the end by a string that starts with `-----END`. + + You import a certificate for two reasons: To add it to the list of trusted + certificates, and to import a certificate reply received from a certificate + authority (CA) as the result of submitting a Certificate Signing Request + (CSR) to that CA. See the `-certreq` command in [Commands for Generating a + Certificate Request]. + + The type of import is indicated by the value of the `-alias` option. If the + alias doesn't point to a key entry, then the `keytool` command assumes you + are adding a trusted certificate entry. In this case, the alias shouldn't + already exist in the keystore. If the alias does exist, then the `keytool` + command outputs an error because a trusted certificate already exists for + that alias, and doesn't import the certificate. If `-alias` points to a key + entry, then the `keytool` command assumes that you're importing a + certificate reply. + +`-importpass` +: The following are the available options for the `-importpass` command: + + - {`-alias` *alias*}: Alias name of the entry to process + + - \[`-keypass` *arg*\]: Key password + + - {`-keyalg` *alg*}: Key algorithm name + + - {`-keysize` *size*}: Key bit size + + - {`-keystore` *keystore*}: Keystore name + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-importpass` command to imports a passphrase and store it in a new + `KeyStore.SecretKeyEntry` identified by `-alias`. The passphrase may be + supplied via the standard input stream; otherwise the user is prompted for + it. The `-keypass` option provides a password to protect the imported + passphrase. If a password is not provided, then the user is prompted for + it. If you press the **Return** key at the prompt, then the key password is + set to the same password as that used for the `keystore`. The `-keypass` + value must contain at least six characters. + +## Commands for Importing Contents from Another Keystore + +`-importkeystore` +: The following are the available options for the `-importkeystore` command: + + - `-srckeystore` *keystore*: Source keystore name + + - {`-destkeystore` *keystore*}: Destination keystore name + + - {`-srcstoretype` *type*}: Source keystore type + + - {`-deststoretype` *type*}: Destination keystore type + + - \[`-srcstorepass` *arg*\]: Source keystore password + + - \[`-deststorepass` *arg*\]: Destination keystore password + + - {`-srcprotected`}: Source keystore password protected + + - {`-destprotected`}: Destination keystore password protected + + - {`-srcprovidername` *name*}: Source keystore provider name + + - {`-destprovidername` *name*}: Destination keystore provider name + + - {`-srcalias` *alias*}: Source alias + + - {`-destalias` *alias*}: Destination alias + + - \[`-srckeypass` *arg*\]: Source key password + + - \[`-destkeypass` *arg*\]: Destination key password + + - {`-noprompt`}: Do not prompt + + - {`-addprovider` *name* \[`-providerarg` *arg*\]: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + **Note:** + + This is the first line of all options: + + > `-srckeystore` *keystore* `-destkeystore` *keystore* + + Use the `-importkeystore` command to import a single entry or all entries + from a source keystore to a destination keystore. + + **Note:** + + If you do not specify `-destkeystore` when using the + `keytool -importkeystore` command, then the default keystore used is + `$HOME/.keystore`. + + When the `-srcalias` option is provided, the command imports the single + entry identified by the alias to the destination keystore. If a destination + alias isn't provided with `-destalias`, then `-srcalias` is used as the + destination alias. If the source entry is protected by a password, then + `-srckeypass` is used to recover the entry. If `-srckeypass` isn't + provided, then the `keytool` command attempts to use `-srcstorepass` to + recover the entry. If `-srcstorepass` is not provided or is incorrect, then + the user is prompted for a password. The destination entry is protected + with `-destkeypass`. If `-destkeypass` isn't provided, then the destination + entry is protected with the source entry password. For example, most + third-party tools require `storepass` and `keypass` in a PKCS \#12 keystore + to be the same. To create a PKCS\#12 keystore for these tools, always + specify a `-destkeypass` that is the same as `-deststorepass`. + + If the `-srcalias` option isn't provided, then all entries in the source + keystore are imported into the destination keystore. Each destination entry + is stored under the alias from the source entry. If the source entry is + protected by a password, then `-srcstorepass` is used to recover the entry. + If `-srcstorepass` is not provided or is incorrect, then the user is + prompted for a password. If a source keystore entry type isn't supported in + the destination keystore, or if an error occurs while storing an entry into + the destination keystore, then the user is prompted either to skip the + entry and continue or to quit. The destination entry is protected with the + source entry password. + + If the destination alias already exists in the destination keystore, then + the user is prompted either to overwrite the entry or to create a new entry + under a different alias name. + + If the `-noprompt` option is provided, then the user isn't prompted for a + new destination alias. Existing entries are overwritten with the + destination alias name. Entries that can't be imported are skipped and a + warning is displayed. + +## Commands for Generating a Certificate Request + +`-certreq` +: The following are the available options for the `-certreq` command: + + - {`-alias` *alias*}: Alias name of the entry to process + + - {`-sigalg` *alg*}: Signature algorithm name + + - {`-file` *file*}: Output file name + + - \[ `-keypass` *arg*\]: Key password + + - {`-keystore` *keystore*}: Keystore name + + - {`-dname` *name*}: Distinguished name + + - {`-ext` *value*}: X.509 extension + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-certreq` command to generate a Certificate Signing Request (CSR) + using the PKCS \#10 format. + + A CSR is intended to be sent to a CA. The CA authenticates the certificate + requestor (usually offline) and returns a certificate or certificate chain + to replace the existing certificate chain (initially a self-signed + certificate) in the keystore. + + The private key associated with *alias* is used to create the PKCS \#10 + certificate request. To access the private key, the correct password must + be provided. If `-keypass` isn't provided at the command line and is + different from the password used to protect the integrity of the keystore, + then the user is prompted for it. If `-dname` is provided, then it is used + as the subject in the CSR. Otherwise, the X.500 Distinguished Name + associated with alias is used. + + The `-sigalg` value specifies the algorithm that should be used to sign the + CSR. + + The CSR is stored in the `-file` *file*. If a file is not specified, then + the CSR is output to `-stdout`. + + Use the `-importcert` command to import the response from the CA. + +## Commands for Exporting Data + +`-exportcert` +: The following are the available options for the `-exportcert` command: + + - {`-rfc`}: Output in RFC style + + - {`-alias` *alias*}: Alias name of the entry to process + + - {`-file` *file*}: Output file name + + - {`-keystore` *keystore*}: Keystore name + + - {`-cacerts`}: Access the cacerts keystore + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\] }: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-exportcert` command to read a certificate from the keystore that + is associated with `-alias` *alias* and store it in the `-file` *file*. + When a file is not specified, the certificate is output to `stdout`. + + By default, the certificate is output in binary encoding. If the `-rfc` + option is specified, then the output in the printable encoding format + defined by the Internet RFC 1421 Certificate Encoding Standard. + + If `-alias` refers to a trusted certificate, then that certificate is + output. Otherwise, `-alias` refers to a key entry with an associated + certificate chain. In that case, the first certificate in the chain is + returned. This certificate authenticates the public key of the entity + addressed by `-alias`. + +## Commands for Displaying Data + +`-list` +: The following are the available options for the `-list` command: + + - {`-rfc`}: Output in RFC style + + - {`-alias` *alias*}: Alias name of the entry to process + + - {`-keystore` *keystore*}: Keystore name + + - {`-cacerts`}: Access the cacerts keystore + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\] }: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-list` command to print the contents of the keystore entry + identified by `-alias` to `stdout`. If `-alias` *alias* is not specified, + then the contents of the entire keystore are printed. + + By default, this command prints the SHA-256 fingerprint of a certificate. + If the `-v` option is specified, then the certificate is printed in + human-readable format, with additional information such as the owner, + issuer, serial number, and any extensions. If the `-rfc` option is + specified, then the certificate contents are printed by using the printable + encoding format, as defined by the Internet RFC 1421 Certificate Encoding + Standard. + + **Note:** + + You can't specify both `-v` and `-rfc` in the same command. Otherwise, an + error is reported. + +`-printcert` +: The following are the available options for the `-printcert` command: + + - {`-rfc`}: Output in RFC style + + - {`-file` *cert\_file*}: Input file name + + - {`-sslserver` *server*\[`:`*port*\]}:: Secure Sockets Layer (SSL) + server host and port + + - {`-jarfile` *JAR\_file*}: Signed `.jar` file + + - {`-keystore` *keystore*}: Keystore name + + - {`-trustcacerts`}: Trust certificates from cacerts + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-protected`}: Password is provided through protected mechanism + + - {`-v`}: Verbose output + + Use the `-printcert` command to read and print the certificate from `-file` + *cert\_file*, the SSL server located at `-sslserver` *server*\[`:`*port*\], + or the signed JAR file specified by `-jarfile` *JAR\_file*. It prints its + contents in a human-readable format. When a port is not specified, the + standard HTTPS port 443 is assumed. + + **Note:** + + The `-sslserver` and `-file` options can't be provided in the same command. + Otherwise, an error is reported. If you don't specify either option, then + the certificate is read from `stdin`. + + When`-rfc` is specified, the `keytool` command prints the certificate in + PEM mode as defined by the Internet RFC 1421 Certificate Encoding standard. + + If the certificate is read from a file or `stdin`, then it might be either + binary encoded or in printable encoding format, as defined by the RFC 1421 + Certificate Encoding standard. + + If the SSL server is behind a firewall, then the + `-J-Dhttps.proxyHost=proxyhost` and `-J-Dhttps.proxyPort=proxyport` options + can be specified on the command line for proxy tunneling. + + **Note:** + + This command can be used independently of a keystore. This command does not + check for the weakness of a certificate's signature algorithm if it is a + trusted certificate in the user keystore (specified by `-keystore`) or in + the `cacerts` keystore (if `-trustcacerts` is specified). + +`-printcertreq` +: The following are the available options for the `-printcertreq` command: + + - {`-file` *file*}: Input file name + + - {`-v`}: Verbose output + + Use the `-printcertreq` command to print the contents of a PKCS \#10 format + certificate request, which can be generated by the `keytool -certreq` + command. The command reads the request from file. If there is no file, then + the request is read from the standard input. + +`-printcrl` +: The following are the available options for the `-printcrl` command: + + - {`-file crl`}: Input file name + + - {`-keystore` *keystore*}: Keystore name + + - {`-trustcacerts`}: Trust certificates from cacerts + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-protected`}: Password is provided through protected mechanism + + - {`-v`}: Verbose output + + Use the `-printcrl` command to read the Certificate Revocation List (CRL) + from `-file crl` . A CRL is a list of the digital certificates that were + revoked by the CA that issued them. The CA generates the `crl` file. + + **Note:** + + This command can be used independently of a keystore. This command attempts + to verify the CRL using a certificate from the user keystore (specified by + `-keystore`) or the `cacerts` keystore (if `-trustcacerts` is specified), and + will print out a warning if it cannot be verified. + +## Commands for Managing the Keystore + +`-storepasswd` +: The following are the available options for the `-storepasswd` command: + + - \[`-new` *arg*\]: New password + + - {`-keystore` *keystore*}: Keystore name + + - {`-cacerts`}: Access the cacerts keystore + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + Use the `-storepasswd` command to change the password used to protect the + integrity of the keystore contents. The new password is set by `-new` *arg* + and must contain at least six characters. + +`-keypasswd` +: The following are the available options for the `-keypasswd` command: + + - {`-alias` *alias*}: Alias name of the entry to process + + - \[`-keypass` *old\_keypass*\]: Key password + + - \[`-new` *new\_keypass*\]: New password + + - {`-keystore` *keystore*}: Keystore name + + - {`-storepass` *arg*}: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + Use the `-keypasswd` command to change the password (under which + private/secret keys identified by `-alias` are protected) from `-keypass` + *old\_keypass* to `-new` *new\_keypass*. The password value must contain at + least six characters. + + If the `-keypass` option isn't provided at the command line and the + `-keypass` password is different from the keystore password (`-storepass` + *arg*), then the user is prompted for it. + + If the `-new` option isn't provided at the command line, then the user is + prompted for it. + +`-delete` +: The following are the available options for the `-delete` command: + + - \[`-alias` *alias*\]: Alias name of the entry to process + + - {`-keystore` *keystore*}: Keystore name + + - {`-cacerts`}: Access the cacerts keystore + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-delete` command to delete the `-alias` *alias* entry from the + keystore. When not provided at the command line, the user is prompted for + the `alias`. + +`-changealias` +: The following are the available options for the `-changealias` command: + + - {`-alias` *alias*}: Alias name of the entry to process + + - \[`-destalias` *alias*\]: Destination alias + + - \[`-keypass` *arg*\]: Key password + + - {`-keystore` *keystore*}: Keystore name + + - {`-cacerts`}: Access the cacerts keystore + + - \[`-storepass` *arg*\]: Keystore password + + - {`-storetype` *type*}: Keystore type + + - {`-providername` *name*}: Provider name + + - {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider + by name (such as SunPKCS11) with an optional configure argument. + + - {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security + provider by fully qualified class name with an optional configure + argument. + + - {`-providerpath` *list*}: Provider classpath + + - {`-v`}: Verbose output + + - {`-protected`}: Password provided through a protected mechanism + + Use the `-changealias` command to move an existing keystore entry from + `-alias` *alias* to a new `-destalias` *alias*. If a destination alias is + not provided, then the command prompts you for one. If the original entry + is protected with an entry password, then the password can be supplied with + the `-keypass` option. If a key password is not provided, then the + `-storepass` (if provided) is attempted first. If the attempt fails, then + the user is prompted for a password. + +## Commands for Displaying Security-related Information + +`-showinfo` +: The following are the available options for the `-showinfo` command: + + - {`-tls`}: Displays TLS configuration information + + - {`-v`}: Verbose output + + Use the `-showinfo` command to display various security-related + information. The `-tls` option displays TLS configurations, such as + the list of enabled protocols and cipher suites. + +## Commands for Displaying Program Version + +You can use `-version` to print the program version of `keytool`. + +## Commands for Displaying Help Information + +You can use `--help` to display a list of `keytool` commands or to display help +information about a specific `keytool` command. + +- To display a list of `keytool` commands, enter: + + > `keytool --help` + +- To display help information about a specific `keytool` command, enter: + + > `keytool - --help` + +## Common Command Options + +The `-v` option can appear for all commands except `--help`. When the `-v` +option appears, it signifies verbose mode, which means that more information is +provided in the output. + +The `-J`*option* argument can appear for any command. When the `-J`*option* is +used, the specified *option* string is passed directly to the Java interpreter. +This option doesn't contain any spaces. It's useful for adjusting the execution +environment or memory usage. For a list of possible interpreter options, enter +`java -h` or `java -X` at the command line. + +These options can appear for all commands operating on a keystore: + +`-storetype` *storetype* +: This qualifier specifies the type of keystore to be instantiated. + +`-keystore` *keystore* +: The keystore location. + + If the JKS `storetype` is used and a keystore file doesn't yet exist, then + certain `keytool` commands can result in a new keystore file being created. + For example, if `keytool -genkeypair` is called and the `-keystore` option + isn't specified, the default keystore file named `.keystore` is created in + the user's home directory if it doesn't already exist. Similarly, if the + `-keystore ks_file` option is specified but `ks_file` doesn't exist, then + it is created. For more information on the JKS `storetype`, see the + **KeyStore Implementation** section in **KeyStore aliases**. + + Note that the input stream from the `-keystore` option is passed to the + `KeyStore.load` method. If `NONE` is specified as the URL, then a null + stream is passed to the `KeyStore.load` method. `NONE` should be specified + if the keystore isn't file-based. For example, when the keystore resides on + a hardware token device. + +`-cacerts` *cacerts* +: Operates on the *cacerts* keystore . This option is equivalent to + `-keystore` *path\_to\_cacerts* `-storetype` *type\_of\_cacerts*. An error + is reported if the `-keystore` or `-storetype` option is used with the + `-cacerts` option. + +`-storepass` \[`:env` \| `:file` \] *argument* +: The password that is used to protect the integrity of the keystore. + + If the modifier `env` or `file` isn't specified, then the password has the + value *argument*, which must contain at least six characters. Otherwise, + the password is retrieved as follows: + + - `env`: Retrieve the password from the environment variable named + *argument*. + + - `file`: Retrieve the password from the file named *argument*. + + **Note:** All other options that require passwords, such as `-keypass`, + `-srckeypass`, `-destkeypass`, `-srcstorepass`, and `-deststorepass`, + accept the `env` and `file` modifiers. Remember to separate the password + option and the modifier with a colon (:). + + The password must be provided to all commands that access the keystore + contents. For such commands, when the `-storepass` option isn't provided at + the command line, the user is prompted for it. + + When retrieving information from the keystore, the password is optional. If + a password is not specified, then the integrity of the retrieved + information can't be verified and a warning is displayed. + +`-providername` *name* +: Used to identify a cryptographic service provider's name when listed in the + security properties file. + +`-addprovider` *name* +: Used to add a security provider by name (such as SunPKCS11) . + +`-providerclass` *class* +: Used to specify the name of a cryptographic service provider's master class + file when the service provider isn't listed in the security properties + file. + +`-providerpath` *list* +: Used to specify the provider classpath. + +`-providerarg` *arg* +: Used with the `-addprovider` or `-providerclass` option to represent an + optional string input argument for the constructor of *class* name. + +`-protected=true`\|`false` +: Specify this value as `true` when a password must be specified by way of a + protected authentication path, such as a dedicated PIN reader. Because + there are two keystores involved in the `-importkeystore` command, the + following two options, `-srcprotected` and `-destprotected`, are provided + for the source keystore and the destination keystore respectively. + +`-ext` {*name*{`:critical`} {`=`*value*}} +: Denotes an X.509 certificate extension. The option can be used in + `-genkeypair` and `-gencert` to embed extensions into the generated + certificate, or in `-certreq` to show what extensions are requested in the + certificate request. The option can appear multiple times. The *name* + argument can be a supported extension name (see [Supported Named + Extensions]) or an arbitrary OID number. The *value* argument, when + provided, denotes the argument for the extension. When *value* is omitted, + the default value of the extension or the extension itself requires no + argument. The `:critical` modifier, when provided, means the extension's + `isCritical` attribute is `true`; otherwise, it is `false`. You can use + `:c` in place of `:critical`. + +`-conf` *file* +: Specifies a pre-configured options file. + +## Pre-configured options file + +A pre-configured options file is a Java properties file that can be specified +with the `-conf` option. Each property represents the default option(s) for +a keytool command using "keytool.*command_name*" as the property name. A +special property named "keytool.all" represents the default option(s) applied +to all commands. A property value can include `${prop}` which will be expanded +to the system property associated with it. If an option value includes white +spaces inside, it should be surrounded by quotation marks (" or '). All +property names must be in lower case. + +When `keytool` is launched with a pre-configured options file, the value for +"keytool.all" (if it exists) is prepended to the `keytool` command line first, +with the value for the command name (if it exists) comes next, and the existing +options on the command line at last. For a single-valued option, this allows +the property for a specific command to override the "keytool.all" value, +and the value specified on the command line to override both. For +multiple-valued options, all of them will be used by `keytool`. + +For example, given the following file named `preconfig`: +``` + # A tiny pre-configured options file + keytool.all = -keystore ${user.home}/ks + keytool.list = -v + keytool.genkeypair = -keyalg rsa +``` + +`keytool -conf preconfig -list` is identical to + +> `keytool -keystore ~/ks -v -list` + +`keytool -conf preconfig -genkeypair -alias me` is identical to + +> `keytool -keystore ~/ks -keyalg rsa -genkeypair -alias me` + +`keytool -conf preconfig -genkeypair -alias you -keyalg ec` is identical to + +> `keytool -keystore ~/ks -keyalg rsa -genkeypair -alias you -keyalg ec` + +which is equivalent to + +> `keytool -keystore ~/ks -genkeypair -alias you -keyalg ec` + +because `-keyalg` is a single-valued option and the `ec` value specified +on the command line overrides the preconfigured options file. + +## Examples of Option Values + +The following examples show the defaults for various option values: + +``` +-alias "mykey" + +-keysize + 2048 (when using -genkeypair and -keyalg is "DSA") + 3072 (when using -genkeypair and -keyalg is "RSA", "RSASSA-PSS", or "DH") + 384 (when using -genkeypair and -keyalg is "EC") + 56 (when using -genseckey and -keyalg is "DES") + 168 (when using -genseckey and -keyalg is "DESede") + +-groupname + ed25519 (when using -genkeypair and -keyalg is "EdDSA", key size is 255) + x25519 (when using -genkeypair and -keyalg is "XDH", key size is 255) + +-validity 90 + +-keystore + +-destkeystore + +-storetype + +-file + stdin (if reading) + stdout (if writing) + +-protected false +``` + +When generating a certificate or a certificate request, the default signature +algorithm (`-sigalg` option) is derived from the algorithm of the underlying +private key to provide an appropriate level of security strength as follows: + +Table: Default Signature Algorithms + +keyalg key size default sigalg +------- -------- -------------- +DSA any size SHA256withDSA +RSA \< 624 SHA256withRSA (key size is too small for using SHA-384) + \<= 7680 SHA384withRSA + \> 7680 SHA512withRSA +EC \< 512 SHA384withECDSA + \>= 512 SHA512withECDSA +RSASSA-PSS \< 624 RSASSA-PSS (with SHA-256, key size is too small for + using SHA-384) + \<= 7680 RSASSA-PSS (with SHA-384) + \> 7680 RSASSA-PSS (with SHA-512) +EdDSA 255 Ed25519 + 448 Ed448 +Ed25519 255 Ed25519 +Ed448 448 Ed448 +------- -------- -------------- + +* The key size, measured in bits, corresponds to the size of the private key. +This size is determined by the value of the `-keysize` or `-groupname` options +or the value derived from a default setting. + +* An RSASSA-PSS signature algorithm uses a `MessageDigest` +algorithm as its hash and MGF1 algorithms. + +* If neither a default `-keysize` or `-groupname` is defined for an algorithm, +the security provider will choose a default setting. + +**Note:** + +To improve out of the box security, default keysize, groupname, and signature +algorithm names are periodically updated to stronger values with each release +of the JDK. If interoperability with older releases of the JDK is important, +make sure that the defaults are supported by those releases. Alternatively, +you can use the `-keysize`, `-groupname`, or `-sigalg` options to override +the default values at your own risk. + +## Supported Named Extensions + +The `keytool` command supports these named extensions. The names aren't +case-sensitive. + +`BC` or `BasicConstraints` +: Values: + + The full form is `ca:`{`true`\|`false`}\[`,pathlen:`*len*\] or *len*, which + is short for `ca:true,pathlen:`*len*. + + When *len* is omitted, the resulting value is `ca:true`. + +`KU` or `KeyUsage` +: Values: + + *usage*(`,` *usage*)\* + + *usage* can be one of the following: + + - `digitalSignature` + + - `nonRepudiation` (`contentCommitment`) + + - `keyEncipherment` + + - `dataEncipherment` + + - `keyAgreement` + + - `keyCertSign` + + - `cRLSign` + + - `encipherOnly` + + - `decipherOnly` + + Provided there is no ambiguity, the *usage* argument can be abbreviated + with the first few letters (such as `dig` for `digitalSignature`) or in + camel-case style (such as `dS` for `digitalSignature` or `cRLS` for + `cRLSign`). The *usage* values are case-sensitive. + +`EKU` or `ExtendedKeyUsage` +: Values: + + *usage*(`,` *usage*)\* + + *usage* can be one of the following: + + - `anyExtendedKeyUsage` + + - `serverAuth` + + - `clientAuth` + + - `codeSigning` + + - `emailProtection` + + - `timeStamping` + + - `OCSPSigning` + + - Any OID string + + Provided there is no ambiguity, the *usage* argument can be abbreviated + with the first few letters or in camel-case style. The *usage* values are + case-sensitive. + +`SAN` or `SubjectAlternativeName` +: Values: + + *type*`:`*value*(`,` *type*`:`*value*)\* + + *type* can be one of the following: + + - `EMAIL` + + - `URI` + + - `DNS` + + - `IP` + + - `OID` + + The *value* argument is the string format value for the *type*. + +`IAN` or `IssuerAlternativeName` +: Values: + + Same as `SAN` or `SubjectAlternativeName`. + +`SIA` or `SubjectInfoAccess` +: Values: + + *method*`:`*location-type*`:`*location-value*(`,` + *method*`:`*location-type*`:`*location-value*)\* + + *method* can be one of the following: + + - `timeStamping` + + - `caRepository` + + - Any OID + + The *location-type* and *location-value* arguments can be any + *type*`:`*value* supported by the `SubjectAlternativeName` extension. + +`AIA` or `AuthorityInfoAccess` +: Values: + + Same as `SIA` or `SubjectInfoAccess`. + + The *method* argument can be one of the following: + + - `ocsp` + + - `caIssuers` + + - Any OID + +When *name* is OID, the value is the hexadecimal dumped Definite Encoding Rules +(DER) encoding of the `extnValue` for the extension excluding the OCTET STRING +type and length bytes. Other than standard hexadecimal numbers (0-9, a-f, A-F), +any extra characters are ignored in the HEX string. Therefore, both 01:02:03:04 +and 01020304 are accepted as identical values. When there is no value, the +extension has an empty value field. + +A special name `honored`, used only in `-gencert`, denotes how the extensions +included in the certificate request should be honored. The value for this name +is a comma-separated list of `all` (all requested extensions are honored), +*name*{`:`\[`critical`\|`non-critical`\]} (the named extension is honored, but +it uses a different `isCritical` attribute), and `-name` (used with `all`, +denotes an exception). Requested extensions aren't honored by default. + +If, besides the`-ext honored` option, another named or OID `-ext` option is +provided, this extension is added to those already honored. However, if this +name (or OID) also appears in the honored value, then its value and criticality +override that in the request. If an extension of the same type is provided +multiple times through either a name or an OID, only the last extension is +used. + +The `subjectKeyIdentifier` extension is always created. For non-self-signed +certificates, the `authorityKeyIdentifier` is created. + +**CAUTION:** + +Users should be aware that some combinations of extensions (and other +certificate fields) may not conform to the Internet standard. See [Certificate +Conformance Warning]. + +## Examples of Tasks in Creating a keystore + +The following examples describe the sequence actions in creating a keystore for +managing public/private key pairs and certificates from trusted entities. + +- [Generating the Key Pair] + +- [Requesting a Signed Certificate from a CA] + +- [Importing a Certificate for the CA] + +- [Importing the Certificate Reply from the CA] + +- [Exporting a Certificate That Authenticates the Public Key] + +- [Importing the Keystore] + +- [Generating Certificates for an SSL Server] + +## Generating the Key Pair + +Create a keystore and then generate the key pair. + +You can enter the command as a single line such as the following: + +> `keytool -genkeypair -dname "cn=myname, ou=mygroup, o=mycompany, + c=mycountry" -alias business -keyalg rsa -keypass` *password* `-keystore + /working/mykeystore -storepass password -validity 180` + +The command creates the keystore named `mykeystore` in the working directory +(provided it doesn't already exist), and assigns it the password specified by +`-keypass`. It generates a public/private key pair for the entity whose +distinguished name is `myname`, `mygroup`, `mycompany`, and a two-letter +country code of `mycountry`. It uses the RSA key generation algorithm +to create the keys; both are 3072 bits. + +The command uses the default SHA384withRSA signature algorithm to create a +self-signed certificate that includes the public key and the distinguished name +information. The certificate is valid for 180 days, and is associated with the +private key in a keystore entry referred to by `-alias business`. The private +key is assigned the password specified by `-keypass`. + +The command is significantly shorter when the option defaults are accepted. In +this case, only `-keyalg` is required, and the defaults are used for unspecified +options that have default values. You are prompted for any required values. You +could have the following: + +> `keytool -genkeypair -keyalg rsa` + +In this case, a keystore entry with the alias `mykey` is created, with a newly +generated key pair and a certificate that is valid for 90 days. This entry is +placed in your home directory in a keystore named `.keystore` . `.keystore` is +created if it doesn't already exist. You are prompted for the distinguished +name information, the keystore password, and the private key password. + +**Note:** + +The rest of the examples assume that you responded to the prompts with values +equal to those specified in the first `-genkeypair` command. For example, a +distinguished name of +`cn=`*myname*`, ou=`*mygroup*`, o=`*mycompany*`, c=`*mycountry*). + +## Requesting a Signed Certificate from a CA + +**Note:** + +Generating the key pair created a self-signed certificate; however, a +certificate is more likely to be trusted by others when it is signed by a CA. + +To get a CA signature, complete the following process: + +1. Generate a CSR: + + > `keytool -certreq -file myname.csr` + + This creates a CSR for the entity identified by the default alias `mykey` + and puts the request in the file named `myname.csr`. + +2. Submit `myname.csr` to a CA, such as DigiCert. + +The CA authenticates you, the requestor (usually offline), and returns a +certificate, signed by them, authenticating your public key. In some cases, the +CA returns a chain of certificates, each one authenticating the public key of +the signer of the previous certificate in the chain. + +## Importing a Certificate for the CA + +To import a certificate for the CA, complete the following process: + +1. Before you import the certificate reply from a CA, you need one or more + trusted certificates either in your keystore or in the `cacerts` keystore + file. See `-importcert` in **Commands**. + + - If the certificate reply is a certificate chain, then you need the top + certificate of the chain. The root CA certificate that authenticates + the public key of the CA. + + - If the certificate reply is a single certificate, then you need a + certificate for the issuing CA (the one that signed it). If that + certificate isn't self-signed, then you need a certificate for its + signer, and so on, up to a self-signed root CA certificate. + + The `cacerts` keystore ships with a set of root certificates issued by the + CAs of [the Oracle Java Root Certificate program]( + http://www.oracle.com/technetwork/java/javase/javasecarootcertsprogram-1876540.html). + If you request a signed certificate from a CA, and a certificate + authenticating that CA's public key hasn't been added to `cacerts`, then + you must import a certificate from that CA as a trusted certificate. + + A certificate from a CA is usually self-signed or signed by another CA. If + it is signed by another CA, you need a certificate that authenticates that + CA's public key. + + For example, you have obtained a *X*`.cer` file from a company that is a CA + and the file is supposed to be a self-signed certificate that authenticates + that CA's public key. Before you import it as a trusted certificate, you + should ensure that the certificate is valid by: + + 1. Viewing it with the `keytool -printcert` command or the + `keytool -importcert` command without using the `-noprompt` option. + Make sure that the displayed certificate fingerprints match the + expected fingerprints. + + 2. Calling the person who sent the certificate, and comparing the + fingerprints that you see with the ones that they show or that a secure + public key repository shows. + + Only when the fingerprints are equal is it assured that the certificate + wasn't replaced in transit with somebody else's certificate (such as an + attacker's certificate). If such an attack takes place, and you didn't + check the certificate before you imported it, then you would be trusting + anything that the attacker signed. + +2. Replace the self-signed certificate with a certificate chain, where each + certificate in the chain authenticates the public key of the signer of the + previous certificate in the chain, up to a root CA. + + If you trust that the certificate is valid, then you can add it to your + keystore by entering the following command: + + > `keytool -importcert -alias` *alias* `-file *X*`.cer` + + This command creates a trusted certificate entry in the keystore from the + data in the CA certificate file and assigns the values of the *alias* to + the entry. + +## Importing the Certificate Reply from the CA + +After you import a certificate that authenticates the public key of the CA that +you submitted your certificate signing request to (or there is already such a +certificate in the `cacerts` file), you can import the certificate reply and +replace your self-signed certificate with a certificate chain. + +The certificate chain is one of the following: + +- Returned by the CA when the CA reply is a chain. + +- Constructed when the CA reply is a single certificate. This certificate + chain is constructed by using the certificate reply and trusted + certificates available either in the keystore where you import the reply or + in the `cacerts` keystore file. + +For example, if you sent your certificate signing request to DigiCert, then you +can import their reply by entering the following command: + +**Note:** + +In this example, the returned certificate is named `DCmyname.cer`. + +> `keytool -importcert -trustcacerts -file DCmyname.cer` + +## Exporting a Certificate That Authenticates the Public Key + +**Note:** + +If you used the `jarsigner` command to sign a Java Archive (JAR) file, then +clients that use the file will want to authenticate your signature. + +One way that clients can authenticate you is by importing your public key +certificate into their keystore as a trusted entry. You can then export the +certificate and supply it to your clients. + +For example: + +1. Copy your certificate to a file named `myname.cer` by entering the + following command: + + **Note:** + + In this example, the entry has an alias of `mykey`. + + > `keytool -exportcert -alias mykey -file myname.cer` + +2. With the certificate and the signed JAR file, a client can use the + `jarsigner` command to authenticate your signature. + +## Importing the Keystore + +Use the `importkeystore` command to import an entire keystore into another +keystore. This imports all entries from the source keystore, including keys and +certificates, to the destination keystore with a single command. You can use +this command to import entries from a different type of keystore. During the +import, all new entries in the destination keystore will have the same alias +names and protection passwords (for secret keys and private keys). If the +`keytool` command can't recover the private keys or secret keys from the source +keystore, then it prompts you for a password. If it detects alias duplication, +then it asks you for a new alias, and you can specify a new alias or simply +allow the `keytool` command to overwrite the existing one. + +For example, import entries from a typical JKS type keystore `key.jks` into a +PKCS \#11 type hardware-based keystore, by entering the following command: + +> `keytool -importkeystore -srckeystore key.jks -destkeystore NONE + -srcstoretype JKS -deststoretype PKCS11 -srcstorepass` *password* + `-deststorepass` *password* + +The `importkeystore` command can also be used to import a single entry from a +source keystore to a destination keystore. In this case, besides the options +you used in the previous example, you need to specify the alias you want to +import. With the `-srcalias` option specified, you can also specify the +destination alias name, protection password for a secret or private key, and +the destination protection password you want as follows: + +> `keytool -importkeystore -srckeystore key.jks -destkeystore NONE + -srcstoretype JKS -deststoretype PKCS11 -srcstorepass` *password* + `-deststorepass` *password* `-srcalias myprivatekey -destalias + myoldprivatekey -srckeypass` *password* `-destkeypass` *password* + `-noprompt` + +## Generating Certificates for an SSL Server + +The following are `keytool` commands used to generate key pairs and +certificates for three entities: + +- Root CA (`root`) + +- Intermediate CA (`ca`) + +- SSL server (`server`) + +Ensure that you store all the certificates in the same keystore. + +``` +keytool -genkeypair -keystore root.jks -alias root -ext bc:c -keyalg rsa +keytool -genkeypair -keystore ca.jks -alias ca -ext bc:c -keyalg rsa +keytool -genkeypair -keystore server.jks -alias server -keyalg rsa + +keytool -keystore root.jks -alias root -exportcert -rfc > root.pem + +keytool -storepass password -keystore ca.jks -certreq -alias ca | + keytool -storepass password -keystore root.jks + -gencert -alias root -ext BC=0 -rfc > ca.pem +keytool -keystore ca.jks -importcert -alias ca -file ca.pem + +keytool -storepass password -keystore server.jks -certreq -alias server | + keytool -storepass password -keystore ca.jks -gencert -alias ca + -ext ku:c=dig,kE -rfc > server.pem +cat root.pem ca.pem server.pem | + keytool -keystore server.jks -importcert -alias server + +``` + +## Terms + +Keystore +: A keystore is a storage facility for cryptographic keys and certificates. + +Keystore entries +: Keystores can have different types of entries. The two most applicable + entry types for the `keytool` command include the following: + + Key entries: Each entry holds very sensitive cryptographic key information, + which is stored in a protected format to prevent unauthorized access. + Typically, a key stored in this type of entry is a secret key, or a private + key accompanied by the certificate chain for the corresponding public key. + See **Certificate Chains**. The `keytool` command can handle both types of + entries, while the `jarsigner` tool only handles the latter type of entry, + that is private keys and their associated certificate chains. + + Trusted certificate entries: Each entry contains a single public key + certificate that belongs to another party. The entry is called a trusted + certificate because the keystore owner trusts that the public key in the + certificate belongs to the identity identified by the subject (owner) of + the certificate. The issuer of the certificate vouches for this, by signing + the certificate. + +Keystore aliases +: All keystore entries (key and trusted certificate entries) are accessed by + way of unique aliases. + + An alias is specified when you add an entity to the keystore with the + `-genseckey` command to generate a secret key, the `-genkeypair` command to + generate a key pair (public and private key), or the `-importcert` command + to add a certificate or certificate chain to the list of trusted + certificates. Subsequent `keytool` commands must use this same alias to + refer to the entity. + + For example, you can use the alias `duke` to generate a new public/private + key pair and wrap the public key into a self-signed certificate with the + following command. See **Certificate Chains**. + + > `keytool -genkeypair -alias duke -keyalg rsa -keypass` *passwd* + + This example specifies an initial *passwd* required by subsequent commands + to access the private key associated with the alias `duke`. If you later + want to change Duke's private key password, use a command such as the + following: + + > `keytool -keypasswd -alias duke -keypass` *passwd* `-new` *newpasswd* + + This changes the initial *passwd* to *newpasswd*. A password shouldn't be + specified on a command line or in a script unless it is for testing + purposes, or you are on a secure system. If you don't specify a required + password option on a command line, then you are prompted for it. + +Keystore implementation +: The `KeyStore` class provided in the `java.security` package supplies + well-defined interfaces to access and modify the information in a keystore. + It is possible for there to be multiple different concrete implementations, + where each implementation is that for a particular type of keystore. + + Currently, two command-line tools (`keytool` and `jarsigner`) make use of + keystore implementations. Because the `KeyStore` class is `public`, users + can write additional security applications that use it. + + In JDK 9 and later, the default keystore implementation is `PKCS12`. This + is a cross platform keystore based on the RSA PKCS12 Personal Information + Exchange Syntax Standard. This standard is primarily meant for storing or + transporting a user's private keys, certificates, and miscellaneous + secrets. There is another built-in implementation, provided by Oracle. It + implements the keystore as a file with a proprietary keystore type (format) + named `JKS`. It protects each private key with its individual password, and + also protects the integrity of the entire keystore with a (possibly + different) password. + + Keystore implementations are provider-based. More specifically, the + application interfaces supplied by `KeyStore` are implemented in terms of a + Service Provider Interface (SPI). That is, there is a corresponding + abstract `KeystoreSpi` class, also in the `java.security package`, which + defines the Service Provider Interface methods that providers must + implement. The term *provider* refers to a package or a set of packages + that supply a concrete implementation of a subset of services that can be + accessed by the Java Security API. To provide a keystore implementation, + clients must implement a provider and supply a `KeystoreSpi` subclass + implementation, as described in Steps to Implement and Integrate a + Provider. + + Applications can choose different types of keystore implementations from + different providers, using the `getInstance` factory method supplied in the + `KeyStore` class. A keystore type defines the storage and data format of + the keystore information, and the algorithms used to protect private/secret + keys in the keystore and the integrity of the keystore. Keystore + implementations of different types aren't compatible. + + The `keytool` command works on any file-based keystore implementation. It + treats the keystore location that is passed to it at the command line as a + file name and converts it to a `FileInputStream`, from which it loads the + keystore information.)The `jarsigner` commands can read a keystore from any + location that can be specified with a URL. + + For `keytool` and `jarsigner`, you can specify a keystore type at the + command line, with the `-storetype` option. + + If you don't explicitly specify a keystore type, then the tools choose a + keystore implementation based on the value of the `keystore.type` property + specified in the security properties file. The security properties file is + called `java.security`, and resides in the security properties directory: + + - **Linux and macOS:** `java.home/lib/security` + + - **Windows:** `java.home\lib\security` + + Each tool gets the `keystore.type` value and then examines all the + currently installed providers until it finds one that implements a + keystores of that type. It then uses the keystore implementation from that + provider.The `KeyStore` class defines a static method named + `getDefaultType` that lets applications retrieve the value of the + `keystore.type` property. The following line of code creates an instance of + the default keystore type as specified in the `keystore.type` property: + + > `KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());` + + The default keystore type is `pkcs12`, which is a cross-platform keystore + based on the RSA PKCS12 Personal Information Exchange Syntax Standard. This + is specified by the following line in the security properties file: + + > `keystore.type=pkcs12` + + To have the tools utilize a keystore implementation other than the default, + you can change that line to specify a different keystore type. For example, + if you want to use the Oracle's `jks` keystore implementation, then change + the line to the following: + + > `keystore.type=jks` + + **Note:** + + Case doesn't matter in keystore type designations. For example, `JKS` would + be considered the same as `jks`. + +Certificate +: A certificate (or public-key certificate) is a digitally signed statement + from one entity (the issuer), saying that the public key and some other + information of another entity (the subject) has some specific value. The + following terms are related to certificates: + + - Public Keys: These are numbers associated with a particular entity, and + are intended to be known to everyone who needs to have trusted + interactions with that entity. Public keys are used to verify + signatures. + + - Digitally Signed: If some data is digitally signed, then it is stored + with the identity of an entity and a signature that proves that entity + knows about the data. The data is rendered unforgeable by signing with + the entity's private key. + + - Identity: A known way of addressing an entity. In some systems, the + identity is the public key, and in others it can be anything from an + Oracle Solaris UID to an email address to an X.509 distinguished name. + + - Signature: A signature is computed over some data using the private key + of an entity. The signer, which in the case of a certificate is also + known as the issuer. + + - Private Keys: These are numbers, each of which is supposed to be known + only to the particular entity whose private key it is (that is, it is + supposed to be kept secret). Private and public keys exist in pairs in + all public key cryptography systems (also referred to as public key + crypto systems). In a typical public key crypto system, such as DSA, a + private key corresponds to exactly one public key. Private keys are + used to compute signatures. + + - Entity: An entity is a person, organization, program, computer, + business, bank, or something else you are trusting to some degree. + + Public key cryptography requires access to users' public keys. In a + large-scale networked environment, it is impossible to guarantee that prior + relationships between communicating entities were established or that a + trusted repository exists with all used public keys. Certificates were + invented as a solution to this public key distribution problem. Now a + Certification Authority (CA) can act as a trusted third party. CAs are + entities such as businesses that are trusted to sign (issue) certificates + for other entities. It is assumed that CAs only create valid and reliable + certificates because they are bound by legal agreements. There are many + public Certification Authorities, such as DigiCert, Comodo, Entrust, and so + on. + + You can also run your own Certification Authority using products such as + Microsoft Certificate Server or the Entrust CA product for your + organization. With the `keytool` command, it is possible to display, + import, and export certificates. It is also possible to generate + self-signed certificates. + + The `keytool` command currently handles X.509 certificates. + +X.509 Certificates +: The X.509 standard defines what information can go into a certificate and + describes how to write it down (the data format). All the data in a + certificate is encoded with two related standards called ASN.1/DER. + Abstract Syntax Notation 1 describes data. The Definite Encoding Rules + describe a single way to store and transfer that data. + + All X.509 certificates have the following data, in addition to the + signature: + + - Version: This identifies which version of the X.509 standard applies to + this certificate, which affects what information can be specified in + it. Thus far, three versions are defined. The `keytool` command can + import and export v1, v2, and v3 certificates. It generates v3 + certificates. + + - X.509 Version 1 has been available since 1988, is widely deployed, + and is the most generic. + + - X.509 Version 2 introduced the concept of subject and issuer unique + identifiers to handle the possibility of reuse of subject or issuer + names over time. Most certificate profile documents strongly + recommend that names not be reused and that certificates shouldn't + make use of unique identifiers. Version 2 certificates aren't + widely used. + + - X.509 Version 3 is the most recent (1996) and supports the notion + of extensions where anyone can define an extension and include it + in the certificate. Some common extensions are: KeyUsage (limits + the use of the keys to particular purposes such as `signing-only`) + and AlternativeNames (allows other identities to also be associated + with this public key, for example. DNS names, email addresses, IP + addresses). Extensions can be marked critical to indicate that the + extension should be checked and enforced or used. For example, if a + certificate has the KeyUsage extension marked critical and set to + `keyCertSign`, then when this certificate is presented during SSL + communication, it should be rejected because the certificate + extension indicates that the associated private key should only be + used for signing certificates and not for SSL use. + + - Serial number: The entity that created the certificate is responsible + for assigning it a serial number to distinguish it from other + certificates it issues. This information is used in numerous ways. For + example, when a certificate is revoked its serial number is placed in a + Certificate Revocation List (CRL). + + - Signature algorithm identifier: This identifies the algorithm used by + the CA to sign the certificate. + + - Issuer name: The X.500 Distinguished Name of the entity that signed the + certificate. This is typically a CA. Using this certificate implies + trusting the entity that signed this certificate. In some cases, such + as root or top-level CA certificates, the issuer signs its own + certificate. + + - Validity period: Each certificate is valid only for a limited amount of + time. This period is described by a start date and time and an end date + and time, and can be as short as a few seconds or almost as long as a + century. The validity period chosen depends on a number of factors, + such as the strength of the private key used to sign the certificate, + or the amount one is willing to pay for a certificate. This is the + expected period that entities can rely on the public value, when the + associated private key has not been compromised. + + - Subject name: The name of the entity whose public key the certificate + identifies. This name uses the X.500 standard, so it is intended to be + unique across the Internet. This is the X.500 Distinguished Name (DN) + of the entity. For example, + + > `CN=Java Duke, OU=Java Software Division, O=Oracle Corporation, + C=US` + + These refer to the subject's common name (CN), organizational unit + (OU), organization (O), and country (C). + + - Subject public key information: This is the public key of the entity + being named with an algorithm identifier that specifies which public + key crypto system this key belongs to and any associated key + parameters. + +Certificate Chains +: The `keytool` command can create and manage keystore key entries that each + contain a private key and an associated certificate chain. The first + certificate in the chain contains the public key that corresponds to the + private key. + + When keys are first generated, the chain usually starts off containing a single + element, a self-signed certificate. See -genkeypair in **Commands**. A + self-signed certificate is one for which the issuer (signer) is the same as + the subject. The subject is the entity whose public key is being + authenticated by the certificate. When the `-genkeypair` command is called + to generate a new public/private key pair, it also wraps the public key + into a self-signed certificate (unless the `-signer` option is specified). + + Later, after a Certificate Signing Request (CSR) was generated with the + `-certreq` command and sent to a Certification Authority (CA), the response + from the CA is imported with `-importcert`, and the self-signed certificate + is replaced by a chain of certificates. At the bottom of the chain is the + certificate (reply) issued by the CA authenticating the subject's public + key. The next certificate in the chain is one that authenticates the CA's + public key. + + In many cases, this is a self-signed certificate, which is a certificate + from the CA authenticating its own public key, and the last certificate in + the chain. In other cases, the CA might return a chain of certificates. In + this case, the bottom certificate in the chain is the same (a certificate + signed by the CA, authenticating the public key of the key entry), but the + second certificate in the chain is a certificate signed by a different CA + that authenticates the public key of the CA you sent the CSR to. The next + certificate in the chain is a certificate that authenticates the second + CA's key, and so on, until a self-signed root certificate is reached. Each + certificate in the chain (after the first) authenticates the public key of + the signer of the previous certificate in the chain. + + Many CAs only return the issued certificate, with no supporting chain, + especially when there is a flat hierarchy (no intermediates CAs). In this + case, the certificate chain must be established from trusted certificate + information already stored in the keystore. + + A different reply format (defined by the PKCS \#7 standard) includes the + supporting certificate chain in addition to the issued certificate. Both + reply formats can be handled by the `keytool` command. + + The top-level (root) CA certificate is self-signed. However, the trust into + the root's public key doesn't come from the root certificate itself, but + from other sources such as a newspaper. This is because anybody could + generate a self-signed certificate with the distinguished name of, for + example, the DigiCert root CA. The root CA public key is widely known. The + only reason it is stored in a certificate is because this is the format + understood by most tools, so the certificate in this case is only used as a + vehicle to transport the root CA's public key. Before you add the root CA + certificate to your keystore, you should view it with the `-printcert` + option and compare the displayed fingerprint with the well-known + fingerprint obtained from a newspaper, the root CA's Web page, and so on. + +cacerts Certificates File +: A certificates file named `cacerts` resides in the security properties + directory: + + - **Linux and macOS:** *JAVA\_HOME*`/lib/security` + + - **Windows:** *JAVA\_HOME*`\lib\security` + + The `cacerts` file represents a system-wide keystore with CA certificates. + System administrators can configure and manage that file with the `keytool` + command by specifying `jks` as the keystore type. The `cacerts` keystore + file ships with a default set of root CA certificates. For Linux, macOS, and + Windows, you can list the default certificates with the following command: + + > `keytool -list -cacerts` + + The initial password of the `cacerts` keystore file is `changeit`. System + administrators should change that password and the default access + permission of that file upon installing the SDK. + + **Note:** + + It is important to verify your `cacerts` file. Because you trust the CAs in + the `cacerts` file as entities for signing and issuing certificates to + other entities, you must manage the `cacerts` file carefully. The `cacerts` + file should contain only certificates of the CAs you trust. It is your + responsibility to verify the trusted root CA certificates bundled in the + `cacerts` file and make your own trust decisions. + + To remove an untrusted CA certificate from the `cacerts` file, use the + `-delete` option of the `keytool` command. You can find the `cacerts` file + in the JDK's `$JAVA_HOME/lib/security` directory. Contact your system + administrator if you don't have permission to edit this file. + +Internet RFC 1421 Certificate Encoding Standard +: Certificates are often stored using the printable encoding format defined + by the Internet RFC 1421 standard, instead of their binary encoding. This + certificate format, also known as Base64 encoding, makes it easy to export + certificates to other applications by email or through some other + mechanism. + + Certificates read by the `-importcert` and `-printcert` commands can be in + either this format or binary encoded. The `-exportcert` command by default + outputs a certificate in binary encoding, but will instead output a + certificate in the printable encoding format, when the `-rfc` option is + specified. + + The `-list` command by default prints the SHA-256 fingerprint of a + certificate. If the `-v` option is specified, then the certificate is + printed in human-readable format. If the `-rfc` option is specified, then + the certificate is output in the printable encoding format. + + In its printable encoding format, the encoded certificate is bounded at the + beginning and end by the following text: + + ``` + -----BEGIN CERTIFICATE----- + + encoded certificate goes here. + + -----END CERTIFICATE----- + ``` + +X.500 Distinguished Names +: X.500 Distinguished Names are used to identify entities, such as those that + are named by the `subject` and `issuer` (signer) fields of X.509 + certificates. The `keytool` command supports the following subparts: + + - commonName: The common name of a person such as Susan Jones. + + - organizationUnit: The small organization (such as department or + division) name. For example, Purchasing. + + - localityName: The locality (city) name, for example, Palo Alto. + + - stateName: State or province name, for example, California. + + - country: Two-letter country code, for example, CH. + + When you supply a distinguished name string as the value of a `-dname` + option, such as for the `-genkeypair` command, the string must be in the + following format: + + > `CN=cName, OU=orgUnit, O=org, L=city, S=state, C=countryCode` + + All the following items represent actual values and the previous keywords + are abbreviations for the following: + + ``` + CN=commonName + OU=organizationUnit + O=organizationName + L=localityName + S=stateName + C=country + ``` + + A sample distinguished name string is: + + > `CN=Mark Smith, OU=Java, O=Oracle, L=Cupertino, S=California, C=US` + + A sample command using such a string is: + + > `keytool -genkeypair -dname "CN=Mark Smith, OU=Java, O=Oracle, + L=Cupertino, S=California, C=US" -alias mark -keyalg rsa` + + Case doesn't matter for the keyword abbreviations. For example, CN, cn, and + Cn are all treated the same. + + Order matters; each subcomponent must appear in the designated order. + However, it isn't necessary to have all the subcomponents. You can use a + subset, for example: + + > `CN=Smith, OU=Java, O=Oracle, C=US` + + If a distinguished name string value contains a comma, then the comma must + be escaped by a backslash (\\) character when you specify the string on a + command line, as in: + + > `cn=Jack, ou=Java\, Product Development, o=Oracle, c=US` + + It is never necessary to specify a distinguished name string on a command + line. When the distinguished name is needed for a command, but not supplied + on the command line, the user is prompted for each of the subcomponents. In + this case, a comma doesn't need to be escaped by a backslash (\\). + +## Warnings + +## Importing Trusted Certificates Warning + +**Important**: Be sure to check a certificate very carefully before importing +it as a trusted certificate. + +**Windows Example:** + +View the certificate first with the `-printcert` command or the `-importcert` +command without the `-noprompt` option. Ensure that the displayed certificate +fingerprints match the expected ones. For example, suppose someone sends or +emails you a certificate that you put it in a file named `\tmp\cert`. Before +you consider adding the certificate to your list of trusted certificates, you +can execute a `-printcert` command to view its fingerprints, as follows: + +``` + keytool -printcert -file \tmp\cert + Owner: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll + Issuer: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll + Serial Number: 59092b34 + Valid from: Thu Jun 24 18:01:13 PDT 2016 until: Wed Jun 23 17:01:13 PST 2016 + Certificate Fingerprints: + + SHA-1: 20:B6:17:FA:EF:E5:55:8A:D0:71:1F:E8:D6:9D:C0:37:13:0E:5E:FE + SHA-256: 90:7B:70:0A:EA:DC:16:79:92:99:41:FF:8A:FE:EB:90: + 17:75:E0:90:B2:24:4D:3A:2A:16:A6:E4:11:0F:67:A4 +``` + +**Linux Example:** + +View the certificate first with the `-printcert` command or the `-importcert` +command without the `-noprompt` option. Ensure that the displayed certificate +fingerprints match the expected ones. For example, suppose someone sends or +emails you a certificate that you put it in a file named `/tmp/cert`. Before +you consider adding the certificate to your list of trusted certificates, you +can execute a `-printcert` command to view its fingerprints, as follows: + +``` + keytool -printcert -file /tmp/cert + Owner: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll + Issuer: CN=ll, OU=ll, O=ll, L=ll, S=ll, C=ll + Serial Number: 59092b34 + Valid from: Thu Jun 24 18:01:13 PDT 2016 until: Wed Jun 23 17:01:13 PST 2016 + Certificate Fingerprints: + + SHA-1: 20:B6:17:FA:EF:E5:55:8A:D0:71:1F:E8:D6:9D:C0:37:13:0E:5E:FE + SHA-256: 90:7B:70:0A:EA:DC:16:79:92:99:41:FF:8A:FE:EB:90: + 17:75:E0:90:B2:24:4D:3A:2A:16:A6:E4:11:0F:67:A4 +``` + +Then call or otherwise contact the person who sent the certificate and compare +the fingerprints that you see with the ones that they show. Only when the +fingerprints are equal is it guaranteed that the certificate wasn't replaced in +transit with somebody else's certificate such as an attacker's certificate. If +such an attack took place, and you didn't check the certificate before you +imported it, then you would be trusting anything the attacker signed, for +example, a JAR file with malicious class files inside. + +**Note:** + +It isn't required that you execute a `-printcert` command before importing a +certificate. This is because before you add a certificate to the list of +trusted certificates in the keystore, the `-importcert` command prints out the +certificate information and prompts you to verify it. You can then stop the +import operation. However, you can do this only when you call the `-importcert` +command without the `-noprompt` option. If the `-noprompt` option is specified, +then there is no interaction with the user. + +## Passwords Warning + +Most commands that operate on a keystore require the store password. Some +commands require a private/secret key password. Passwords can be specified on +the command line in the `-storepass` and `-keypass` options. However, a +password shouldn't be specified on a command line or in a script unless it is +for testing, or you are on a secure system. When you don't specify a required +password option on a command line, you are prompted for it. + +## Certificate Conformance Warning + +[Internet X.509 Public Key Infrastructure Certificate and Certificate +Revocation List (CRL) Profile](https://tools.ietf.org/rfc/rfc5280.txt) defined +a profile on conforming X.509 certificates, which includes what values and +value combinations are valid for certificate fields and extensions. + +The `keytool` command doesn't enforce all of these rules so it can generate +certificates that don't conform to the standard, such as self-signed +certificates that would be used for internal testing purposes. Certificates +that don't conform to the standard might be rejected by the JDK or other +applications. Users should ensure that they provide the correct options for +`-dname`, `-ext`, and so on. + +## Import a New Trusted Certificate + +Before you add the certificate to the keystore, the `keytool` command verifies +it by attempting to construct a chain of trust from that certificate to a +self-signed certificate (belonging to a root CA), using trusted certificates +that are already available in the keystore. + +If the `-trustcacerts` option was specified, then additional certificates are +considered for the chain of trust, namely the certificates in a file named +`cacerts`. + +If the `keytool` command fails to establish a trust path from the certificate +to be imported up to a self-signed certificate (either from the keystore or the +`cacerts` file), then the certificate information is printed, and the user is +prompted to verify it by comparing the displayed certificate fingerprints with +the fingerprints obtained from some other (trusted) source of information, +which might be the certificate owner. Be very careful to ensure the certificate +is valid before importing it as a trusted certificate. The user then has the +option of stopping the import operation. If the `-noprompt` option is +specified, then there is no interaction with the user. + +## Import a Certificate Reply + +When you import a certificate reply, the certificate reply is validated with +trusted certificates from the keystore, and optionally, the certificates +configured in the `cacerts` keystore file when the `-trustcacerts` option is +specified. + +The methods of determining whether the certificate reply is trusted are as +follows: + +- If the reply is a single X.509 certificate, then the `keytool` command + attempts to establish a trust chain, starting at the certificate reply and + ending at a self-signed certificate (belonging to a root CA). The + certificate reply and the hierarchy of certificates is used to authenticate + the certificate reply from the new certificate chain of aliases. If a trust + chain can't be established, then the certificate reply isn't imported. In + this case, the `keytool` command doesn't print the certificate and prompt + the user to verify it, because it is very difficult for a user to determine + the authenticity of the certificate reply. + +- If the reply is a PKCS \#7 formatted certificate chain or a sequence of + X.509 certificates, then the chain is ordered with the user certificate + first followed by zero or more CA certificates. If the chain ends with a + self-signed root CA certificate and the`-trustcacerts` option was + specified, the `keytool` command attempts to match it with any of the + trusted certificates in the keystore or the `cacerts` keystore file. If the + chain doesn't end with a self-signed root CA certificate and the + `-trustcacerts` option was specified, the `keytool` command tries to find + one from the trusted certificates in the keystore or the `cacerts` keystore + file and add it to the end of the chain. If the certificate isn't found and + the `-noprompt` option isn't specified, the information of the last + certificate in the chain is printed, and the user is prompted to verify it. + +If the public key in the certificate reply matches the user's public key +already stored with `alias`, then the old certificate chain is replaced with +the new certificate chain in the reply. The old chain can only be replaced with +a valid `keypass`, and so the password used to protect the private key of the +entry is supplied. If no password is provided, and the private key password is +different from the keystore password, the user is prompted for it. + +This command was named `-import` in earlier releases. This old name is still +supported in this release. The new name, `-importcert`, is preferred. diff --git a/src/java.base/unix/classes/java/io/UnixFileSystem.java b/src/java.base/unix/classes/java/io/UnixFileSystem.java index 18afb729c01..ea2ca28fe86 100644 --- a/src/java.base/unix/classes/java/io/UnixFileSystem.java +++ b/src/java.base/unix/classes/java/io/UnixFileSystem.java @@ -27,7 +27,6 @@ import java.util.Properties; import jdk.internal.util.StaticProperty; -import sun.security.action.GetPropertyAction; final class UnixFileSystem extends FileSystem { @@ -36,7 +35,7 @@ final class UnixFileSystem extends FileSystem { private final String userDir; UnixFileSystem() { - Properties props = GetPropertyAction.privilegedGetProperties(); + Properties props = System.getProperties(); slash = props.getProperty("file.separator").charAt(0); colon = props.getProperty("path.separator").charAt(0); userDir = StaticProperty.userDir(); @@ -150,11 +149,6 @@ public boolean isInvalid(File f) { @Override public String resolve(File f) { if (isAbsolute(f)) return f.getPath(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPropertyAccess("user.dir"); - } return resolve(userDir, f.getPath()); } @@ -259,16 +253,7 @@ public boolean setReadOnly(File f) { @Override public File[] listRoots() { - try { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead("/"); - } - return new File[] { new File("/") }; - } catch (SecurityException x) { - return new File[0]; - } + return new File[] { new File("/") }; } /* -- Disk usage -- */ diff --git a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 8a2944081d5..c034cd4dcd7 100644 --- a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -35,7 +35,6 @@ import java.security.GeneralSecurityException; import java.util.Base64; import java.util.Locale; -import java.util.Objects; import java.util.Properties; import sun.net.www.HeaderParser; @@ -70,8 +69,7 @@ * through a proxy, rather between client and proxy, or between client and server (with no proxy) */ -public class NTLMAuthentication extends AuthenticationInfo { - private static final long serialVersionUID = 170L; +public final class NTLMAuthentication extends AuthenticationInfo { private static final NTLMAuthenticationCallback NTLMAuthCallback = NTLMAuthenticationCallback.getNTLMAuthenticationCallback(); diff --git a/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java b/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java index 868e859da29..d0cab80c664 100644 --- a/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java +++ b/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java @@ -149,18 +149,6 @@ protected void implCloseSelectableChannel() throws IOException { } } - /* - * If there's a SecurityManager then check for the appropriate - * RuntimePermission. - */ - private static void checkAccess() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("inheritedChannel")); - } - } - /* * If standard inherited channel is connected to a socket then return a Channel * of the appropriate type based standard input. @@ -252,11 +240,6 @@ public static synchronized Channel getChannel() throws IOException { haveChannel = true; } - // if there is a channel then do the security check before - // returning it. - if (channel != null) { - checkAccess(); - } return channel; } diff --git a/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java b/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java index d8e6ed1a21a..e98756c7e64 100644 --- a/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java +++ b/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,9 +31,6 @@ import java.io.FileDescriptor; import java.net.InetSocketAddress; import java.util.concurrent.atomic.AtomicBoolean; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * Unix implementation of AsynchronousServerSocketChannel @@ -64,11 +61,6 @@ private void enableAccept() { private Object acceptAttachment; private PendingFuture acceptFuture; - // context for permission check when security manager set - @SuppressWarnings("removal") - private AccessControlContext acceptAcc; - - UnixAsynchronousServerSocketChannelImpl(Port port) throws IOException { @@ -165,9 +157,9 @@ public void onEvent(int events, boolean mayInvokeDirect) { AsynchronousSocketChannel child = null; if (exc == null) { try { - child = finishAccept(newfd, isaa[0], acceptAcc); + child = finishAccept(newfd, isaa[0]); } catch (Throwable x) { - if (!(x instanceof IOException) && !(x instanceof SecurityException)) + if (!(x instanceof IOException)) x = new IOException(x); exc = x; } @@ -198,14 +190,12 @@ public void onEvent(int events, boolean mayInvokeDirect) { /** * Completes the accept by creating the AsynchronousSocketChannel for * the given file descriptor and remote address. If this method completes - * with an IOException or SecurityException then the channel/file descriptor + * with an IOException then the channel/file descriptor * will be closed. */ - @SuppressWarnings("removal") private AsynchronousSocketChannel finishAccept(FileDescriptor newfd, - final InetSocketAddress remote, - AccessControlContext acc) - throws IOException, SecurityException + final InetSocketAddress remote) + throws IOException { AsynchronousSocketChannel ch = null; try { @@ -215,38 +205,9 @@ private AsynchronousSocketChannel finishAccept(FileDescriptor newfd, throw x; } - // permission check must always be in initiator's context - try { - if (acc != null) { - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkAccept(remote.getAddress().getHostAddress(), - remote.getPort()); - } - return null; - } - }, acc); - } else { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkAccept(remote.getAddress().getHostAddress(), - remote.getPort()); - } - } - } catch (SecurityException x) { - try { - ch.close(); - } catch (Throwable suppressed) { - x.addSuppressed(suppressed); - } - throw x; - } return ch; } - @SuppressWarnings("removal") @Override Future implAccept(Object att, CompletionHandler handler) @@ -283,9 +244,6 @@ Future implAccept(Object att, int n = Net.accept(this.fd, newfd, isaa); if (n == IOStatus.UNAVAILABLE) { - // need calling context when there is security manager as - // permission check may be done in a different thread without - // any application call frames on the stack PendingFuture result = null; synchronized (updateLock) { if (handler == null) { @@ -296,8 +254,6 @@ Future implAccept(Object att, this.acceptHandler = handler; this.acceptAttachment = att; } - this.acceptAcc = (System.getSecurityManager() == null) ? - null : AccessController.getContext(); this.acceptPending = true; } @@ -318,7 +274,7 @@ Future implAccept(Object att, if (exc == null) { // connection accepted immediately try { - child = finishAccept(newfd, isaa[0], null); + child = finishAccept(newfd, isaa[0]); } catch (Throwable x) { exc = x; } diff --git a/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java index 49960b7ed21..b9c099ef92f 100644 --- a/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java +++ b/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -35,7 +35,6 @@ import sun.net.ConnectionResetException; import sun.net.NetHooks; import sun.net.util.SocketExceptions; -import sun.security.action.GetPropertyAction; /** * Unix implementation of AsynchronousSocketChannel @@ -49,7 +48,7 @@ private static enum OpType { CONNECT, READ, WRITE }; private static final boolean disableSynchronousRead; static { - String propValue = GetPropertyAction.privilegedGetProperty( + String propValue = System.getProperty( "sun.nio.ch.disableSynchronousRead", "false"); disableSynchronousRead = propValue.isEmpty() ? true : Boolean.parseBoolean(propValue); @@ -309,12 +308,6 @@ Future implConnect(SocketAddress remote, InetSocketAddress isa = Net.checkAddress(remote); - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); - // check and set state boolean notifyBeforeTcpConnect; synchronized (stateLock) { diff --git a/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketsUtil.java b/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketsUtil.java index b28bf9d093c..f3f6499871e 100644 --- a/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketsUtil.java +++ b/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketsUtil.java @@ -26,8 +26,6 @@ package sun.nio.ch; import java.nio.charset.Charset; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.net.NetProperties; import jdk.internal.util.StaticProperty; @@ -51,16 +49,12 @@ static Charset getCharset() { * 2. ${jdk.net.unixdomain.tmpdir} if set as net property * 3. ${java.io.tmpdir} system property */ - @SuppressWarnings("removal") static String getTempDir() { - PrivilegedAction action = () -> { - String s = NetProperties.get("jdk.net.unixdomain.tmpdir"); - if (s != null && s.length() > 0) { - return s; - } else { - return StaticProperty.javaIoTmpDir(); - } - }; - return AccessController.doPrivileged(action); + String s = NetProperties.get("jdk.net.unixdomain.tmpdir"); + if (s != null && s.length() > 0) { + return s; + } else { + return StaticProperty.javaIoTmpDir(); + } } } diff --git a/src/java.base/unix/classes/sun/nio/fs/MimeTypesFileTypeDetector.java b/src/java.base/unix/classes/sun/nio/fs/MimeTypesFileTypeDetector.java index e68158c2569..67abe634ab1 100644 --- a/src/java.base/unix/classes/sun/nio/fs/MimeTypesFileTypeDetector.java +++ b/src/java.base/unix/classes/sun/nio/fs/MimeTypesFileTypeDetector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,6 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -93,19 +91,13 @@ private void loadMimeTypes() { if (!loaded) { synchronized (this) { if (!loaded) { - @SuppressWarnings("removal") - List lines = AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public List run() { - try { - return Files.readAllLines(mimeTypesFile, - Charset.defaultCharset()); - } catch (IOException ignore) { - return Collections.emptyList(); - } - } - }); + List lines; + try { + lines = Files.readAllLines(mimeTypesFile, + Charset.defaultCharset()); + } catch (IOException ignore) { + lines = Collections.emptyList(); + } mimeTypeMap = HashMap.newHashMap(lines.size()); String entry = ""; diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java b/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java index 8e5bf38882c..dec13180f2f 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java @@ -25,9 +25,9 @@ package sun.nio.fs; +import java.io.FileDescriptor; import java.nio.file.*; import java.nio.channels.*; -import java.io.FileDescriptor; import java.util.Set; import jdk.internal.access.SharedSecrets; @@ -108,7 +108,6 @@ static Flags toFlags(Set options) { */ static FileChannel newFileChannel(int dfd, UnixPath path, - String pathForPermissionCheck, Set options, int mode) throws UnixException @@ -130,7 +129,7 @@ static FileChannel newFileChannel(int dfd, if (flags.append && flags.truncateExisting) throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); - FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode); + FileDescriptor fdObj = open(dfd, path, flags, mode); return FileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, (flags.sync || flags.dsync), flags.direct, null); } @@ -143,7 +142,7 @@ static FileChannel newFileChannel(UnixPath path, int mode) throws UnixException { - return newFileChannel(-1, path, null, options, mode); + return newFileChannel(-1, path, options, mode); } /** @@ -167,7 +166,7 @@ static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path, throw new UnsupportedOperationException("APPEND not allowed"); // for now use simple implementation - FileDescriptor fdObj = open(-1, path, null, flags, mode); + FileDescriptor fdObj = open(-1, path, flags, mode); return SimpleAsynchronousFileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, pool); } @@ -177,7 +176,6 @@ static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path, */ protected static FileDescriptor open(int dfd, UnixPath path, - String pathForPermissionCheck, Flags flags, int mode) throws UnixException @@ -236,20 +234,6 @@ protected static FileDescriptor open(int dfd, if (flags.direct) oflags |= O_DIRECT; - // permission check before we open the file - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (pathForPermissionCheck == null) - pathForPermissionCheck = path.getPathForPermissionCheck(); - if (flags.read) - sm.checkRead(pathForPermissionCheck); - if (flags.write) - sm.checkWrite(pathForPermissionCheck); - if (flags.deleteOnClose) - sm.checkDelete(pathForPermissionCheck); - } - int fd; try { if (dfd >= 0) { diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java index 033deee2f4f..aadef1ea50f 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -25,11 +25,11 @@ package sun.nio.fs; +import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.*; import java.util.*; import java.util.concurrent.TimeUnit; -import java.io.IOException; import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixNativeDispatcher.*; @@ -47,7 +47,6 @@ static class Basic extends AbstractBasicFileAttributeView { @Override public BasicFileAttributes readAttributes() throws IOException { - file.checkRead(); try { UnixFileAttributes attrs = UnixFileAttributes.get(file, followLinks); @@ -69,45 +68,25 @@ public void setTimes(FileTime lastModifiedTime, return; } - // permission check - file.checkWrite(); - - boolean haveFd = false; - boolean useFutimes = false; - boolean useFutimens = false; - boolean useLutimes = false; - boolean useUtimensat = false; + // use a file descriptor if possible to avoid a race due to + // accessing a path more than once as the file at that path could + // change. + // if path is a symlink, then the open should fail with ELOOP and + // the path will be used instead of the file descriptor. int fd = -1; try { - if (!followLinks) { - // these path-based syscalls also work if following links - if (!(useUtimensat = utimensatSupported())) { - useLutimes = lutimesSupported(); - } - } - if (!useUtimensat && !useLutimes) { - fd = file.openForAttributeAccess(followLinks); - if (fd != -1) { - haveFd = true; - if (!(useFutimens = futimensSupported())) { - useFutimes = futimesSupported(); - } - } - } + fd = file.openForAttributeAccess(followLinks); } catch (UnixException x) { - if (!(x.errno() == ENXIO || - (x.errno() == ELOOP && (useUtimensat || useLutimes)))) { + if (!(x.errno() == ENXIO || (x.errno() == ELOOP))) { x.rethrowAsIOException(file); } } try { - // assert followLinks || !UnixFileAttributes.get(fd).isSymbolicLink(); - // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { - UnixFileAttributes attrs = haveFd ? + UnixFileAttributes attrs = fd >= 0 ? UnixFileAttributes.get(fd) : UnixFileAttributes.get(file, followLinks); if (lastModifiedTime == null) @@ -120,28 +99,20 @@ public void setTimes(FileTime lastModifiedTime, } // update times - TimeUnit timeUnit = (useFutimens || useUtimensat) ? - TimeUnit.NANOSECONDS : TimeUnit.MICROSECONDS; - long modValue = lastModifiedTime.to(timeUnit); - long accessValue= lastAccessTime.to(timeUnit); + long modValue = lastModifiedTime.to(TimeUnit.NANOSECONDS); + long accessValue= lastAccessTime.to(TimeUnit.NANOSECONDS); boolean retry = false; try { - if (useFutimens) { + if (fd >= 0) futimens(fd, accessValue, modValue); - } else if (useFutimes) { - futimes(fd, accessValue, modValue); - } else if (useLutimes) { - lutimes(file, accessValue, modValue); - } else if (useUtimensat) { + else utimensat(AT_FDCWD, file, accessValue, modValue, followLinks ? 0 : AT_SYMLINK_NOFOLLOW); - } else { - utimes(file, accessValue, modValue); - } } catch (UnixException x) { - // if futimes/utimes fails with EINVAL and one/both of the times is - // negative then we adjust the value to the epoch and retry. + // if utimensat fails with EINVAL and one/both of + // the times is negative then we adjust the value to the + // epoch and retry. if (x.errno() == EINVAL && (modValue < 0L || accessValue < 0L)) { retry = true; @@ -153,18 +124,11 @@ public void setTimes(FileTime lastModifiedTime, if (modValue < 0L) modValue = 0L; if (accessValue < 0L) accessValue= 0L; try { - if (useFutimens) { + if (fd >= 0) futimens(fd, accessValue, modValue); - } else if (useFutimes) { - futimes(fd, accessValue, modValue); - } else if (useLutimes) { - lutimes(file, accessValue, modValue); - } else if (useUtimensat) { + else utimensat(AT_FDCWD, file, accessValue, modValue, followLinks ? 0 : AT_SYMLINK_NOFOLLOW); - } else { - utimes(file, accessValue, modValue); - } } catch (UnixException x) { x.rethrowAsIOException(file); } @@ -188,24 +152,6 @@ static class Posix extends Basic implements PosixFileAttributeView { super(file, followLinks); } - final void checkReadExtended() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - file.checkRead(); - sm.checkPermission(new RuntimePermission("accessUserInformation")); - } - } - - final void checkWriteExtended() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - file.checkWrite(); - sm.checkPermission(new RuntimePermission("accessUserInformation")); - } - } - @Override public String name() { return "posix"; @@ -260,7 +206,6 @@ public Map readAttributes(String[] requested) @Override public UnixFileAttributes readAttributes() throws IOException { - checkReadExtended(); try { return UnixFileAttributes.get(file, followLinks); } catch (UnixException x) { @@ -271,8 +216,6 @@ public UnixFileAttributes readAttributes() throws IOException { // chmod final void setMode(int mode) throws IOException { - checkWriteExtended(); - if (followLinks) { try { chmod(file, mode); @@ -315,7 +258,6 @@ final void setMode(int mode) throws IOException { // chown final void setOwners(int uid, int gid) throws IOException { - checkWriteExtended(); try { if (followLinks) { chown(file, uid, gid); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java index 6704a588d10..4311cd6c646 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,8 +34,6 @@ import java.nio.channels.*; import java.util.*; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * Base implementation of FileStore for Unix/like implementations. @@ -269,17 +267,11 @@ enum FeatureStatus { /** * Returns status to indicate if file system supports a given feature */ - @SuppressWarnings("removal") FeatureStatus checkIfFeaturePresent(String feature) { if (props == null) { synchronized (loadLock) { if (props == null) { - props = AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public Properties run() { - return loadProperties(); - }}); + props = loadProperties(); } } } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java index 2b9ab775ed8..51ed4211fff 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java @@ -34,7 +34,6 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystemException; import java.nio.file.LinkOption; -import java.nio.file.LinkPermission; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.StandardCopyOption; @@ -54,7 +53,6 @@ import java.util.regex.Pattern; import sun.nio.ch.DirectBuffer; import sun.nio.ch.IOStatus; -import sun.security.action.GetPropertyAction; import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixNativeDispatcher.*; @@ -87,8 +85,7 @@ abstract class UnixFileSystem // if process-wide chdir is allowed or default directory is not the // process working directory then paths must be resolved against the // default directory. - String propValue = GetPropertyAction - .privilegedGetProperty("sun.nio.fs.chdirAllowed", "false"); + String propValue = System.getProperty("sun.nio.fs.chdirAllowed", "false"); boolean chdirAllowed = propValue.isEmpty() ? true : Boolean.parseBoolean(propValue); if (chdirAllowed) { this.needToResolveAgainstDefaultDirectory = true; @@ -179,20 +176,7 @@ void copyNonPosixAttributes(int sfd, int tfd) { */ @Override public final Iterable getRootDirectories() { - final List allowedList = List.of(rootDirectory); - return new Iterable<>() { - public Iterator iterator() { - try { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkRead(rootDirectory.toString()); - return allowedList.iterator(); - } catch (SecurityException x) { - return Collections.emptyIterator(); //disallowed - } - } - }; + return List.of(rootDirectory); } /** @@ -228,16 +212,6 @@ private FileStore readNext() { if (entry.isIgnored()) continue; - // check permission to read mount point - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkRead(Util.toString(entry.dir())); - } catch (SecurityException x) { - continue; - } - } try { return getFileStore(entry); } catch (IOException ignore) { @@ -275,20 +249,7 @@ public void remove() { @Override public final Iterable getFileStores() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); - } catch (SecurityException se) { - return Collections.emptyList(); - } - } - return new Iterable<>() { - public Iterator iterator() { - return new FileStoreIterator(); - } - }; + return FileStoreIterator::new; } @Override @@ -577,14 +538,14 @@ private void copyDirectory(UnixPath source, // copy time stamps last if (flags.copyBasicAttributes) { try { - if (dfd >= 0 && futimesSupported()) { - futimes(dfd, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); + if (dfd >= 0) { + futimens(dfd, + attrs.lastAccessTime().to(TimeUnit.NANOSECONDS), + attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS)); } else { - utimes(target, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); + utimensat(AT_FDCWD, target, + attrs.lastAccessTime().to(TimeUnit.NANOSECONDS), + attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS), 0); } } catch (UnixException x) { // unable to set times @@ -727,15 +688,9 @@ void copyFile(UnixPath source, // copy time attributes if (flags.copyBasicAttributes) { try { - if (futimesSupported()) { - futimes(fo, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); - } else { - utimes(target, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); - } + futimens(fo, + attrs.lastAccessTime().to(TimeUnit.NANOSECONDS), + attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS)); } catch (UnixException x) { if (flags.failIfUnableToCopyBasic) x.rethrowAsIOException(target); @@ -814,9 +769,10 @@ private void copySpecial(UnixPath source, } if (flags.copyBasicAttributes) { try { - utimes(target, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); + utimensat(AT_FDCWD, target, + attrs.lastAccessTime().to(TimeUnit.NANOSECONDS), + attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS), + 0); } catch (UnixException x) { if (flags.failIfUnableToCopyBasic) x.rethrowAsIOException(target); @@ -850,14 +806,6 @@ static void ensureEmptyDir(UnixPath dir) throws IOException { void move(UnixPath source, UnixPath target, CopyOption... options) throws IOException { - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - source.checkWrite(); - target.checkWrite(); - } - // translate options into flags Flags flags = Flags.fromMoveOptions(options); @@ -993,14 +941,6 @@ void copy(final UnixPath source, final UnixPath target, CopyOption... options) throws IOException { - // permission checks - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - source.checkRead(); - target.checkWrite(); - } - // translate options into flags final Flags flags = Flags.fromCopyOptions(options); @@ -1014,11 +954,6 @@ void copy(final UnixPath source, x.rethrowAsIOException(source); } - // if source file is symbolic link then we must check LinkPermission - if (sm != null && sourceAttrs.isSymbolicLink()) { - sm.checkPermission(new LinkPermission("symbolic")); - } - // ensure source can be copied if (!sourceAttrs.isSymbolicLink() || flags.followLinks) { // the access(2) system call always follows links so it diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java index 7b3bca3acac..ed846354ea0 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java @@ -40,7 +40,6 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystemAlreadyExistsException; import java.nio.file.LinkOption; -import java.nio.file.LinkPermission; import java.nio.file.NotDirectoryException; import java.nio.file.NotLinkException; import java.nio.file.OpenOption; @@ -59,7 +58,6 @@ import jdk.internal.util.StaticProperty; import sun.nio.ch.ThreadPool; -import sun.security.util.SecurityConstants; import static sun.nio.fs.UnixNativeDispatcher.*; import static sun.nio.fs.UnixConstants.*; @@ -171,7 +169,6 @@ public A readAttributesIfExists(Path path, { if (type == BasicFileAttributes.class && Util.followLinks(options)) { UnixPath file = UnixPath.toUnixPath(path); - file.checkRead(); try { @SuppressWarnings("unchecked") A attrs = (A) UnixFileAttributes.getIfExists(file); @@ -250,7 +247,6 @@ public SeekableByteChannel newByteChannel(Path obj, @Override boolean implDelete(Path obj, boolean failIfNotExists) throws IOException { UnixPath file = UnixPath.toUnixPath(obj); - file.checkDelete(); // need file attributes to know if file is directory UnixFileAttributes attrs = null; @@ -317,20 +313,12 @@ public void checkAccess(Path obj, AccessMode... modes) throws IOException { int mode = 0; if (e || r) { - file.checkRead(); mode |= (r) ? R_OK : F_OK; } if (w) { - file.checkWrite(); mode |= W_OK; } if (x) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // not cached - sm.checkExec(file.getPathForPermissionCheck()); - } mode |= X_OK; } int errno = access(file, mode); @@ -341,26 +329,18 @@ public void checkAccess(Path obj, AccessMode... modes) throws IOException { @Override public boolean isReadable(Path path) { UnixPath file = UnixPath.toUnixPath(path); - file.checkRead(); return access(file, R_OK) == 0; } @Override public boolean isWritable(Path path) { UnixPath file = UnixPath.toUnixPath(path); - file.checkWrite(); return access(file, W_OK) == 0; } @Override public boolean isExecutable(Path path) { UnixPath file = UnixPath.toUnixPath(path); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // not cached - sm.checkExec(file.getPathForPermissionCheck()); - } return access(file, X_OK) == 0; } @@ -374,10 +354,6 @@ public boolean isSameFile(Path obj1, Path obj2) throws IOException { if (!(obj2 instanceof UnixPath file2)) return false; - // check security manager access to both files - file1.checkRead(); - file2.checkRead(); - UnixFileAttributes attrs1; UnixFileAttributes attrs2; try { @@ -398,7 +374,6 @@ public boolean isSameFile(Path obj1, Path obj2) throws IOException { @Override public boolean isHidden(Path obj) { UnixPath file = UnixPath.toUnixPath(obj); - file.checkRead(); UnixPath name = file.getFileName(); if (name == null) return false; @@ -421,12 +396,6 @@ public boolean isHidden(Path obj) { @Override public FileStore getFileStore(Path obj) throws IOException { UnixPath file = UnixPath.toUnixPath(obj); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); - file.checkRead(); - } return getFileStore(file); } @@ -435,7 +404,6 @@ public void createDirectory(Path obj, FileAttribute... attrs) throws IOException { UnixPath dir = UnixPath.toUnixPath(obj); - dir.checkWrite(); int mode = UnixFileModeAttribute.toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs); try { @@ -453,7 +421,6 @@ public DirectoryStream newDirectoryStream(Path obj, DirectoryStream.Filter throws IOException { UnixPath dir = UnixPath.toUnixPath(obj); - dir.checkRead(); if (filter == null) throw new NullPointerException(); @@ -506,14 +473,6 @@ public void createSymbolicLink(Path obj1, Path obj2, FileAttribute... attrs) " not supported when creating symbolic link"); } - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new LinkPermission("symbolic")); - link.checkWrite(); - } - // create link try { symlink(target.asByteArray(), link); @@ -527,14 +486,6 @@ public void createLink(Path obj1, Path obj2) throws IOException { UnixPath link = UnixPath.toUnixPath(obj1); UnixPath existing = UnixPath.toUnixPath(obj2); - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new LinkPermission("hard")); - link.checkWrite(); - existing.checkWrite(); - } try { link(existing, link); } catch (UnixException x) { @@ -545,14 +496,6 @@ public void createLink(Path obj1, Path obj2) throws IOException { @Override public Path readSymbolicLink(Path obj1) throws IOException { UnixPath link = UnixPath.toUnixPath(obj1); - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - FilePermission perm = new FilePermission(link.getPathForPermissionCheck(), - SecurityConstants.FILE_READLINK_ACTION); - sm.checkPermission(perm); - } try { byte[] target = readlink(link); return new UnixPath(link.getFileSystem(), target); @@ -568,7 +511,6 @@ public Path readSymbolicLink(Path obj1) throws IOException { public boolean exists(Path path, LinkOption... options) { if (Util.followLinks(options)) { UnixPath file = UnixPath.toUnixPath(path); - file.checkRead(); return access(file, F_OK) == 0; } else { return super.exists(path, options); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java index d6d2b9fdcd7..046f843371d 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -347,28 +347,6 @@ static void fchmod(int fd, int mode) throws UnixException { } private static native void fchmod0(int fd, int mode) throws UnixException; - /** - * utimes(const char* path, const struct timeval times[2]) - */ - static void utimes(UnixPath path, long times0, long times1) - throws UnixException - { - try (NativeBuffer buffer = copyToNativeBuffer(path)) { - utimes0(buffer.address(), times0, times1); - } - } - private static native void utimes0(long pathAddress, long times0, long times1) - throws UnixException; - - /** - * futimes(int fildes, const struct timeval times[2]) - */ - static void futimes(int fd, long times0, long times1) throws UnixException { - futimes0(fd, times0, times1); - } - private static native void futimes0(int fd, long times0, long times1) - throws UnixException; - /** * futimens(int fildes, const struct timespec times[2]) */ @@ -378,19 +356,6 @@ static void futimens(int fd, long times0, long times1) throws UnixException { private static native void futimens0(int fd, long times0, long times1) throws UnixException; - /** - * lutimes(const char* path, const struct timeval times[2]) - */ - static void lutimes(UnixPath path, long times0, long times1) - throws UnixException - { - try (NativeBuffer buffer = copyToNativeBuffer(path)) { - lutimes0(buffer.address(), times0, times1); - } - } - private static native void lutimes0(long pathAddress, long times0, long times1) - throws UnixException; - /** * utimensat(int fd, const char* path, * const struct timeval times[2], int flags) @@ -568,11 +533,7 @@ static native int flistxattr(int filedes, long listAddress, int size) * Capabilities */ private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls - private static final int SUPPORTS_FUTIMES = 1 << 2; - private static final int SUPPORTS_FUTIMENS = 1 << 3; - private static final int SUPPORTS_LUTIMES = 1 << 4; - private static final int SUPPORTS_UTIMENSAT = 1 << 5; - private static final int SUPPORTS_XATTR = 1 << 6; + private static final int SUPPORTS_XATTR = 1 << 3; private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features private static final int capabilities; @@ -583,34 +544,6 @@ static boolean openatSupported() { return (capabilities & SUPPORTS_OPENAT) != 0; } - /** - * Supports futimes - */ - static boolean futimesSupported() { - return (capabilities & SUPPORTS_FUTIMES) != 0; - } - - /** - * Supports futimens - */ - static boolean futimensSupported() { - return (capabilities & SUPPORTS_FUTIMENS) != 0; - } - - /** - * Supports lutimes - */ - static boolean lutimesSupported() { - return (capabilities & SUPPORTS_LUTIMES) != 0; - } - - /** - * Supports utimensat - */ - static boolean utimensatSupported() { - return (capabilities & SUPPORTS_UTIMENSAT) != 0; - } - /** * Supports file birth (creation) time attribute */ diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixPath.java b/src/java.base/unix/classes/sun/nio/fs/UnixPath.java index 7898acdc452..e2f52e701cb 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixPath.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixPath.java @@ -833,47 +833,18 @@ int openForAttributeAccess(boolean followLinks) throws UnixException { return open(this, flags, 0); } - void checkRead() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkRead(getPathForPermissionCheck()); - } - - void checkWrite() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkWrite(getPathForPermissionCheck()); - } - - void checkDelete() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkDelete(getPathForPermissionCheck()); - } - @Override public UnixPath toAbsolutePath() { if (isAbsolute()) { return this; } - // The path is relative so need to resolve against default directory, - // taking care not to reveal the user.dir - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPropertyAccess("user.dir"); - } + // The path is relative so need to resolve against default directory return new UnixPath(getFileSystem(), resolve(getFileSystem().defaultDirectory(), path)); } @Override public Path toRealPath(LinkOption... options) throws IOException { - checkRead(); - UnixPath absolute = toAbsolutePath(); // if resolving links then use realpath @@ -1022,7 +993,6 @@ public WatchKey register(WatchService watcher, throw new NullPointerException(); if (!(watcher instanceof AbstractWatchService)) throw new ProviderMismatchException(); - checkRead(); return ((AbstractWatchService)watcher).register(this, events, modifiers); } } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java b/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java index bedf847c6e7..ce04f49a9e2 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,12 @@ package sun.nio.fs; +import java.io.IOException; +import java.nio.channels.SeekableByteChannel; import java.nio.file.*; import java.nio.file.attribute.*; -import java.nio.channels.SeekableByteChannel; import java.util.*; import java.util.concurrent.TimeUnit; -import java.io.IOException; import static sun.nio.fs.UnixNativeDispatcher.*; import static sun.nio.fs.UnixConstants.*; @@ -93,13 +93,6 @@ public SecureDirectoryStream newDirectoryStream(Path obj, UnixPath child = ds.directory().resolve(file); boolean followLinks = Util.followLinks(options); - // permission check using name resolved against original path of directory - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - child.checkRead(); - } - ds.readLock().lock(); try { if (!ds.isOpen()) @@ -146,15 +139,12 @@ public SeekableByteChannel newByteChannel(Path obj, int mode = UnixFileModeAttribute .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); - // path for permission check - String pathToCheck = ds.directory().resolve(file).getPathForPermissionCheck(); - ds.readLock().lock(); try { if (!ds.isOpen()) throw new ClosedDirectoryStreamException(); try { - return UnixChannelFactory.newFileChannel(dfd, file, pathToCheck, options, mode); + return UnixChannelFactory.newFileChannel(dfd, file, options, mode); } catch (UnixException x) { x.rethrowAsIOException(file); return null; // keep compiler happy @@ -173,13 +163,6 @@ private void implDelete(Path obj, boolean haveFlags, int flags) { UnixPath file = getName(obj); - // permission check using name resolved against original path of directory - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ds.directory().resolve(file).checkDelete(); - } - ds.readLock().lock(); try { if (!ds.isOpen()) @@ -239,14 +222,6 @@ public void move(Path fromObj, SecureDirectoryStream dir, Path toObj) throw new ProviderMismatchException(); UnixSecureDirectoryStream that = (UnixSecureDirectoryStream)dir; - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - this.ds.directory().resolve(from).checkWrite(); - that.ds.directory().resolve(to).checkWrite(); - } - // lock ordering doesn't matter this.ds.readLock().lock(); try { @@ -337,18 +312,6 @@ int open() throws IOException { } } - private void checkWriteAccess() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (file == null) { - ds.directory().checkWrite(); - } else { - ds.directory().resolve(file).checkWrite(); - } - } - } - @Override public String name() { return "basic"; @@ -361,15 +324,6 @@ public BasicFileAttributes readAttributes() throws IOException { if (!ds.isOpen()) throw new ClosedDirectoryStreamException(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (file == null) { - ds.directory().checkRead(); - } else { - ds.directory().resolve(file).checkRead(); - } - } try { UnixFileAttributes attrs = (file == null) ? UnixFileAttributes.get(dfd) : @@ -392,8 +346,6 @@ public void setTimes(FileTime lastModifiedTime, FileTime createTime) // ignore throws IOException { - checkWriteAccess(); - ds.readLock().lock(); try { if (!ds.isOpen()) @@ -415,9 +367,9 @@ public void setTimes(FileTime lastModifiedTime, } // update times try { - futimes(fd, - lastAccessTime.to(TimeUnit.MICROSECONDS), - lastModifiedTime.to(TimeUnit.MICROSECONDS)); + futimens(fd, + lastAccessTime.to(TimeUnit.NANOSECONDS), + lastModifiedTime.to(TimeUnit.NANOSECONDS)); } catch (UnixException x) { x.rethrowAsIOException(file); } @@ -441,15 +393,6 @@ private class PosixFileAttributeViewImpl super(file, followLinks); } - private void checkWriteAndUserAccess() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - super.checkWriteAccess(); - sm.checkPermission(new RuntimePermission("accessUserInformation")); - } - } - @Override public String name() { return "posix"; @@ -457,16 +400,6 @@ public String name() { @Override public PosixFileAttributes readAttributes() throws IOException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (file == null) - ds.directory().checkRead(); - else - ds.directory().resolve(file).checkRead(); - sm.checkPermission(new RuntimePermission("accessUserInformation")); - } - ds.readLock().lock(); try { if (!ds.isOpen()) @@ -490,9 +423,6 @@ public PosixFileAttributes readAttributes() throws IOException { public void setPermissions(Set perms) throws IOException { - // permission check - checkWriteAndUserAccess(); - ds.readLock().lock(); try { if (!ds.isOpen()) @@ -513,9 +443,6 @@ public void setPermissions(Set perms) } private void setOwners(int uid, int gid) throws IOException { - // permission check - checkWriteAndUserAccess(); - ds.readLock().lock(); try { if (!ds.isOpen()) diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java index 2cbc4c377a2..269e8b8f1fd 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -121,12 +121,11 @@ static URI toUri(UnixPath up) { // trailing slash if directory if (sb.charAt(sb.length()-1) != '/') { try { - up.checkRead(); UnixFileAttributes attrs = UnixFileAttributes.getIfExists(up); if (attrs != null && ((attrs.mode() & UnixConstants.S_IFMT) == UnixConstants.S_IFDIR)) sb.append('/'); - } catch (UnixException | SecurityException ignore) { } + } catch (UnixException ignore) { } } try { diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java b/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java index e814dde3229..5b8d50dabf2 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java @@ -25,9 +25,9 @@ package sun.nio.fs; +import java.io.IOException; import java.nio.file.*; import java.nio.ByteBuffer; -import java.io.IOException; import java.util.*; import jdk.internal.access.JavaNioAccess; @@ -114,12 +114,8 @@ private static List list(int fd, int bufSize) throws UnixException { } } - @SuppressWarnings("removal") @Override public List list() throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), true, false); - int fd = -1; try { fd = file.openForAttributeAccess(followLinks); @@ -141,12 +137,8 @@ public List list() throws IOException { } } - @SuppressWarnings("removal") @Override public int size(String name) throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), true, false); - int fd = -1; try { fd = file.openForAttributeAccess(followLinks); @@ -165,12 +157,8 @@ public int size(String name) throws IOException { } } - @SuppressWarnings("removal") @Override public int read(String name, ByteBuffer dst) throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), true, false); - if (dst.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); int pos = dst.position(); @@ -230,12 +218,8 @@ private int read(String name, long address, int rem) throws IOException { } } - @SuppressWarnings("removal") @Override public int write(String name, ByteBuffer src) throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), false, true); - int pos = src.position(); int lim = src.limit(); assert (pos <= lim); @@ -293,12 +277,8 @@ private void write(String name, long address, int rem) throws IOException { } } - @SuppressWarnings("removal") @Override public void delete(String name) throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), false, true); - int fd = -1; try { fd = file.openForAttributeAccess(followLinks); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java b/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java index 26da60fe2f8..f50dea108b0 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -132,11 +132,6 @@ public static Group fromGid(int gid) { private static int lookupName(String name, boolean isGroup) throws IOException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("lookupUserInformation")); - } int id; try { id = (isGroup) ? getgrnam(name) : getpwnam(name); diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index aa46a2470a1..1a616446b4a 100644 --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -204,28 +204,19 @@ typedef int openat_func(int, const char *, int, ...); typedef int fstatat_func(int, const char *, struct stat *, int); typedef int unlinkat_func(int, const char*, int); typedef int renameat_func(int, const char*, int, const char*); -typedef int futimes_func(int, const struct timeval *); -typedef int futimens_func(int, const struct timespec *); -typedef int lutimes_func(const char *, const struct timeval *); typedef DIR* fdopendir_func(int); #if defined(__linux__) typedef int statx_func(int dirfd, const char *restrict pathname, int flags, unsigned int mask, struct my_statx *restrict statxbuf); -typedef int utimensat_func(int dirfd, const char *pathname, - const struct timespec[2], int flags); #endif static openat_func* my_openat_func = NULL; static fstatat_func* my_fstatat_func = NULL; static unlinkat_func* my_unlinkat_func = NULL; static renameat_func* my_renameat_func = NULL; -static futimes_func* my_futimes_func = NULL; -static futimens_func* my_futimens_func = NULL; -static lutimes_func* my_lutimes_func = NULL; static fdopendir_func* my_fdopendir_func = NULL; #if defined(__linux__) static statx_func* my_statx_func = NULL; -static utimensat_func* my_utimensat_func = NULL; #endif /** @@ -375,18 +366,6 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) #endif my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat"); my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat"); -#if defined(__linux__) && defined(__arm__) - my_futimes_func = (futimes_func*) lookup_time_t_function("futimes", - "__futimes64"); - my_lutimes_func = (lutimes_func*) lookup_time_t_function("lutimes", - "__lutimes64"); - my_futimens_func = (futimens_func*) lookup_time_t_function("futimens", - "__futimens64"); -#else - my_futimes_func = (futimes_func*) dlsym(RTLD_DEFAULT, "futimes"); - my_lutimes_func = (lutimes_func*) dlsym(RTLD_DEFAULT, "lutimes"); - my_futimens_func = (futimens_func*) dlsym(RTLD_DEFAULT, "futimens"); -#endif #if defined(_AIX) // Make sure we link to the 64-bit version of the function my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir64"); @@ -402,25 +381,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) my_fstatat_func = (fstatat_func*)&fstatat_wrapper; #endif - /* supports futimes, futimens, and/or lutimes */ - -#ifdef _ALLBSD_SOURCE - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES; - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES; -#else - if (my_futimes_func != NULL) - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES; - if (my_lutimes_func != NULL) - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES; -#endif - if (my_futimens_func != NULL) - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMENS; - /* supports openat, etc. */ if (my_openat_func != NULL && my_fstatat_func != NULL && my_unlinkat_func != NULL && my_renameat_func != NULL && - my_futimes_func != NULL && my_fdopendir_func != NULL) + my_fdopendir_func != NULL) { capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_OPENAT; } @@ -435,10 +400,6 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) if (my_statx_func != NULL) { capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME; } - my_utimensat_func = (utimensat_func*) dlsym(RTLD_DEFAULT, "utimensat"); - if (my_utimensat_func != NULL) { - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_UTIMENSAT; - } #endif /* supports extended attributes */ @@ -905,33 +866,6 @@ Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this, } } -JNIEXPORT void JNICALL -Java_sun_nio_fs_UnixNativeDispatcher_futimes0(JNIEnv* env, jclass this, jint filedes, - jlong accessTime, jlong modificationTime) -{ - struct timeval times[2]; - int err = 0; - - times[0].tv_sec = accessTime / 1000000; - times[0].tv_usec = accessTime % 1000000; - - times[1].tv_sec = modificationTime / 1000000; - times[1].tv_usec = modificationTime % 1000000; - -#ifdef _ALLBSD_SOURCE - RESTARTABLE(futimes(filedes, ×[0]), err); -#else - if (my_futimes_func == NULL) { - JNU_ThrowInternalError(env, "my_futimes_func is NULL"); - return; - } - RESTARTABLE((*my_futimes_func)(filedes, ×[0]), err); -#endif - if (err == -1) { - throwUnixException(env, errno); - } -} - JNIEXPORT void JNICALL Java_sun_nio_fs_UnixNativeDispatcher_futimens0(JNIEnv* env, jclass this, jint filedes, jlong accessTime, jlong modificationTime) @@ -945,39 +879,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_futimens0(JNIEnv* env, jclass this, jint fi times[1].tv_sec = modificationTime / 1000000000; times[1].tv_nsec = modificationTime % 1000000000; - if (my_futimens_func == NULL) { - JNU_ThrowInternalError(env, "my_futimens_func is NULL"); - return; - } - RESTARTABLE((*my_futimens_func)(filedes, ×[0]), err); - if (err == -1) { - throwUnixException(env, errno); - } -} - -JNIEXPORT void JNICALL -Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this, - jlong pathAddress, jlong accessTime, jlong modificationTime) -{ - int err; - struct timeval times[2]; - const char* path = (const char*)jlong_to_ptr(pathAddress); - - times[0].tv_sec = accessTime / 1000000; - times[0].tv_usec = accessTime % 1000000; - - times[1].tv_sec = modificationTime / 1000000; - times[1].tv_usec = modificationTime % 1000000; - -#ifdef _ALLBSD_SOURCE - RESTARTABLE(lutimes(path, ×[0]), err); -#else - if (my_lutimes_func == NULL) { - JNU_ThrowInternalError(env, "my_lutimes_func is NULL"); - return; - } - RESTARTABLE((*my_lutimes_func)(path, ×[0]), err); -#endif + RESTARTABLE(futimens(filedes, ×[0]), err); if (err == -1) { throwUnixException(env, errno); } @@ -986,7 +888,6 @@ Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this, JNIEXPORT void JNICALL Java_sun_nio_fs_UnixNativeDispatcher_utimensat0(JNIEnv* env, jclass this, jint fd, jlong pathAddress, jlong accessTime, jlong modificationTime, jint flags) { -#if defined(__linux__) int err; struct timespec times[2]; const char* path = (const char*)jlong_to_ptr(pathAddress); @@ -997,18 +898,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_utimensat0(JNIEnv* env, jclass this, times[1].tv_sec = modificationTime / 1000000000; times[1].tv_nsec = modificationTime % 1000000000; - if (my_utimensat_func == NULL) { - JNU_ThrowInternalError(env, "my_utimensat_func is NULL"); - return; - } - RESTARTABLE((*my_utimensat_func)(fd, path, ×[0], flags), err); + RESTARTABLE(utimensat(fd, path, ×[0], flags), err); if (err == -1) { throwUnixException(env, errno); } -#else - JNU_ThrowInternalError(env, "should not reach here"); -#endif } JNIEXPORT jlong JNICALL diff --git a/src/java.base/windows/classes/java/io/WinNTFileSystem.java b/src/java.base/windows/classes/java/io/WinNTFileSystem.java index 10e02b4ba72..af6531edd01 100644 --- a/src/java.base/windows/classes/java/io/WinNTFileSystem.java +++ b/src/java.base/windows/classes/java/io/WinNTFileSystem.java @@ -30,7 +30,6 @@ import java.util.BitSet; import java.util.Locale; import java.util.Properties; -import sun.security.action.GetPropertyAction; /** * Unicode-aware FileSystem for Windows NT/2000. @@ -53,7 +52,7 @@ final class WinNTFileSystem extends FileSystem { // only if the property is set, ignoring case, to the string "false". private static final boolean ENABLE_ADS; static { - String enableADS = GetPropertyAction.privilegedGetProperty("jdk.io.File.enableADS"); + String enableADS = System.getProperty("jdk.io.File.enableADS"); if (enableADS != null) { ENABLE_ADS = !enableADS.equalsIgnoreCase(Boolean.FALSE.toString()); } else { @@ -81,7 +80,7 @@ private static String stripLongOrUNCPrefix(String path) { } WinNTFileSystem() { - Properties props = GetPropertyAction.privilegedGetProperties(); + Properties props = System.getProperties(); slash = props.getProperty("file.separator").charAt(0); semicolon = props.getProperty("path.separator").charAt(0); altSlash = (this.slash == '\\') ? '/' : '\\'; @@ -394,15 +393,15 @@ public String resolve(File f) { if (pl == 3) return path; /* Absolute local */ if (pl == 0) - return getUserPath() + slashify(path); /* Completely relative */ + return userDir + slashify(path); /* Completely relative */ if (pl == 1) { /* Drive-relative */ - String up = getUserPath(); + String up = userDir; String ud = getDrive(up); if (ud != null) return ud + path; return up + path; /* User dir is a UNC path */ } if (pl == 2) { /* Directory-relative */ - String up = getUserPath(); + String up = userDir; String ud = getDrive(up); if ((ud != null) && path.startsWith(ud)) return up + slashify(path.substring(2)); @@ -413,14 +412,6 @@ public String resolve(File f) { drive other than the current drive, insist that the caller have read permission on the result */ String p = drive + (':' + dir + slashify(path.substring(2))); - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - try { - if (security != null) security.checkRead(p); - } catch (SecurityException x) { - /* Don't disclose the drive's directory in the exception */ - throw new SecurityException("Cannot resolve path " + path); - } return p; } return drive + ":" + slashify(path.substring(2)); /* fake it */ @@ -428,17 +419,6 @@ public String resolve(File f) { throw new InternalError("Unresolvable path: " + path); } - private String getUserPath() { - /* For both compatibility and security, - we must look this up every time */ - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPropertyAccess("user.dir"); - } - return userDir; - } - private String getDrive(String path) { int pl = prefixLength(path); return (pl == 3) ? path.substring(0, 2) : null; @@ -595,22 +575,10 @@ public File[] listRoots() { .valueOf(new long[] {listRoots0()}) .stream() .mapToObj(i -> new File((char)('A' + i) + ":" + slash)) - .filter(f -> access(f.getPath())) .toArray(File[]::new); } private static native int listRoots0(); - private boolean access(String path) { - try { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) security.checkRead(path); - return true; - } catch (SecurityException x) { - return false; - } - } - /* -- Disk usage -- */ @Override diff --git a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index d3b60daad74..a7056082e12 100644 --- a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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,14 +31,11 @@ import java.net.UnknownHostException; import java.net.URL; import java.util.Locale; -import java.util.Objects; -import java.util.Properties; import sun.net.NetProperties; import sun.net.www.HeaderParser; import sun.net.www.protocol.http.AuthenticationInfo; import sun.net.www.protocol.http.AuthScheme; import sun.net.www.protocol.http.HttpURLConnection; -import sun.security.action.GetPropertyAction; /** * NTLMAuthentication: @@ -46,14 +43,11 @@ * @author Michael McMahon */ -public class NTLMAuthentication extends AuthenticationInfo { - - private static final long serialVersionUID = 100L; +public final class NTLMAuthentication extends AuthenticationInfo { private static final NTLMAuthenticationCallback NTLMAuthCallback = - NTLMAuthenticationCallback.getNTLMAuthenticationCallback(); + NTLMAuthenticationCallback.getNTLMAuthenticationCallback(); - private String hostname; /* Domain to use if not specified by user */ private static final String defaultDomain; /* Whether cache is enabled for NTLM */ @@ -68,18 +62,10 @@ enum TransparentAuth { private static final TransparentAuth authMode; static { - Properties props = GetPropertyAction.privilegedGetProperties(); - defaultDomain = props.getProperty("http.auth.ntlm.domain", "domain"); - String ntlmCacheProp = props.getProperty("jdk.ntlm.cache", "true"); + defaultDomain = System.getProperty("http.auth.ntlm.domain", "domain"); + String ntlmCacheProp = System.getProperty("jdk.ntlm.cache", "true"); ntlmCache = Boolean.parseBoolean(ntlmCacheProp); - @SuppressWarnings("removal") - String modeProp = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public String run() { - return NetProperties.get("jdk.http.ntlm.transparentAuth"); - } - }); - + String modeProp = NetProperties.get("jdk.http.ntlm.transparentAuth"); if ("trustedHosts".equalsIgnoreCase(modeProp)) authMode = TransparentAuth.TRUSTED_HOSTS; else if ("allHosts".equalsIgnoreCase(modeProp)) @@ -88,27 +74,6 @@ else if ("allHosts".equalsIgnoreCase(modeProp)) authMode = TransparentAuth.DISABLED; } - @SuppressWarnings("removal") - private void init0() { - - hostname = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public String run() { - String localhost; - try { - localhost = InetAddress.getLocalHost().getHostName().toUpperCase(Locale.ROOT); - } catch (UnknownHostException e) { - localhost = "localhost"; - } - return localhost; - } - }); - int x = hostname.indexOf ('.'); - if (x != -1) { - hostname = hostname.substring (0, x); - } - } - String username; String ntdomain; String password; @@ -147,7 +112,6 @@ private void init (PasswordAuthentication pw) { ntdomain = null; password = null; } - init0(); } /** diff --git a/src/java.base/windows/classes/sun/nio/ch/DefaultSelectorProvider.java b/src/java.base/windows/classes/sun/nio/ch/DefaultSelectorProvider.java index 0133d82986f..1da43697eaf 100644 --- a/src/java.base/windows/classes/sun/nio/ch/DefaultSelectorProvider.java +++ b/src/java.base/windows/classes/sun/nio/ch/DefaultSelectorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,12 @@ package sun.nio.ch; -import java.security.AccessController; -import java.security.PrivilegedAction; - /** * Creates this platform's default SelectorProvider */ -@SuppressWarnings("removal") public class DefaultSelectorProvider { - private static final SelectorProviderImpl INSTANCE; - static { - PrivilegedAction pa = WEPollSelectorProvider::new; - INSTANCE = AccessController.doPrivileged(pa); - } + private static final SelectorProviderImpl INSTANCE = new WEPollSelectorProvider(); /** * Prevent instantiation. diff --git a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java index 67a344a663d..7e138a5cc11 100644 --- a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -39,9 +39,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.channels.spi.*; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.security.PrivilegedActionException; import java.security.SecureRandom; import java.util.Random; @@ -64,10 +61,7 @@ class PipeImpl private final SourceChannelImpl source; private final SinkChannelImpl sink; - private static class Initializer - implements PrivilegedExceptionAction - { - + private static class Initializer { private final SelectorProvider sp; private final boolean preferUnixDomain; private IOException ioe; @@ -79,8 +73,7 @@ private Initializer(SelectorProvider sp, boolean preferUnixDomain) { this.preferUnixDomain = preferUnixDomain; } - @Override - public Void run() throws IOException { + public void init() throws IOException { LoopbackConnector connector = new LoopbackConnector(); connector.run(); if (ioe instanceof ClosedByInterruptException) { @@ -101,8 +94,6 @@ public void interrupt() {} if (ioe != null) throw new IOException("Unable to establish loopback connection", ioe); - - return null; } private class LoopbackConnector implements Runnable { @@ -190,17 +181,12 @@ public void run() { * * @param buffering if false set TCP_NODELAY on TCP sockets */ - @SuppressWarnings("removal") PipeImpl(SelectorProvider sp, boolean preferAfUnix, boolean buffering) throws IOException { Initializer initializer = new Initializer(sp, preferAfUnix); - try { - AccessController.doPrivileged(initializer); - SinkChannelImpl sink = initializer.sink; - if (sink.isNetSocket() && !buffering) { - sink.setOption(StandardSocketOptions.TCP_NODELAY, true); - } - } catch (PrivilegedActionException pae) { - throw (IOException) pae.getCause(); + initializer.init(); + SinkChannelImpl sink = initializer.sink; + if (sink.isNetSocket() && !buffering) { + sink.setOption(StandardSocketOptions.TCP_NODELAY, true); } this.source = initializer.source; this.sink = initializer.sink; diff --git a/src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java b/src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java index fd51e4540fd..43d790e5411 100644 --- a/src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java +++ b/src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -27,8 +27,6 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.net.NetProperties; import jdk.internal.util.StaticProperty; @@ -50,20 +48,16 @@ static Charset getCharset() { * 3. %TEMP% * 4. ${java.io.tmpdir} */ - @SuppressWarnings("removal") static String getTempDir() { - PrivilegedAction action = () -> { - String s = NetProperties.get("jdk.net.unixdomain.tmpdir"); - if (s != null) { - return s; - } - String temp = System.getenv("TEMP"); - if (temp != null) { - return temp; - } - return StaticProperty.javaIoTmpDir(); - }; - return AccessController.doPrivileged(action); + String s = NetProperties.get("jdk.net.unixdomain.tmpdir"); + if (s != null) { + return s; + } + String temp = System.getenv("TEMP"); + if (temp != null) { + return temp; + } + return StaticProperty.javaIoTmpDir(); } } diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java index 53c2219368c..9f84a5089fa 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,9 +30,6 @@ import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import java.io.IOException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import jdk.internal.misc.Unsafe; /** @@ -115,16 +112,12 @@ public AsynchronousChannelGroupImpl group() { */ private class AcceptTask implements Runnable, Iocp.ResultHandler { private final WindowsAsynchronousSocketChannelImpl channel; - @SuppressWarnings("removal") - private final AccessControlContext acc; private final PendingFuture result; AcceptTask(WindowsAsynchronousSocketChannelImpl channel, - @SuppressWarnings("removal") AccessControlContext acc, PendingFuture result) { this.channel = channel; - this.acc = acc; this.result = result; } @@ -139,7 +132,6 @@ void closeChildChannel() { } // caller must have acquired read lock for the listener and child channel. - @SuppressWarnings("removal") void finishAccept() throws IOException { /** * Set local/remote addresses. This is currently very inefficient @@ -151,18 +143,6 @@ void finishAccept() throws IOException { InetSocketAddress local = Net.localAddress(channel.fd); final InetSocketAddress remote = Net.remoteAddress(channel.fd); channel.setConnected(local, remote); - - // permission check (in context of initiating thread) - if (acc != null) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - SecurityManager sm = System.getSecurityManager(); - sm.checkAccept(remote.getAddress().getHostAddress(), - remote.getPort()); - return null; - } - }, acc); - } } /** @@ -207,7 +187,7 @@ public void run() { closeChildChannel(); if (x instanceof ClosedChannelException) x = new AsynchronousCloseException(); - if (!(x instanceof IOException) && !(x instanceof SecurityException)) + if (!(x instanceof IOException)) x = new IOException(x); enableAccept(); result.setFailure(x); @@ -259,7 +239,7 @@ public void completed(int bytesTransferred, boolean canInvokeDirect) { closeChildChannel(); if (x instanceof ClosedChannelException) x = new AsynchronousCloseException(); - if (!(x instanceof IOException) && !(x instanceof SecurityException)) + if (!(x instanceof IOException)) x = new IOException(x); result.setFailure(x); } @@ -328,16 +308,9 @@ Future implAccept(Object attachment, return null; } - // need calling context when there is security manager as - // permission check may be done in a different thread without - // any application call frames on the stack - @SuppressWarnings("removal") - AccessControlContext acc = (System.getSecurityManager() == null) ? - null : AccessController.getContext(); - PendingFuture result = new PendingFuture(this, handler, attachment); - AcceptTask task = new AcceptTask(ch, acc, result); + AcceptTask task = new AcceptTask(ch, result); result.setContext(task); // check and set flag to prevent concurrent accepting diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java index 20fdfc46ae3..9f3916bad8c 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,9 +31,6 @@ import java.net.*; import java.util.concurrent.*; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import jdk.internal.misc.Unsafe; import sun.net.util.SocketExceptions; @@ -308,20 +305,6 @@ public void failed(int error, IOException x) { } } - @SuppressWarnings("removal") - private void doPrivilegedBind(final SocketAddress sa) throws IOException { - try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Void run() throws IOException { - bind(sa); - return null; - } - }); - } catch (PrivilegedActionException e) { - throw (IOException) e.getException(); - } - } - @Override Future implConnect(SocketAddress remote, A attachment, @@ -337,12 +320,6 @@ Future implConnect(SocketAddress remote, InetSocketAddress isa = Net.checkAddress(remote); - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); - // check and update state // ConnectEx requires the socket to be bound to a local address IOException bindException = null; @@ -354,11 +331,7 @@ Future implConnect(SocketAddress remote, if (localAddress == null) { try { SocketAddress any = new InetSocketAddress(0); - if (sm == null) { - bind(any); - } else { - doPrivilegedBind(any); - } + bind(any); } catch (IOException x) { bindException = x; } diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java b/src/java.base/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java index d22c7aaba86..99898549dc8 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,22 +61,6 @@ class WindowsAclFileAttributeView this.followLinks = followLinks; } - // permission check - private void checkAccess(WindowsPath file, - boolean checkRead, - boolean checkWrite) - { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (checkRead) - sm.checkRead(file.getPathForPermissionCheck()); - if (checkWrite) - sm.checkWrite(file.getPathForPermissionCheck()); - sm.checkPermission(new RuntimePermission("accessUserInformation")); - } - } - // invokes GetFileSecurity to get requested security information static NativeBuffer getFileSecurity(String path, int request) throws IOException @@ -114,8 +98,6 @@ static NativeBuffer getFileSecurity(String path, int request) public UserPrincipal getOwner() throws IOException { - checkAccess(file, true, false); - // GetFileSecurity does not follow links so when following links we // need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); @@ -135,8 +117,6 @@ public UserPrincipal getOwner() public List getAcl() throws IOException { - checkAccess(file, true, false); - // GetFileSecurity does not follow links so when following links we // need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); @@ -158,9 +138,6 @@ public void setOwner(UserPrincipal obj) throw new ProviderMismatchException(); WindowsUserPrincipals.User owner = (WindowsUserPrincipals.User)obj; - // permission check - checkAccess(file, false, true); - // SetFileSecurity does not follow links so when following links we // need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); @@ -199,8 +176,6 @@ public void setOwner(UserPrincipal obj) @Override public void setAcl(List acl) throws IOException { - checkAccess(file, false, true); - // SetFileSecurity does not follow links so when following links we // need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java b/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java index 59db82d3fab..75d68f938c1 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java @@ -139,11 +139,8 @@ static Flags toFlags(Set options) { * * @param pathForWindows * The path of the file to open/create - * @param pathToCheck - * The path used for permission checks (if security manager) */ static FileChannel newFileChannel(String pathForWindows, - String pathToCheck, Set options, long pSecurityDescriptor) throws WindowsException @@ -165,7 +162,7 @@ static FileChannel newFileChannel(String pathForWindows, if (flags.append && flags.truncateExisting) throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); - FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); + FileDescriptor fdObj = open(pathForWindows, flags, pSecurityDescriptor); return FileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, (flags.sync || flags.dsync), flags.direct, null); } @@ -175,13 +172,10 @@ static FileChannel newFileChannel(String pathForWindows, * * @param pathForWindows * The path of the file to open/create - * @param pathToCheck - * The path used for permission checks (if security manager) * @param pool * The thread pool that the channel is associated with */ static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows, - String pathToCheck, Set options, long pSecurityDescriptor, ThreadPool pool) @@ -204,7 +198,7 @@ static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows, // open file for overlapped I/O FileDescriptor fdObj; try { - fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); + fdObj = open(pathForWindows, flags, pSecurityDescriptor); } catch (WindowsException x) { x.rethrowAsIOException(pathForWindows); return null; @@ -226,7 +220,6 @@ static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows, * encapsulating the handle to the open file. */ private static FileDescriptor open(String pathForWindows, - String pathToCheck, Flags flags, long pSecurityDescriptor) throws WindowsException @@ -291,20 +284,6 @@ private static FileDescriptor open(String pathForWindows, dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT; } - // permission check - if (pathToCheck != null) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (flags.read) - sm.checkRead(pathToCheck); - if (flags.write) - sm.checkWrite(pathToCheck); - if (flags.deleteOnClose) - sm.checkDelete(pathToCheck); - } - } - // open file long handle = CreateFile(pathForWindows, dwDesiredAccess, diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java index 2db3c912d39..9a6c0cf3764 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -46,7 +46,6 @@ private static class Basic extends AbstractBasicFileAttributeView { @Override public WindowsFileAttributes readAttributes() throws IOException { - file.checkRead(); try { return WindowsFileAttributes.get(file, followLinks); } catch (WindowsException x) { @@ -110,7 +109,7 @@ void setFileTimes(long createTime, // retry succeeded x = null; } - } catch (SecurityException | WindowsException | IOException ignore) { + } catch (WindowsException | IOException ignore) { // ignore exceptions to let original exception be thrown } } @@ -134,9 +133,6 @@ public void setTimes(FileTime lastModifiedTime, return; } - // permission check - file.checkWrite(); - // update times long t1 = (createTime == null) ? -1L : WindowsFileAttributes.toWindowsTime(createTime); @@ -219,8 +215,6 @@ public Map readAttributes(String[] attributes) private void updateAttributes(int flag, boolean enable) throws IOException { - file.checkWrite(); - // GetFileAttributes & SetFileAttributes do not follow links so when // following links we need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java index 8ad69662822..16bb2898a8d 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java @@ -84,15 +84,6 @@ static void copy(final WindowsPath source, throw new UnsupportedOperationException("Unsupported copy option: " + option); } - // check permissions. If the source file is a symbolic link then - // later we must also check LinkPermission - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - source.checkRead(); - target.checkWrite(); - } - // get attributes of source file // attempt to get attributes of target file // if both files are the same there is nothing to do @@ -144,11 +135,6 @@ static void copy(final WindowsPath source, CloseHandle(sourceHandle); } - // if source file is a symbolic link then we must check for LinkPermission - if (sm != null && sourceAttrs.isSymbolicLink()) { - sm.checkPermission(new LinkPermission("symbolic")); - } - // if source is a Unix domain socket, we don't want to copy it for various // reasons including consistency with Unix if (sourceAttrs.isUnixDomainSocket()) { @@ -308,13 +294,6 @@ static void move(WindowsPath source, WindowsPath target, CopyOption... options) throw new UnsupportedOperationException("Unsupported option: " + option); } - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - source.checkWrite(); - target.checkWrite(); - } - final String sourcePath = asWin32Path(source); final String targetPath = asWin32Path(target); diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java index f2cded1b372..2788c0cf304 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -101,23 +101,14 @@ public Iterable getRootDirectories() { throw new AssertionError(x.getMessage()); } - // iterate over roots, ignoring those that the security manager denies + // iterate over roots ArrayList result = new ArrayList<>(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); for (int i = 0; i <= 25; i++) { // 0->A, 1->B, 2->C... if ((drives & (1 << i)) != 0) { StringBuilder sb = new StringBuilder(3); sb.append((char)('A' + i)); sb.append(":\\"); String root = sb.toString(); - if (sm != null) { - try { - sm.checkRead(root); - } catch (SecurityException x) { - continue; - } - } result.add(WindowsPath.createFromNormalizedPath(this, root)); } } @@ -141,12 +132,6 @@ private FileStore readNext() { if (!roots.hasNext()) return null; WindowsPath root = (WindowsPath)roots.next(); - // ignore if security manager denies access - try { - root.checkRead(); - } catch (SecurityException x) { - continue; - } try { FileStore fs = WindowsFileStore.create(root.toString(), true); if (fs != null) @@ -186,20 +171,7 @@ public void remove() { @Override public Iterable getFileStores() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); - } catch (SecurityException se) { - return Collections.emptyList(); - } - } - return new Iterable() { - public Iterator iterator() { - return new FileStoreIterator(); - } - }; + return FileStoreIterator::new; } // supported views diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java index d76ad8b6f8e..7c280d87f62 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -112,7 +112,6 @@ public FileChannel newFileChannel(Path path, try { return WindowsChannelFactory .newFileChannel(file.getPathForWin32Calls(), - file.getPathForPermissionCheck(), options, sd.address()); } catch (WindowsException x) { @@ -142,7 +141,6 @@ public AsynchronousFileChannel newAsynchronousFileChannel(Path path, try { return WindowsChannelFactory .newAsynchronousFileChannel(file.getPathForWin32Calls(), - file.getPathForPermissionCheck(), options, sd.address(), pool); @@ -227,7 +225,6 @@ public SeekableByteChannel newByteChannel(Path obj, try { return WindowsChannelFactory .newFileChannel(file.getPathForWin32Calls(), - file.getPathForPermissionCheck(), options, sd.address()); } catch (WindowsException x) { @@ -241,7 +238,6 @@ public SeekableByteChannel newByteChannel(Path obj, @Override boolean implDelete(Path obj, boolean failIfNotExists) throws IOException { WindowsPath file = WindowsPath.toWindowsPath(obj); - file.checkDelete(); WindowsFileAttributes attrs = null; try { @@ -324,7 +320,6 @@ private void checkReadAccess(WindowsPath file) throws IOException { Set opts = Collections.emptySet(); FileChannel fc = WindowsChannelFactory .newFileChannel(file.getPathForWin32Calls(), - file.getPathForPermissionCheck(), opts, 0L); fc.close(); @@ -371,7 +366,6 @@ public void checkAccess(Path obj, AccessMode... modes) throws IOException { // check file exists only if (!(r || w || x)) { - file.checkRead(); try { WindowsFileAttributes.get(file, true); return; @@ -389,18 +383,12 @@ public void checkAccess(Path obj, AccessMode... modes) throws IOException { int mask = 0; if (r) { - file.checkRead(); mask |= FILE_READ_DATA; } if (w) { - file.checkWrite(); mask |= FILE_WRITE_DATA; } if (x) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkExec(file.getPathForPermissionCheck()); mask |= FILE_EXECUTE; } @@ -440,10 +428,6 @@ public boolean isSameFile(Path obj1, Path obj2) throws IOException { return false; WindowsPath file2 = (WindowsPath)obj2; - // check security manager access to both files - file1.checkRead(); - file2.checkRead(); - // open both files and see if they are the same long h1 = 0L; try { @@ -483,7 +467,6 @@ public boolean isSameFile(Path obj1, Path obj2) throws IOException { @Override public boolean isHidden(Path obj) throws IOException { WindowsPath file = WindowsPath.toWindowsPath(obj); - file.checkRead(); WindowsFileAttributes attrs = null; try { attrs = WindowsFileAttributes.get(file, true); @@ -496,12 +479,6 @@ public boolean isHidden(Path obj) throws IOException { @Override public FileStore getFileStore(Path obj) throws IOException { WindowsPath file = WindowsPath.toWindowsPath(obj); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); - file.checkRead(); - } return WindowsFileStore.create(file); } @@ -511,7 +488,6 @@ public void createDirectory(Path obj, FileAttribute... attrs) throws IOException { WindowsPath dir = WindowsPath.toWindowsPath(obj); - dir.checkWrite(); WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs); try { CreateDirectory(dir.getPathForWin32Calls(), sd.address()); @@ -535,7 +511,6 @@ public DirectoryStream newDirectoryStream(Path obj, DirectoryStream.Filter throws IOException { WindowsPath dir = WindowsPath.toWindowsPath(obj); - dir.checkRead(); if (filter == null) throw new NullPointerException(); return new WindowsDirectoryStream(dir, filter); @@ -555,14 +530,6 @@ public void createSymbolicLink(Path obj1, Path obj2, FileAttribute... attrs) "not supported when creating symbolic link"); } - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new LinkPermission("symbolic")); - link.checkWrite(); - } - /** * Throw I/O exception for the drive-relative case because Windows * creates a link with the resolved target for this case. @@ -611,15 +578,6 @@ public void createLink(Path obj1, Path obj2) throws IOException { WindowsPath link = WindowsPath.toWindowsPath(obj1); WindowsPath existing = WindowsPath.toWindowsPath(obj2); - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new LinkPermission("hard")); - link.checkWrite(); - existing.checkWrite(); - } - // create hard link try { CreateHardLink(link.getPathForWin32Calls(), @@ -634,15 +592,6 @@ public Path readSymbolicLink(Path obj1) throws IOException { WindowsPath link = WindowsPath.toWindowsPath(obj1); WindowsFileSystem fs = link.getFileSystem(); - // permission check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - FilePermission perm = new FilePermission(link.getPathForPermissionCheck(), - SecurityConstants.FILE_READLINK_ACTION); - sm.checkPermission(perm); - } - String target = WindowsLinkSupport.readLink(link); return WindowsPath.createFromNormalizedPath(fs, target); } diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java b/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java index 4ccd1d702bd..6ada2337cbb 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java @@ -28,8 +28,6 @@ import java.nio.file.*; import java.io.IOException; import java.io.IOError; -import java.security.AccessController; -import java.security.PrivilegedAction; import jdk.internal.misc.Unsafe; import static sun.nio.fs.WindowsNativeDispatcher.*; @@ -120,7 +118,6 @@ static String getFinalPath(WindowsPath input) throws IOException { * Returns the final path of a given path as a String. This should be used * prior to calling Win32 system calls that do not follow links. */ - @SuppressWarnings("removal") static String getFinalPath(WindowsPath input, boolean followLinks) throws IOException { @@ -164,12 +161,7 @@ static String getFinalPath(WindowsPath input, boolean followLinks) if (parent == null) { // no parent so use parent of absolute path final WindowsPath t = target; - target = AccessController - .doPrivileged(new PrivilegedAction() { - @Override - public WindowsPath run() { - return t.toAbsolutePath(); - }}); + target = t.toAbsolutePath(); parent = target.getParent(); } target = parent.resolve(link); diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java b/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java index c3dc204bb9d..a085adefd68 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -166,11 +166,6 @@ String getPathForExceptionMessage() { return path; } - // use this path for permission checks - String getPathForPermissionCheck() { - return path; - } - // use this path for Win32 calls // This method will prefix long paths with \\?\ or \\?\UNC as required. String getPathForWin32Calls() throws WindowsException { @@ -890,30 +885,6 @@ private long openSocketForReadAttributeAccess() } } - void checkRead() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkRead(getPathForPermissionCheck()); - } - } - - void checkWrite() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkWrite(getPathForPermissionCheck()); - } - } - - void checkDelete() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkDelete(getPathForPermissionCheck()); - } - } - @Override public URI toUri() { return WindowsUriSupport.toUri(this); @@ -924,13 +895,6 @@ public WindowsPath toAbsolutePath() { if (isAbsolute()) return this; - // permission check as per spec - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPropertyAccess("user.dir"); - } - try { return createFromNormalizedPath(getFileSystem(), getAbsolutePath()); } catch (WindowsException x) { @@ -940,7 +904,6 @@ public WindowsPath toAbsolutePath() { @Override public WindowsPath toRealPath(LinkOption... options) throws IOException { - checkRead(); String rp = WindowsLinkSupport.getRealPath(this, Util.followLinks(options)); return createFromNormalizedPath(getFileSystem(), rp); } @@ -956,31 +919,6 @@ public WatchKey register(WatchService watcher, if (!(watcher instanceof WindowsWatchService)) throw new ProviderMismatchException(); - // When a security manager is set then we need to make a defensive - // copy of the modifiers and check for the Windows specific FILE_TREE - // modifier. When the modifier is present then check that permission - // has been granted recursively. - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - boolean watchSubtree = false; - final int ml = modifiers.length; - if (ml > 0) { - modifiers = Arrays.copyOf(modifiers, ml); - int i=0; - while (i < ml) { - if (ExtendedOptions.FILE_TREE.matches(modifiers[i++])) { - watchSubtree = true; - break; - } - } - } - String s = getPathForPermissionCheck(); - sm.checkRead(s); - if (watchSubtree) - sm.checkRead(s + "\\-"); - } - return ((WindowsWatchService)watcher).register(this, events, modifiers); } } diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsUriSupport.java b/src/java.base/windows/classes/sun/nio/fs/WindowsUriSupport.java index a4d4c2ff316..3d22d1122bd 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsUriSupport.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsUriSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -104,9 +104,8 @@ static URI toUri(WindowsPath path) { boolean addSlash = false; if (!s.endsWith("\\")) { try { - path.checkRead(); addSlash = WindowsFileAttributes.get(path, true).isDirectory(); - } catch (SecurityException | WindowsException x) { + } catch (WindowsException x) { } } diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java b/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java index a96596af3cd..b488602a0f2 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -100,19 +100,13 @@ private List listUsingStreamEnumeration() throws IOException { return Collections.unmodifiableList(list); } - @SuppressWarnings("removal") @Override public List list() throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), true, false); return listUsingStreamEnumeration(); } - @SuppressWarnings("removal") @Override public int size(String name) throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), true, false); // wrap with channel FileChannel fc = null; @@ -122,9 +116,9 @@ public int size(String name) throws IOException { if (!followLinks) opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); fc = WindowsChannelFactory - .newFileChannel(join(file, name), null, opts, 0L); + .newFileChannel(join(file, name), opts, 0L); } catch (WindowsException x) { - x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); + x.rethrowAsIOException(join(file.getPathForExceptionMessage(), name)); } try { long size = fc.size(); @@ -136,12 +130,8 @@ public int size(String name) throws IOException { } } - @SuppressWarnings("removal") @Override public int read(String name, ByteBuffer dst) throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), true, false); - // wrap with channel FileChannel fc = null; try { @@ -150,9 +140,9 @@ public int read(String name, ByteBuffer dst) throws IOException { if (!followLinks) opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); fc = WindowsChannelFactory - .newFileChannel(join(file, name), null, opts, 0L); + .newFileChannel(join(file, name), opts, 0L); } catch (WindowsException x) { - x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); + x.rethrowAsIOException(join(file.getPathForExceptionMessage(), name)); } // read to EOF (nothing we can do if I/O error occurs) @@ -172,12 +162,8 @@ public int read(String name, ByteBuffer dst) throws IOException { } } - @SuppressWarnings("removal") @Override public int write(String name, ByteBuffer src) throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), false, true); - /** * Creating a named stream will cause the unnamed stream to be created * if it doesn't already exist. To avoid this we open the unnamed stream @@ -210,9 +196,9 @@ public int write(String name, ByteBuffer src) throws IOException { FileChannel named = null; try { named = WindowsChannelFactory - .newFileChannel(join(file, name), null, opts, 0L); + .newFileChannel(join(file, name), opts, 0L); } catch (WindowsException x) { - x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); + x.rethrowAsIOException(join(file.getPathForExceptionMessage(), name)); } // write value (nothing we can do if I/O error occurs) try { @@ -229,12 +215,8 @@ public int write(String name, ByteBuffer src) throws IOException { } } - @SuppressWarnings("removal") @Override public void delete(String name) throws IOException { - if (System.getSecurityManager() != null) - checkAccess(file.getPathForPermissionCheck(), false, true); - String path = WindowsLinkSupport.getFinalPath(file, followLinks); String toDelete = join(path, name); try { diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsUserPrincipals.java b/src/java.base/windows/classes/sun/nio/fs/WindowsUserPrincipals.java index cdb66296a63..336bbe22cfb 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsUserPrincipals.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsUserPrincipals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -131,12 +131,6 @@ static UserPrincipal fromSid(long sidAddress) throws IOException { } static UserPrincipal lookup(String name) throws IOException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("lookupUserInformation")); - } - // invoke LookupAccountName to get buffer size needed for SID int size; try { diff --git a/src/java.compiler/share/classes/javax/tools/ToolProvider.java b/src/java.compiler/share/classes/javax/tools/ToolProvider.java index 8cdfd63b17d..03a56139fdd 100644 --- a/src/java.compiler/share/classes/javax/tools/ToolProvider.java +++ b/src/java.compiler/share/classes/javax/tools/ToolProvider.java @@ -25,8 +25,6 @@ package javax.tools; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Objects; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; @@ -118,29 +116,13 @@ private static T getSystemTool(Class clazz, String moduleName, String cla try { ServiceLoader sl = ServiceLoader.load(clazz, ClassLoader.getSystemClassLoader()); for (T tool : sl) { - if (matches(tool, moduleName)) + if (Objects.equals(tool.getClass().getModule().getName(), moduleName)) { return tool; + } } } catch (ServiceConfigurationError e) { throw new Error(e); } return null; } - - /** - * Determine if this is the desired tool instance. - * @param the interface of the tool - * @param tool the instance of the tool - * @param moduleName the name of the module containing the desired implementation - * @return true if and only if the tool matches the specified criteria - */ - @SuppressWarnings("removal") - private static boolean matches(T tool, String moduleName) { - PrivilegedAction pa = () -> { - Module toolModule = tool.getClass().getModule(); - String toolModuleName = toolModule.getName(); - return Objects.equals(toolModuleName, moduleName); - }; - return AccessController.doPrivileged(pa); - } } diff --git a/src/java.datatransfer/share/classes/java/awt/datatransfer/DataFlavor.java b/src/java.datatransfer/share/classes/java/awt/datatransfer/DataFlavor.java index 757c4f99f45..f228f1a4da1 100644 --- a/src/java.datatransfer/share/classes/java/awt/datatransfer/DataFlavor.java +++ b/src/java.datatransfer/share/classes/java/awt/datatransfer/DataFlavor.java @@ -45,7 +45,6 @@ import java.util.Objects; import sun.datatransfer.DataFlavorUtil; -import sun.reflect.misc.ReflectUtil; /** * A {@code DataFlavor} provides meta information about data. {@code DataFlavor} @@ -131,32 +130,22 @@ protected static final Class tryToLoadClass(String className, ClassLoader fallback) throws ClassNotFoundException { - ReflectUtil.checkPackageAccess(className); + ClassLoader loader = ClassLoader.getSystemClassLoader(); try { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getClassLoader")); - } - ClassLoader loader = ClassLoader.getSystemClassLoader(); - try { - // bootstrap class loader and system class loader if present - return Class.forName(className, true, loader); - } - catch (ClassNotFoundException exception) { - // thread context class loader if and only if present - loader = Thread.currentThread().getContextClassLoader(); - if (loader != null) { - try { - return Class.forName(className, true, loader); - } - catch (ClassNotFoundException e) { - // fallback to user's class loader - } + // bootstrap class loader and system class loader if present + return Class.forName(className, true, loader); + } + catch (ClassNotFoundException exception) { + // thread context class loader if and only if present + loader = Thread.currentThread().getContextClassLoader(); + if (loader != null) { + try { + return Class.forName(className, true, loader); + } + catch (ClassNotFoundException e) { + // fallback to user's class loader } } - } catch (SecurityException exception) { - // ignore secured class loaders } return Class.forName(className, true, fallback); } diff --git a/src/java.datatransfer/share/classes/java/awt/datatransfer/SystemFlavorMap.java b/src/java.datatransfer/share/classes/java/awt/datatransfer/SystemFlavorMap.java index 6b2dc14c05f..deea133b734 100644 --- a/src/java.datatransfer/share/classes/java/awt/datatransfer/SystemFlavorMap.java +++ b/src/java.datatransfer/share/classes/java/awt/datatransfer/SystemFlavorMap.java @@ -30,8 +30,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.lang.ref.SoftReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -202,12 +200,8 @@ private void initSystemFlavorMap() { } isMapInitialized = true; - @SuppressWarnings("removal") - InputStream is = AccessController.doPrivileged( - (PrivilegedAction) () -> { - return SystemFlavorMap.class.getResourceAsStream( + InputStream is = SystemFlavorMap.class.getResourceAsStream( "/sun/datatransfer/resources/flavormap.properties"); - }); if (is == null) { throw new InternalError("Default flavor mapping not found"); } diff --git a/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c index 908b7cca653..bbfb5ae42f9 100644 --- a/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c @@ -449,7 +449,7 @@ awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp) "(Ljava/lang/String;J)V", javastr, event->time); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } @@ -682,7 +682,7 @@ static void onoffStatusWindow(X11InputMethodData* pX11IMData, parent = JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, "getCurrentParentWindow", "()J").j; - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } @@ -1057,7 +1057,7 @@ PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data) "clearComposedText", "(J)V", awt_util_nowMillisUTC()); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } @@ -1160,7 +1160,7 @@ PreeditDrawCallback(XIC ic, XPointer client_data, (jint)pre_draw->caret, awt_util_nowMillisUTC()); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } @@ -2125,7 +2125,7 @@ JNIEXPORT jstring JNICALL Java_sun_awt_X11InputMethodBase_resetXIC JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, "clearComposedText", "()V"); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIUtils.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIUtils.java index bed22b8d4ee..d6c051c17ab 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIUtils.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIUtils.java @@ -25,12 +25,9 @@ package apple.laf; -import java.security.AccessController; - import apple.laf.JRSUIConstants.Hit; import apple.laf.JRSUIConstants.ScrollBarPart; import com.apple.laf.AquaImageFactory.NineSliceMetrics; -import sun.security.action.GetPropertyAction; public final class JRSUIUtils { @@ -69,8 +66,7 @@ static boolean currentMacOSXVersionMatchesGivenVersionRange( final int majorVersion, final int minorVersion, final boolean inclusive, final boolean matchBelow, final boolean matchAbove) { // split the "x.y.z" version number - @SuppressWarnings("removal") - String osVersion = AccessController.doPrivileged(new GetPropertyAction("os.version")); + String osVersion = System.getProperty("os.version"); String[] fragments = osVersion.split("\\."); if (fragments.length < 2) return false; diff --git a/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java b/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java index 1a77ddd7600..5449e3ff9e2 100644 --- a/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java +++ b/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java @@ -58,15 +58,9 @@ public class FileManager { loadOSXLibrary(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void loadOSXLibrary() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("osx"); - return null; - } - }); + System.loadLibrary("osx"); } /** diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java index b79cc98be9d..a9eab801b0d 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -63,7 +63,6 @@ class AquaComboBoxButton extends JButton { boolean isPopDown; boolean isSquare; - @SuppressWarnings("serial") // anonymous class protected AquaComboBoxButton(final AquaComboBoxUI ui, final JComboBox comboBox, final CellRendererPane rendererPane, diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java index 981a00d5588..dc29d0b5ae8 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -161,7 +161,6 @@ public void show() { } @Override - @SuppressWarnings("serial") // anonymous class protected JList createList() { return new JList(comboBox.getModel()) { @Override diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java index b9b60994085..130c30aa9e1 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -230,7 +230,6 @@ private void editorTextChanged() { @SuppressWarnings("serial") // Superclass is not serializable across versions class AquaCustomComboTextField extends JTextField { - @SuppressWarnings("serial") // anonymous class public AquaCustomComboTextField() { final InputMap inputMap = getInputMap(); inputMap.put(KeyStroke.getKeyStroke("DOWN"), highlightNextAction); @@ -350,7 +349,6 @@ public void actionPerformed(final ActionEvent e) { /** * Highlight _but do not select_ the next item in the list. */ - @SuppressWarnings("serial") // anonymous class private Action highlightNextAction = new ComboBoxAction() { @Override public void performComboBoxAction(AquaComboBoxUI ui) { @@ -367,7 +365,6 @@ public void performComboBoxAction(AquaComboBoxUI ui) { /** * Highlight _but do not select_ the previous item in the list. */ - @SuppressWarnings("serial") // anonymous class private Action highlightPreviousAction = new ComboBoxAction() { @Override void performComboBoxAction(final AquaComboBoxUI ui) { @@ -380,7 +377,6 @@ void performComboBoxAction(final AquaComboBoxUI ui) { } }; - @SuppressWarnings("serial") // anonymous class private Action highlightFirstAction = new ComboBoxAction() { @Override void performComboBoxAction(final AquaComboBoxUI ui) { @@ -389,7 +385,6 @@ void performComboBoxAction(final AquaComboBoxUI ui) { } }; - @SuppressWarnings("serial") // anonymous class private Action highlightLastAction = new ComboBoxAction() { @Override void performComboBoxAction(final AquaComboBoxUI ui) { @@ -399,7 +394,6 @@ void performComboBoxAction(final AquaComboBoxUI ui) { } }; - @SuppressWarnings("serial") // anonymous class private Action highlightPageUpAction = new ComboBoxAction() { @Override void performComboBoxAction(final AquaComboBoxUI ui) { @@ -420,7 +414,6 @@ void performComboBoxAction(final AquaComboBoxUI ui) { } }; - @SuppressWarnings("serial") // anonymous class private Action highlightPageDownAction = new ComboBoxAction() { @Override void performComboBoxAction(final AquaComboBoxUI ui) { @@ -560,7 +553,6 @@ protected static void triggerSelectionEvent(final JComboBox comboBox, final A // This is somewhat messy. The difference here from BasicComboBoxUI.EnterAction is that // arrow up or down does not automatically select the - @SuppressWarnings("serial") // anonymous class private final Action triggerSelectionAction = new AbstractAction() { public void actionPerformed(final ActionEvent e) { triggerSelectionEvent((JComboBox)e.getSource(), e); @@ -572,7 +564,6 @@ public boolean isEnabled() { } }; - @SuppressWarnings("serial") // anonymous class private static final Action toggleSelectionAction = new AbstractAction() { public void actionPerformed(final ActionEvent e) { final JComboBox comboBox = (JComboBox) e.getSource(); @@ -591,7 +582,6 @@ public void actionPerformed(final ActionEvent e) { } }; - @SuppressWarnings("serial") // anonymous class private final Action hideAction = new AbstractAction() { @Override public void actionPerformed(final ActionEvent e) { @@ -606,7 +596,6 @@ public boolean isEnabled() { } }; - @SuppressWarnings("serial") // anonymous class private final Action openPopupOrHighlightLast = new ComboBoxAction() { @Override void performComboBoxAction(final AquaComboBoxUI ui) { @@ -617,7 +606,6 @@ void performComboBoxAction(final AquaComboBoxUI ui) { } }; - @SuppressWarnings("serial") // anonymous class private final Action openPopupOrHighlightFirst = new ComboBoxAction() { @Override void performComboBoxAction(final AquaComboBoxUI ui) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java index e4b112cc297..bdb440bf4d2 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -1240,7 +1240,6 @@ public Dimension getMaximumSize(final JComponent c) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } - @SuppressWarnings("serial") // anonymous class protected ListCellRenderer createDirectoryComboBoxRenderer(final JFileChooser fc) { return new AquaComboBoxRendererInternal(directoryComboBox) { public Component getListCellRendererComponent(final JList list, @@ -1356,7 +1355,6 @@ public File getElementAt(final int index) { // // Renderer for Types ComboBox // - @SuppressWarnings("serial") // anonymous class protected ListCellRenderer createFilterComboBoxRenderer() { return new AquaComboBoxRendererInternal(filterComboBox) { public Component getListCellRendererComponent(final JList list, @@ -1611,7 +1609,6 @@ public void installComponents(final JFileChooser fc) { tPanel.add(labelArea); // separator line - @SuppressWarnings("serial") // anonymous class final JSeparator sep = new JSeparator(){ public Dimension getPreferredSize() { return new Dimension(((JComponent)getParent()).getWidth(), 3); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java index 34e5b7c9b7c..653cf49cb55 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -39,7 +39,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; -@SuppressWarnings("serial") // JDK implementation class class AquaFileView extends FileView { private static final boolean DEBUG = false; @@ -65,15 +64,9 @@ class AquaFileView extends FileView { loadOSXUILibrary(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void loadOSXUILibrary() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("osxui"); - return null; - } - }); + System.loadLibrary("osxui"); } // TODO: Un-comment this out when the native version exists diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java index 2fddf6483a5..9cf3b920f91 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaImageFactory.java @@ -27,11 +27,11 @@ import java.awt.*; import java.awt.image.BufferedImage; -import java.security.PrivilegedAction; import javax.swing.*; import javax.swing.plaf.*; +import com.apple.eawt.Application; import sun.lwawt.macosx.LWCToolkit; import apple.laf.JRSUIConstants.AlignmentHorizontal; import apple.laf.JRSUIConstants.AlignmentVertical; @@ -82,22 +82,12 @@ public static IconUIResource getLockImageIcon() { return getAppIconCompositedOn(lockIcon); } - @SuppressWarnings("removal") static Image getGenericJavaIcon() { - return java.security.AccessController.doPrivileged(new PrivilegedAction() { - public Image run() { - return com.apple.eawt.Application.getApplication().getDockIconImage(); - } - }); + return Application.getApplication().getDockIconImage(); } - @SuppressWarnings("removal") static String getPathToThisApplication() { - return java.security.AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return FileManager.getPathToApplicationBundle(); - } - }); + return FileManager.getPathToApplicationBundle(); } static IconUIResource getAppIconCompositedOn(final SystemIcon systemIcon) { diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java index 9748f900827..34a39525a74 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java @@ -154,22 +154,10 @@ public boolean isSupportedLookAndFeel() { * @see #uninitialize * @see UIManager#setLookAndFeel */ - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") public void initialize() { - java.security.AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - System.loadLibrary("osxui"); - return null; - } - }); - - java.security.AccessController.doPrivileged(new PrivilegedAction(){ - @Override - public Void run() { - JRSUIControl.initJRSUI(); - return null; - } - }); + System.loadLibrary("osxui"); + JRSUIControl.initJRSUI(); super.initialize(); final ScreenPopupFactory spf = new ScreenPopupFactory(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarUI.java index f252e310750..1c9ad2c929d 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaMenuBarUI.java @@ -29,7 +29,6 @@ import java.awt.Dimension; import java.awt.Graphics; import java.awt.MenuBar; -import java.security.AccessController; import javax.swing.JComponent; import javax.swing.JFrame; @@ -38,18 +37,13 @@ import javax.swing.plaf.basic.BasicMenuBarUI; import sun.lwawt.macosx.LWCToolkit; -import sun.security.action.GetBooleanAction; // MenuBar implementation for Mac L&F -@SuppressWarnings({"removal", "restricted"}) +@SuppressWarnings("restricted") public class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvider { static { - java.security.AccessController.doPrivileged( - (java.security.PrivilegedAction) () -> { - System.loadLibrary("osxui"); - return null; - }); + System.loadLibrary("osxui"); } // Utilities @@ -151,7 +145,6 @@ public static final boolean isScreenMenuBar(final JMenuBar c) { public static boolean getScreenMenuBarProperty() { // Do not allow AWT to set the screen menu bar if it's embedded in another UI toolkit if (LWCToolkit.isEmbedded()) return false; - return AccessController.doPrivileged(new GetBooleanAction( - AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar")); + return Boolean.getBoolean(AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java index a8abf1a6cd8..ee813fc7104 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaNativeResources.java @@ -32,16 +32,10 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; -@SuppressWarnings({"removal", "restricted"}) +@SuppressWarnings("restricted") public class AquaNativeResources { static { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("osxui"); - return null; - } - }); + System.loadLibrary("osxui"); } // TODO: removing CColorPaint for now diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java index e00722bc293..1a10e30a6c6 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -1020,7 +1020,6 @@ JMenuItem createMenuItem(final int i) { if (component == null) { menuItem = new JMenuItem(tabPane.getTitleAt(i), tabPane.getIconAt(i)); } else { - @SuppressWarnings("serial") // anonymous class JMenuItem tmp = new JMenuItem() { public void paintComponent(final Graphics g) { super.paintComponent(g); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldSearch.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldSearch.java index 99349b6c6b3..a6be82d9ac3 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldSearch.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTextFieldSearch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -249,7 +249,6 @@ static void updatePromptLabelOnEDT(final JLabel label, final JTextComponent text label.setText(promptText); } - @SuppressWarnings("serial") // anonymous class inside protected static JButton getCancelButton(final JTextComponent c) { final JButton b = createButton(c, getCancelIcon()); b.setName("cancel"); @@ -326,7 +325,6 @@ public Insets getBorderInsets(final Component c) { } protected boolean doingLayout; - @SuppressWarnings("serial") // anonymous class inside protected LayoutManager getCustomLayout() { // unfortunately, the default behavior of BorderLayout, which accommodates for margins // is not what we want, so we "turn off margins" for layout for layout out our buttons diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java index 0bd1ce9609d..51b02a7f5d4 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java @@ -27,7 +27,6 @@ import java.awt.*; import java.beans.*; -import java.security.AccessController; import javax.swing.*; import javax.swing.border.Border; @@ -38,7 +37,6 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; -import sun.security.action.GetPropertyAction; public class AquaUtilControlSize { protected static final String CLIENT_PROPERTY_KEY = "JComponent.sizeVariant"; @@ -72,9 +70,7 @@ private static JRSUIConstants.Size getSizeFromString(final String name) { } private static Size getDefaultSize() { - @SuppressWarnings("removal") - final String sizeProperty = AccessController.doPrivileged( - new GetPropertyAction(SYSTEM_PROPERTY_KEY)); + final String sizeProperty = System.getProperty(SYSTEM_PROPERTY_KEY); final JRSUIConstants.Size size = getSizeFromString(sizeProperty); if (size != null) return size; return JRSUIConstants.Size.REGULAR; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java index 712f597f9ef..d40d50b1b5c 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java @@ -29,8 +29,6 @@ import java.awt.image.*; import java.lang.ref.SoftReference; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.*; import javax.swing.*; @@ -41,7 +39,6 @@ import sun.lwawt.macosx.CPlatformWindow; import sun.reflect.misc.ReflectUtil; -import sun.security.action.GetPropertyAction; import sun.swing.SwingUtilities2; import com.apple.laf.AquaImageFactory.SlicedImageControl; @@ -205,9 +202,7 @@ V get(final K key) { private static final RecyclableSingleton enableAnimations = new RecyclableSingleton() { @Override protected Boolean getInstance() { - @SuppressWarnings("removal") - final String sizeProperty = (String) AccessController.doPrivileged((PrivilegedAction)new GetPropertyAction( - ANIMATIONS_PROPERTY)); + final String sizeProperty = System.getProperty(ANIMATIONS_PROPERTY); return !"false".equals(sizeProperty); // should be true by default } }; @@ -332,25 +327,17 @@ public void paintBorder(final Component c, final Graphics g, final int x, final } } - @SuppressWarnings("removal") private static final RecyclableSingleton getJComponentGetFlagMethod = new RecyclableSingleton() { @Override protected Method getInstance() { - return AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public Method run() { - try { - final Method method = JComponent.class.getDeclaredMethod( - "getFlag", new Class[] { int.class }); - method.setAccessible(true); - return method; - } catch (final Throwable ignored) { - return null; - } - } - } - ); + try { + final Method method = JComponent.class.getDeclaredMethod( + "getFlag", new Class[]{int.class}); + method.setAccessible(true); + return method; + } catch (final Throwable ignored) { + return null; + } } }; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java index d8d0928c55f..ef4e4c5707a 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java @@ -45,15 +45,9 @@ final class ScreenMenu extends Menu loadAWTLibrary(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void loadAWTLibrary() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); } // screen menu stuff diff --git a/src/java.desktop/macosx/classes/sun/awt/PlatformGraphicsInfo.java b/src/java.desktop/macosx/classes/sun/awt/PlatformGraphicsInfo.java index 6af002fc04f..571bc5c5479 100644 --- a/src/java.desktop/macosx/classes/sun/awt/PlatformGraphicsInfo.java +++ b/src/java.desktop/macosx/classes/sun/awt/PlatformGraphicsInfo.java @@ -27,17 +27,12 @@ import java.awt.GraphicsEnvironment; import java.awt.Toolkit; -import java.security.AccessController; -import java.security.PrivilegedAction; -@SuppressWarnings({"removal", "restricted"}) +@SuppressWarnings({"restricted"}) public class PlatformGraphicsInfo { static { - AccessController.doPrivileged((PrivilegedAction) () -> { System.loadLibrary("awt"); - return null; - }); } public static GraphicsEnvironment createGE() { diff --git a/src/java.desktop/macosx/classes/sun/font/CFontManager.java b/src/java.desktop/macosx/classes/sun/font/CFontManager.java index baab3257153..f9455a6d102 100644 --- a/src/java.desktop/macosx/classes/sun/font/CFontManager.java +++ b/src/java.desktop/macosx/classes/sun/font/CFontManager.java @@ -27,8 +27,6 @@ import java.awt.*; import java.io.File; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; @@ -147,10 +145,7 @@ protected void addNativeFontFamilyNames(TreeMap familyNames, Loc protected void registerFontsInDir(final String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) { - @SuppressWarnings("removal") - String[] files = AccessController.doPrivileged((PrivilegedAction) () -> { - return new File(dirName).list(getTrueTypeFilter()); - }); + String[] files = new File(dirName).list(getTrueTypeFilter()); if (files == null) { return; @@ -205,24 +200,17 @@ void registerItalicDerived() { Object waitForFontsToBeLoaded = new Object(); private boolean loadedAllFonts = false; - @SuppressWarnings("removal") + public void loadFonts() { synchronized(waitForFontsToBeLoaded) { super.loadFonts(); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - if (!loadedAllFonts) { - loadNativeFonts(); - registerItalicDerived(); - loadedAllFonts = true; - } - return null; - } - } - ); + if (!loadedAllFonts) { + loadNativeFonts(); + registerItalicDerived(); + loadedAllFonts = true; + } String defaultFont = "Lucida Grande"; String defaultFallback = "Lucida Grande"; diff --git a/src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java b/src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java index 37b573a339b..033b9ad8362 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java +++ b/src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java @@ -25,7 +25,6 @@ package sun.java2d; -import java.security.PrivilegedAction; import sun.java2d.metal.MTLGraphicsConfig; import sun.java2d.opengl.CGLGraphicsConfig; @@ -83,59 +82,53 @@ private static boolean isBooleanPropTrueVerbose(String p) { return false; } - @SuppressWarnings("removal") private static void initJavaFlags() { - java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> { - PropertyState oglState = getBooleanProp("sun.java2d.opengl", PropertyState.UNSPECIFIED); - PropertyState metalState = getBooleanProp("sun.java2d.metal", PropertyState.UNSPECIFIED); - - // Handle invalid combinations to use the default rendering pipeline - // The default rendering pipeline is Metal - if ((oglState == PropertyState.UNSPECIFIED && metalState == PropertyState.UNSPECIFIED) || - (oglState == PropertyState.DISABLED && metalState == PropertyState.DISABLED) || - (oglState == PropertyState.ENABLED && metalState == PropertyState.ENABLED)) { - metalState = PropertyState.ENABLED; // Enable default pipeline - oglState = PropertyState.DISABLED; // Disable non-default pipeline - } - - if (metalState == PropertyState.UNSPECIFIED) { - if (oglState == PropertyState.DISABLED) { - oglEnabled = false; - metalEnabled = true; - } else { - oglEnabled = true; - metalEnabled = false; - } - } else if (metalState == PropertyState.ENABLED) { - oglEnabled = false; - metalEnabled = true; - } else if (metalState == PropertyState.DISABLED) { - oglEnabled = true; - metalEnabled = false; - } - - oglVerbose = isBooleanPropTrueVerbose("sun.java2d.opengl"); - metalVerbose = isBooleanPropTrueVerbose("sun.java2d.metal"); - - if (oglEnabled && !metalEnabled) { - // Check whether OGL is available - if (!CGLGraphicsConfig.isCGLAvailable()) { - if (oglVerbose) { - System.out.println("Could not enable OpenGL pipeline (CGL not available)"); - } - oglEnabled = false; - metalEnabled = true; - } - } - - // At this point one of the rendering pipeline must be enabled. - if (!metalEnabled && !oglEnabled) { - throw new InternalError("Error - unable to initialize any rendering pipeline."); - } - - return null; - }); + PropertyState oglState = getBooleanProp("sun.java2d.opengl", PropertyState.UNSPECIFIED); + PropertyState metalState = getBooleanProp("sun.java2d.metal", PropertyState.UNSPECIFIED); + + // Handle invalid combinations to use the default rendering pipeline + // The default rendering pipeline is Metal + if ((oglState == PropertyState.UNSPECIFIED && metalState == PropertyState.UNSPECIFIED) || + (oglState == PropertyState.DISABLED && metalState == PropertyState.DISABLED) || + (oglState == PropertyState.ENABLED && metalState == PropertyState.ENABLED)) { + metalState = PropertyState.ENABLED; // Enable default pipeline + oglState = PropertyState.DISABLED; // Disable non-default pipeline + } + + if (metalState == PropertyState.UNSPECIFIED) { + if (oglState == PropertyState.DISABLED) { + oglEnabled = false; + metalEnabled = true; + } else { + oglEnabled = true; + metalEnabled = false; + } + } else if (metalState == PropertyState.ENABLED) { + oglEnabled = false; + metalEnabled = true; + } else if (metalState == PropertyState.DISABLED) { + oglEnabled = true; + metalEnabled = false; + } + + oglVerbose = isBooleanPropTrueVerbose("sun.java2d.opengl"); + metalVerbose = isBooleanPropTrueVerbose("sun.java2d.metal"); + + if (oglEnabled && !metalEnabled) { + // Check whether OGL is available + if (!CGLGraphicsConfig.isCGLAvailable()) { + if (oglVerbose) { + System.out.println("Could not enable OpenGL pipeline (CGL not available)"); + } + oglEnabled = false; + metalEnabled = true; + } + } + + // At this point one of the rendering pipeline must be enabled. + if (!metalEnabled && !oglEnabled) { + throw new InternalError("Error - unable to initialize any rendering pipeline."); + } } public static boolean isMetalEnabled() { diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java index 2b70c39146b..f3867ce88c1 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java @@ -58,8 +58,6 @@ import java.awt.image.VolatileImage; import java.awt.image.WritableRaster; import java.io.File; -import java.security.AccessController; -import java.security.PrivilegedAction; import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_GRAD_SHADER; import static sun.java2d.pipe.hw.AccelSurface.TEXTURE; @@ -73,11 +71,10 @@ public final class MTLGraphicsConfig extends CGraphicsConfig { private static ImageCapabilities imageCaps = new MTLImageCaps(); - @SuppressWarnings("removal") - private static final String mtlShadersLib = AccessController.doPrivileged( - (PrivilegedAction) () -> + + private static final String mtlShadersLib = System.getProperty("java.home", "") + File.separator + - "lib" + File.separator + "shaders.metallib"); + "lib" + File.separator + "shaders.metallib"; private BufferCapabilities bufferCaps; diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java index 57b412f5b13..7970aa919f1 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java @@ -29,9 +29,6 @@ import sun.java2d.pipe.RenderBuffer; import sun.java2d.pipe.RenderQueue; -import java.security.AccessController; -import java.security.PrivilegedAction; - import static sun.java2d.pipe.BufferedOpCodes.DISPOSE_CONFIG; import static sun.java2d.pipe.BufferedOpCodes.SYNC; @@ -46,13 +43,12 @@ public class MTLRenderQueue extends RenderQueue { private static MTLRenderQueue theInstance; private final QueueFlusher flusher; - @SuppressWarnings("removal") private MTLRenderQueue() { /* * The thread must be a member of a thread group * which will not get GCed before VM exit. */ - flusher = AccessController.doPrivileged((PrivilegedAction) QueueFlusher::new); + flusher = new QueueFlusher(); } /** diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java index f37e4ad7425..b487b14fd79 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -58,8 +58,6 @@ import java.awt.peer.ContainerPeer; import java.awt.peer.KeyboardFocusManagerPeer; import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.JComponent; @@ -260,37 +258,26 @@ public void addDirtyRegion(final JComponent c, final int x, final int y, final i * This method must be called under Toolkit.getDefaultToolkit() lock * and followed by setToolkitAWTEventListener() */ - @SuppressWarnings("removal") protected final AWTEventListener getToolkitAWTEventListener() { - return AccessController.doPrivileged(new PrivilegedAction() { - public AWTEventListener run() { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - try { - Field field = Toolkit.class.getDeclaredField("eventListener"); - field.setAccessible(true); - return (AWTEventListener) field.get(toolkit); - } catch (Exception e) { - throw new InternalError(e.toString()); - } - } - }); + Toolkit toolkit = Toolkit.getDefaultToolkit(); + try { + Field field = Toolkit.class.getDeclaredField("eventListener"); + field.setAccessible(true); + return (AWTEventListener) field.get(toolkit); + } catch (Exception e) { + throw new InternalError(e.toString()); + } } - @SuppressWarnings("removal") protected final void setToolkitAWTEventListener(final AWTEventListener listener) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - try { - Field field = Toolkit.class.getDeclaredField("eventListener"); - field.setAccessible(true); - field.set(toolkit, listener); - } catch (Exception e) { - throw new InternalError(e.toString()); - } - return null; - } - }); + Toolkit toolkit = Toolkit.getDefaultToolkit(); + try { + Field field = Toolkit.class.getDeclaredField("eventListener"); + field.setAccessible(true); + field.set(toolkit, listener); + } catch (Exception e) { + throw new InternalError(e.toString()); + } } /** diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWListPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWListPeer.java index a9081ae3c36..905a66b3212 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWListPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWListPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -254,7 +254,6 @@ public void setSkipStateChangedEvent(boolean skipStateChangedEvent) { } @Override - @SuppressWarnings("unchecked") public void valueChanged(final ListSelectionEvent e) { if (!e.getValueIsAdjusting() && !isSkipStateChangedEvent()) { final JList source = (JList) e.getSource(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java index 6f38e62c46d..9a08fae9f4e 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java @@ -31,7 +31,6 @@ import java.awt.dnd.DropTarget; import java.awt.image.*; import java.awt.peer.*; -import java.security.*; import java.util.*; import sun.awt.*; @@ -69,27 +68,23 @@ protected LWToolkit() { * This method waits for the toolkit to be completely initialized * and returns before the message pump is started. */ - @SuppressWarnings("removal") protected final void init() { AWTAutoShutdown.notifyToolkitThreadBusy(); - AccessController.doPrivileged((PrivilegedAction) () -> { - Runnable shutdownRunnable = () -> { - shutdown(); - waitForRunState(STATE_CLEANUP); - }; - Thread shutdown = new Thread( - ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable, - "AWT-Shutdown", 0, false); - shutdown.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(shutdown); - String name = "AWT-LW"; - Thread toolkitThread = new Thread( - ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); - toolkitThread.setDaemon(true); - toolkitThread.setPriority(Thread.NORM_PRIORITY + 1); - toolkitThread.start(); - return null; - }); + Runnable shutdownRunnable = () -> { + shutdown(); + waitForRunState(STATE_CLEANUP); + }; + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable, + "AWT-Shutdown", 0, false); + shutdown.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(shutdown); + String name = "AWT-LW"; + Thread toolkitThread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); + toolkitThread.setDaemon(true); + toolkitThread.setPriority(Thread.NORM_PRIORITY + 1); + toolkitThread.start(); waitForRunState(STATE_MESSAGELOOP); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 4ec8d87fee3..13b6372a3c8 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -1353,7 +1353,6 @@ public void emulateActivation(boolean activate) { changeFocusedWindow(activate, null); } - @SuppressWarnings("deprecation") private boolean isOneOfOwnersOf(LWWindowPeer peer) { Window owner = (peer != null ? peer.getTarget().getOwner() : null); while (owner != null) { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index 436ab6138fa..417750507aa 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -77,16 +77,10 @@ class CAccessibility implements PropertyChangeListener { loadAWTLibrary(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void loadAWTLibrary() { // Need to load the native library for this code. - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); } static CAccessibility sAccessibility; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java index dbf595a55e1..c36cdd27f3f 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java @@ -59,8 +59,7 @@ public final class CDragSourceContextPeer extends SunDragSourceContextPeer { private static double fMaxImageSize = 128.0; static { - @SuppressWarnings("removal") - String propValue = java.security.AccessController.doPrivileged(new sun.security.action.GetPropertyAction("apple.awt.dnd.defaultDragImageSize")); + String propValue = System.getProperty("apple.awt.dnd.defaultDragImageSize"); if (propValue != null) { try { double value = Double.parseDouble(propValue); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java index 169aea8127e..090a90554f0 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java @@ -51,12 +51,10 @@ import java.awt.peer.FileDialogPeer; import java.io.File; import java.io.FilenameFilter; -import java.security.AccessController; import java.util.List; import sun.awt.AWTAccessor; import sun.java2d.pipe.Region; -import sun.security.action.GetBooleanAction; class CFileDialog implements FileDialogPeer { @@ -65,12 +63,8 @@ private class Task implements Runnable { @Override public void run() { try { - @SuppressWarnings("removal") - boolean navigateApps = !AccessController.doPrivileged( - new GetBooleanAction("apple.awt.use-file-dialog-packages")); - @SuppressWarnings("removal") - boolean chooseDirectories = AccessController.doPrivileged( - new GetBooleanAction("apple.awt.fileDialogForDirectories")); + boolean navigateApps = !Boolean.getBoolean("apple.awt.use-file-dialog-packages"); + boolean chooseDirectories = Boolean.getBoolean("apple.awt.fileDialogForDirectories"); int dialogMode = target.getMode(); String title = target.getTitle(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 1bf77f5ee69..0596ad2379e 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -46,7 +46,6 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -70,7 +69,6 @@ import sun.lwawt.LWWindowPeer; import sun.lwawt.LWWindowPeer.PeerType; import sun.lwawt.PlatformWindow; -import sun.security.action.GetPropertyAction; import sun.util.logging.PlatformLogger; public class CPlatformWindow extends CFRetainedResource implements PlatformWindow { @@ -131,9 +129,7 @@ private static native void nativeSetNSWindowStandardFrame(long nsWindowPtr, // This system property is named as jdk.* because it is not specific to AWT // and it is also used in JavaFX - @SuppressWarnings("removal") - public static final String MAC_OS_TABBED_WINDOW = AccessController.doPrivileged( - new GetPropertyAction("jdk.allowMacOSTabbedWindows")); + public static final String MAC_OS_TABBED_WINDOW = System.getProperty("jdk.allowMacOSTabbedWindows"); // Yeah, I know. But it's easier to deal with ints from JNI static final int MODELESS = 0; @@ -272,7 +268,6 @@ public void applyProperty(final CPlatformWindow c, final Object value) { } } }) { - @SuppressWarnings("deprecation") public CPlatformWindow convertJComponentToTarget(final JRootPane p) { Component root = SwingUtilities.getRoot(p); final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index 416a3ee002b..cbb39e24c1a 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -31,8 +31,6 @@ import java.awt.image.BufferedImage; import java.awt.print.*; import java.net.URI; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.concurrent.atomic.AtomicReference; import javax.print.*; @@ -284,7 +282,6 @@ private String getDestinationFile() { return destinationAttr; } - @SuppressWarnings("removal") @Override public void print(PrintRequestAttributeSet attributes) throws PrinterException { // NOTE: Some of this code is copied from RasterPrinterJob. @@ -344,14 +341,7 @@ public void print(PrintRequestAttributeSet attributes) throws PrinterException { onEventThread = true; - printingLoop = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public SecondaryLoop run() { - return Toolkit.getDefaultToolkit() - .getSystemEventQueue() - .createSecondaryLoop(); - } - }); + printingLoop = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop(); try { // Fire off the print rendering loop on the AppKit thread, and don't have diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java index 7d35f859a7a..4ca923c75b6 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java @@ -45,8 +45,6 @@ import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import java.awt.peer.TrayIconPeer; -import java.security.AccessController; -import java.security.PrivilegedAction; import javax.swing.Icon; import javax.swing.UIManager; @@ -71,10 +69,7 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer { // events between MOUSE_PRESSED and MOUSE_RELEASED for particular button private static int mouseClickButtons = 0; - @SuppressWarnings("removal") - private static final boolean useTemplateImages = AccessController.doPrivileged((PrivilegedAction) - () -> Boolean.getBoolean("apple.awt.enableTemplateImages") - ); + private static final boolean useTemplateImages = Boolean.getBoolean("apple.awt.enableTemplateImages"); CTrayIcon(TrayIcon target) { super(0, true); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 9a9be0e65c7..d3ffcfc7730 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -87,8 +87,6 @@ import java.lang.reflect.UndeclaredThrowableException; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -146,24 +144,14 @@ public final class LWCToolkit extends LWToolkit { static { System.err.flush(); - @SuppressWarnings({"removal", "restricted"}) - ResourceBundle platformResources = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - @Override - public ResourceBundle run() { - ResourceBundle platformResources = null; - try { - platformResources = ResourceBundle.getBundle("sun.awt.resources.awtosx"); - } catch (MissingResourceException e) { - // No resource file; defaults will be used. - } - - System.loadLibrary("awt"); - System.loadLibrary("fontmanager"); - - return platformResources; - } - }); + ResourceBundle platformResources = null; + try { + platformResources = ResourceBundle.getBundle("sun.awt.resources.awtosx"); + } catch (MissingResourceException e) { + // No resource file; defaults will be used. + } + + loadLibrary(); if (!GraphicsEnvironment.isHeadless() && !PlatformGraphicsInfo.isInAquaSession()) @@ -178,32 +166,28 @@ public ResourceBundle run() { } } + @SuppressWarnings("restricted") + private static void loadLibrary() { + System.loadLibrary("awt"); + System.loadLibrary("fontmanager"); + } + /* * If true we operate in normal mode and nested runloop is executed in JavaRunLoopMode * If false we operate in singleThreaded FX/AWT interop mode and nested loop uses NSDefaultRunLoopMode */ - @SuppressWarnings("removal") private static final boolean inAWT - = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Boolean run() { - return !Boolean.parseBoolean( + = !Boolean.parseBoolean( System.getProperty("javafx.embed.singleThread", "false")); - } - }); - @SuppressWarnings("removal") public LWCToolkit() { final String extraButtons = "sun.awt.enableExtraMouseButtons"; - AccessController.doPrivileged((PrivilegedAction) () -> { areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty(extraButtons, "true")); //set system property if not yet assigned - System.setProperty(extraButtons, ""+areExtraMouseButtonsEnabled); + System.setProperty(extraButtons, "" + areExtraMouseButtonsEnabled); initAppkit(ThreadGroupUtils.getRootThreadGroup(), GraphicsEnvironment.isHeadless()); - return null; - }); } /* @@ -254,13 +238,9 @@ public static Color getAppleColor(int color) { } // This is only called from native code. - @SuppressWarnings("removal") static void systemColorsChanged() { EventQueue.invokeLater(() -> { - AccessController.doPrivileged( (PrivilegedAction) () -> { AWTAccessor.getSystemColorAccessor().updateSystemColors(); - return null; - }); }); } @@ -592,13 +572,9 @@ public boolean isAlwaysOnTopSupported() { private static final String APPKIT_THREAD_NAME = "AppKit Thread"; // Intended to be called from the LWCToolkit.m only. - @SuppressWarnings("removal") private static void installToolkitThreadInJava() { Thread.currentThread().setName(APPKIT_THREAD_NAME); - AccessController.doPrivileged((PrivilegedAction) () -> { - Thread.currentThread().setContextClassLoader(null); - return null; - }); + Thread.currentThread().setContextClassLoader(null); } @Override diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m index e881c5cc38f..889eaa4aff7 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -515,23 +515,6 @@ - (void) drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; JNIEnv *env = [ThreadUtilities getJNIEnv]; if (env != NULL) { - /* - if ([self inLiveResize]) { - NSRect rs[4]; - NSInteger count; - [self getRectsExposedDuringLiveResize:rs count:&count]; - for (int i = 0; i < count; i++) { - JNU_CallMethodByName(env, NULL, [m_awtWindow cPlatformView], - "deliverWindowDidExposeEvent", "(FFFF)V", - (jfloat)rs[i].origin.x, (jfloat)rs[i].origin.y, - (jfloat)rs[i].size.width, (jfloat)rs[i].size.height); - if ((*env)->ExceptionOccurred(env)) { - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - } - } - } else { - */ DECLARE_CLASS(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView"); DECLARE_METHOD(jm_deliverWindowDidExposeEvent, jc_CPlatformView, "deliverWindowDidExposeEvent", "()V"); jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); @@ -540,9 +523,6 @@ - (void) drawRect:(NSRect)dirtyRect { CHECK_EXCEPTION(); (*env)->DeleteLocalRef(env, jlocal); } - /* - } - */ } } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDataTransferer.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDataTransferer.m index f0bc347197f..ca92d67faf5 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDataTransferer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDataTransferer.m @@ -136,7 +136,7 @@ static jobjectArray CreateJavaFilenameArray(JNIEnv *env, NSArray *filenameArray) jclass stringClazz = (*env)->FindClass(env, "java/lang/String"); CHECK_NULL_RETURN(stringClazz, nil); jobject jfilenameArray = (*env)->NewObjectArray(env, filenameCount, stringClazz, NULL); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); return nil; @@ -156,7 +156,7 @@ static jobjectArray CreateJavaFilenameArray(JNIEnv *env, NSArray *filenameArray) // Create a Java String: jstring string = (*env)->NewStringUTF(env, stringBytes); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); continue; @@ -168,7 +168,7 @@ static jobjectArray CreateJavaFilenameArray(JNIEnv *env, NSArray *filenameArray) // Set the Java array element with our String: (*env)->SetObjectArrayElement(env, jfilenameArray, i, string); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); continue; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m index b8e87b25343..8752af237fe 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m @@ -371,10 +371,10 @@ - (jobject) copyDraggingDataForFormat:(jlong)format (*env)->ReleaseByteArrayElements(env, gbyteArray, jbytes, 0); // In case of an error make sure to return nil: - if ((*env)->ExceptionOccurred(env)) { - (*env)->ExceptionDescribe(env); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); gbyteArray = nil; - } + } return gbyteArray; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTargetContextPeer.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTargetContextPeer.m index 2e590369508..0ee8300f72f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTargetContextPeer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTargetContextPeer.m @@ -85,7 +85,7 @@ static void TransferFailed(JNIEnv *env, jobject jthis, jlong jdroptarget, jlong GET_DTCP_CLASS_RETURN(result); DECLARE_METHOD_RETURN(newDataMethod, jc_CDropTargetContextPeer, "newData", "(J[B)V", result); - if ((*env)->ExceptionOccurred(env) || !newDataMethod) { + if ((*env)->ExceptionCheck(env) || !newDataMethod) { DLog2(@"[CDropTargetContextPeer startTransfer]: couldn't get newData method for %d.\n", (NSInteger) jdroptarget); TransferFailed(env, jthis, jdroptarget, (jlong) 0L, jformat); return result; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m index 468c5f6dae0..787b90b4b90 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m @@ -364,7 +364,7 @@ static jobject createJavaDisplayMode(CGDisplayModeRef mode, JNIEnv *env) { if (cRef != NULL) { jobject oneMode = createJavaDisplayMode(cRef, env); (*env)->SetObjectArrayElement(env, jreturnArray, n, oneMode); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); continue; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m index 3bfd72668c3..7d580216985 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m @@ -316,10 +316,10 @@ + (void) _nativeEndComposition:(AWTView *)view { } if ((*env)->CallBooleanMethod(env, returnValue, jm_listContains, localeObj) == JNI_FALSE) { - if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionClear(env); + if ((*env)->ExceptionCheck(env)) (*env)->ExceptionClear(env); (*env)->CallBooleanMethod(env, returnValue, jm_listAdd, localeObj); } - if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionClear(env); + if ((*env)->ExceptionCheck(env)) (*env)->ExceptionClear(env); (*env)->DeleteLocalRef(env, localeObj); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m index 5e1d6ba0cb1..a1f4afb0929 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m @@ -577,7 +577,7 @@ static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath) jstring jFontName = (jstring)NSStringToJavaString(env, fontname); CFRelease(fontname); (*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { CFRelease(fds); return; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m index 1e2ba23d9aa..7b436382065 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m @@ -95,7 +95,7 @@ + (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont _fontThrowJavaException = YES; \ goto cleanup; \ } \ - if ((*env)->ExceptionCheck(env) == JNI_TRUE) { \ + if ((*env)->ExceptionCheck(env)) { \ goto cleanup; \ } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m index 90b77879b2a..d09e1fc32c7 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m @@ -154,7 +154,7 @@ static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque } JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); - if (!((*env)->ExceptionOccurred(env))) { + if (!((*env)->ExceptionCheck(env))) { JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); } diff --git a/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h b/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h index 41dd4c48b75..fec64e09141 100644 --- a/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h +++ b/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h @@ -38,11 +38,11 @@ NSLog(@"Bad JNI lookup %s\n", name); \ NSLog(@"%@",[NSThread callStackSymbols]); \ if ([NSThread isMainThread] == NO) { \ - if ((*env)->ExceptionOccurred(env) == NULL) { \ + if (!(*env)->ExceptionCheck(env)) { \ JNU_ThrowInternalError(env, "Bad JNI Lookup"); \ } \ } else { \ - if ((*env)->ExceptionOccurred(env) != NULL) { \ + if ((*env)->ExceptionCheck(env)) { \ (*env)->ExceptionDescribe(env); \ } \ } \ @@ -184,7 +184,7 @@ * nature of the problem that has been detected and how survivable it is. */ #define CHECK_EXCEPTION() \ - if ((*env)->ExceptionOccurred(env) != NULL) { \ + if ((*env)->ExceptionCheck(env)) { \ if ([NSThread isMainThread] == YES) { \ if (getenv("JNU_APPKIT_TRACE")) { \ (*env)->ExceptionDescribe(env); \ diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java index 9eab27031d4..06af183b37c 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java @@ -48,8 +48,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.ByteOrder; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -2039,17 +2037,9 @@ public void readAborted(ImageReader src) {} private static Boolean isLinkedProfileAllowed = null; - @SuppressWarnings("removal") private static boolean isLinkedProfileAllowed() { if (isLinkedProfileAllowed == null) { - PrivilegedAction a = new PrivilegedAction() { - @Override - public Boolean run() { - return Boolean. - getBoolean("sun.imageio.bmp.enableLinkedProfiles"); - } - }; - isLinkedProfileAllowed = AccessController.doPrivileged(a); + isLinkedProfileAllowed = Boolean.getBoolean("sun.imageio.bmp.enableLinkedProfiles"); } return isLinkedProfileAllowed; } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index c28759058c0..24013fb68ad 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -90,16 +90,9 @@ public class JPEGImageReader extends ImageReader { initStatic(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void initStatic() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - @Override - public Void run() { - System.loadLibrary("javajpeg"); - return null; - } - }); + System.loadLibrary("javajpeg"); initReaderIDs(ImageInputStream.class, JPEGQTable.class, JPEGHuffmanTable.class); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java index 39189130be3..f263d47f6c9 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java @@ -175,16 +175,9 @@ public class JPEGImageWriter extends ImageWriter { initStatic(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void initStatic() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - @Override - public Void run() { - System.loadLibrary("javajpeg"); - return null; - } - }); + System.loadLibrary("javajpeg"); initWriterIDs(JPEGQTable.class, JPEGHuffmanTable.class); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java index 5ad3db345e2..bc787f9127c 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -610,7 +610,6 @@ public void decodeRaw(byte[] b, JPEGReader.read(0, JPEGParam); } - @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); JPEGReader.dispose(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java b/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java index 3dabca71ffb..b40c53ead3d 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java +++ b/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java @@ -28,8 +28,6 @@ import sun.awt.util.ThreadGroupUtils; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Set; import java.util.WeakHashMap; import javax.imageio.stream.ImageInputStream; @@ -86,21 +84,18 @@ public void run() { } }; - AccessController.doPrivileged((PrivilegedAction) () -> { - /* The thread must be a member of a thread group - * which will not get GCed before VM exit. - * Make its parent the top-level thread group. - */ - ThreadGroup tg = ThreadGroupUtils.getRootThreadGroup(); - streamCloser = new Thread(tg, streamCloserRunnable, - "StreamCloser", 0, false); - /* Set context class loader to null in order to avoid - * keeping a strong reference to an application classloader. - */ - streamCloser.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(streamCloser); - return null; - }); + /* The thread must be a member of a thread group + * which will not get GCed before VM exit. + * Make its parent the top-level thread group. + */ + ThreadGroup tg = ThreadGroupUtils.getRootThreadGroup(); + streamCloser = new Thread(tg, streamCloserRunnable, + "StreamCloser", 0, false); + /* Set context class loader to null in order to avoid + * keeping a strong reference to an application classloader. + */ + streamCloser.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(streamCloser); } } } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java index 295e474579b..629b107f163 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java @@ -60,8 +60,6 @@ import java.io.Reader; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -506,21 +504,12 @@ void paintFrameBorder(SynthContext context, Graphics g, int x0, int y0, int widt - private static class Privileged implements PrivilegedAction { + private static class ThemeGetter { private static int GET_THEME_DIR = 0; private static int GET_USER_THEME = 1; private static int GET_IMAGE = 2; - private int type; - private Object arg; - @SuppressWarnings("removal") - public Object doPrivileged(int type, Object arg) { - this.type = type; - this.arg = arg; - return AccessController.doPrivileged(this); - } - - public Object run() { + public Object getThemeItem(int type, Object arg) { if (type == GET_THEME_DIR) { String sep = File.separator; String[] dirs = new String[] { @@ -618,11 +607,11 @@ public Object run() { } private static URL getThemeDir(String themeName) { - return (URL)new Privileged().doPrivileged(Privileged.GET_THEME_DIR, themeName); + return (URL)new ThemeGetter().getThemeItem(ThemeGetter.GET_THEME_DIR, themeName); } private static String getUserTheme() { - return (String)new Privileged().doPrivileged(Privileged.GET_USER_THEME, null); + return (String)new ThemeGetter().getThemeItem(ThemeGetter.GET_USER_THEME, null); } protected void tileImage(Graphics g, Image image, int x0, int y0, int w, int h, float[] alphas) { @@ -673,7 +662,7 @@ protected Image getImage(String key) { try { @SuppressWarnings("deprecation") URL url = new URL(themeDir, key); - image = (Image)new Privileged().doPrivileged(Privileged.GET_IMAGE, url); + image = (Image)new ThemeGetter().getThemeItem(ThemeGetter.GET_IMAGE, url); } catch (MalformedURLException ex) { //log("Bad image url: "+ themeDir + "/" + key); } @@ -1587,18 +1576,11 @@ protected static Document getXMLDoc(final URL xmlFile) documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); } - @SuppressWarnings("removal") - InputStream inputStream = - AccessController.doPrivileged(new PrivilegedAction() { - public InputStream run() { - try { - return new BufferedInputStream(xmlFile.openStream()); - } catch (IOException ex) { - return null; - } - } - }); - + InputStream inputStream = null; + try { + inputStream = new BufferedInputStream(xmlFile.openStream()); + } catch (IOException ex) { + } Document doc = null; if (inputStream != null) { doc = documentBuilder.parse(inputStream); diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java index a6d2f5bbb0e..0f1ecd0dc1e 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -281,7 +281,6 @@ public void installComponents(JFileChooser fc) { fc.setLayout(new BorderLayout(10, 10)); fc.setAlignmentX(JComponent.CENTER_ALIGNMENT); - @SuppressWarnings("serial") // anonymous class JPanel interior = new JPanel() { public Insets getInsets() { return insets; @@ -305,7 +304,6 @@ public Insets getInsets() { curDirName = currentDirectory.getPath(); } - @SuppressWarnings("serial") // anonymous class JTextField tmp1 = new JTextField(curDirName, 35) { public Dimension getMaximumSize() { Dimension d = super.getMaximumSize(); @@ -341,7 +339,6 @@ public Dimension getMaximumSize() { align(l); leftPanel.add(l); - @SuppressWarnings("serial") // anonymous class JComboBox tmp2 = new JComboBox() { public Dimension getMaximumSize() { Dimension d = super.getMaximumSize(); @@ -419,7 +416,6 @@ public Dimension getMaximumSize() { align(fileNameLabel); interior.add(fileNameLabel); - @SuppressWarnings("serial") // anonymous class JTextField tmp3 = new JTextField(35) { public Dimension getMaximumSize() { Dimension d = super.getMaximumSize(); @@ -444,7 +440,6 @@ public Dimension getMaximumSize() { buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS)); buttonPanel.add(Box.createGlue()); - @SuppressWarnings("serial") // anonymous class JButton tmp4 = new JButton(getApproveButtonText(fc)) { public Dimension getMaximumSize() { return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); @@ -460,7 +455,6 @@ public Dimension getMaximumSize() { buttonPanel.add(approveButton); buttonPanel.add(Box.createGlue()); - @SuppressWarnings("serial") // anonymous class JButton updateButton = new JButton(updateButtonText) { public Dimension getMaximumSize() { return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); @@ -475,7 +469,6 @@ public Dimension getMaximumSize() { buttonPanel.add(updateButton); buttonPanel.add(Box.createGlue()); - @SuppressWarnings("serial") // anonymous class JButton cancelButton = new JButton(cancelButtonText) { public Dimension getMaximumSize() { return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); @@ -490,7 +483,6 @@ public Dimension getMaximumSize() { buttonPanel.add(cancelButton); buttonPanel.add(Box.createGlue()); - @SuppressWarnings("serial") // anonymous class JButton helpButton = new JButton(helpButtonText) { public Dimension getMaximumSize() { return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java index cba71847fa4..1179df181ab 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -132,7 +132,6 @@ protected void uninstallKeyboardActions(){ } } - @SuppressWarnings("serial") // anonymous class protected void setupMenuOpenKey(){ super.setupMenuOpenKey(); ActionMap map = SwingUtilities.getUIActionMap(frame); @@ -152,7 +151,6 @@ public boolean isEnabled(){ } } - @SuppressWarnings("serial") // anonymous class protected void setupMenuCloseKey(){ ActionMap map = SwingUtilities.getUIActionMap(frame); if (map != null) { diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java index a9c40aa71af..e68d7e2d8bf 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -72,7 +72,6 @@ public Dimension getMinimumOptionPaneSize() { return null; } - @SuppressWarnings("serial") // anonymous class protected Container createSeparator() { return new JPanel() { diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java b/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java index 6447e654f60..4ff72c7040a 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java @@ -32,7 +32,6 @@ import java.io.InputStreamReader; import java.net.URL; import java.net.URLClassLoader; -import java.security.AccessController; import java.util.ArrayList; import java.util.Objects; @@ -55,10 +54,7 @@ public final class JARSoundbankReader extends SoundbankReader { * {@code true} if jar sound bank is allowed to be loaded default is * {@code false}. */ - @SuppressWarnings("removal") - private static final boolean JAR_SOUNDBANK_ENABLED = - AccessController.doPrivileged( - new GetBooleanAction("jdk.sound.jarsoundbank")); + private static final boolean JAR_SOUNDBANK_ENABLED = Boolean.getBoolean("jdk.sound.jarsoundbank"); private static boolean isZIP(URL url) { boolean ok = false; diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JDK13Services.java b/src/java.desktop/share/classes/com/sun/media/sound/JDK13Services.java index 0d8f34ca225..4ed79db13b5 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/JDK13Services.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/JDK13Services.java @@ -25,8 +25,6 @@ package com.sun.media.sound; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -170,9 +168,7 @@ private static synchronized String getDefaultProvider(Class typeClass) { return null; } String name = typeClass.getName(); - @SuppressWarnings("removal") - String value = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty(name)); + String value = System.getProperty(name); if (value == null) { value = getProperties().getProperty(name); } diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java b/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java index 51482b24aea..e9b99ac1a10 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java @@ -29,8 +29,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -41,7 +39,7 @@ /** Managing security in the Java Sound implementation. * This class contains all code that uses and is used by - * SecurityManager.doPrivileged(). + * SecurityManager * * @author Matthias Pfisterer */ @@ -74,24 +72,18 @@ static void checkRecordPermission() throws SecurityException { * @param properties the properties bundle to store the values of the * properties file */ - @SuppressWarnings("removal") static void loadProperties(final Properties properties) { - final String customFile = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty( - "javax.sound.config.file")); + final String customFile = System.getProperty("javax.sound.config.file"); if (customFile != null) { if (loadPropertiesImpl(properties, customFile)) { return; } } - AccessController.doPrivileged((PrivilegedAction) () -> { - final String home = System.getProperty("java.home"); - if (home == null) { - throw new Error("Can't find java.home ??"); - } - loadPropertiesImpl(properties, home, "conf", "sound.properties"); - return null; - }); + final String home = System.getProperty("java.home"); + if (home == null) { + throw new Error("Can't find java.home ??"); + } + loadPropertiesImpl(properties, home, "conf", "sound.properties"); } private static boolean loadPropertiesImpl(final Properties properties, @@ -124,32 +116,11 @@ static Thread createThread(final Runnable runnable, return thread; } - @SuppressWarnings("removal") static synchronized List getProviders(final Class providerClass) { List p = new ArrayList<>(7); - // ServiceLoader creates "lazy" iterator instance, but it ensures that - // next/hasNext run with permissions that are restricted by whatever - // creates the ServiceLoader instance, so it requires to be called from - // privileged section - final PrivilegedAction> psAction = - new PrivilegedAction>() { - @Override - public Iterator run() { - return ServiceLoader.load(providerClass).iterator(); - } - }; - final Iterator ps = AccessController.doPrivileged(psAction); - - // the iterator's hasNext() method looks through classpath for - // the provider class names, so it requires read permissions - PrivilegedAction hasNextAction = new PrivilegedAction() { - @Override - public Boolean run() { - return ps.hasNext(); - } - }; + final Iterator ps = ServiceLoader.load(providerClass).iterator(); - while (AccessController.doPrivileged(hasNextAction)) { + while (ps.hasNext()) { try { // the iterator's next() method creates instances of the // providers and it should be called in the current security diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java b/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java index affec1aace1..00862ea9022 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -57,7 +57,7 @@ * @author Arthur van Hoff, Kara Kytle, Jan Borgersen * @author Florian Bomers */ -@SuppressWarnings({"deprecation", "removal"}) +@SuppressWarnings("removal") public final class JavaSoundAudioClip implements AudioClip, MetaEventListener, LineListener { private long lastPlayCall = 0; diff --git a/src/java.desktop/share/classes/com/sun/media/sound/Platform.java b/src/java.desktop/share/classes/com/sun/media/sound/Platform.java index 727718c6ca9..ded8a6496f5 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/Platform.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/Platform.java @@ -25,8 +25,6 @@ package com.sun.media.sound; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.StringTokenizer; /** @@ -74,15 +72,12 @@ static boolean isBigEndian() { /** * Load the native library or libraries. */ - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void loadLibraries() { // load the native library isNativeLibLoaded = true; try { - AccessController.doPrivileged((PrivilegedAction) () -> { - System.loadLibrary(libName); - return null; - }); + System.loadLibrary(libName); } catch (Throwable t) { if (Printer.err) Printer.err("Couldn't load library "+libName+": "+t.toString()); isNativeLibLoaded = false; diff --git a/src/java.desktop/share/classes/com/sun/media/sound/Printer.java b/src/java.desktop/share/classes/com/sun/media/sound/Printer.java index c67ca92f574..40e179b1bd8 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/Printer.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/Printer.java @@ -25,7 +25,6 @@ package com.sun.media.sound; -import java.security.AccessController; import sun.security.action.GetPropertyAction; @@ -66,9 +65,7 @@ public static void err(String str) { * Returns {@code true} if the build of the current jdk is "internal". */ private static boolean isBuildInternal() { - @SuppressWarnings("removal") - String javaVersion = AccessController.doPrivileged( - new GetPropertyAction("java.version")); + String javaVersion = System.getProperty("java.version"); return javaVersion != null && javaVersion.contains("internal"); } diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java b/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java index e951a6a6578..4c33416e470 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java @@ -36,8 +36,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -634,15 +632,19 @@ public boolean remapInstrument(Instrument from, Instrument to) { } } + static interface RunnableAction { + T run(); + } + @Override public Soundbank getDefaultSoundbank() { synchronized (SoftSynthesizer.class) { if (defaultSoundBank != null) return defaultSoundBank; - List> actions = new ArrayList<>(); + List> actions = new ArrayList<>(); - actions.add(new PrivilegedAction() { + actions.add(new RunnableAction() { @Override public InputStream run() { File javahome = new File(System.getProperties() @@ -678,7 +680,7 @@ public InputStream run() { } }); - actions.add(new PrivilegedAction() { + actions.add(new RunnableAction() { @Override public InputStream run() { if (OSInfo.getOSType() == OSInfo.OSType.LINUX) { @@ -712,7 +714,7 @@ public InputStream run() { } }); - actions.add(new PrivilegedAction() { + actions.add(new RunnableAction() { @Override public InputStream run() { if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { @@ -729,7 +731,7 @@ public InputStream run() { } }); - actions.add(new PrivilegedAction() { + actions.add(new RunnableAction() { @Override public InputStream run() { /* @@ -749,10 +751,9 @@ public InputStream run() { } }); - for (PrivilegedAction action : actions) { + for (RunnableAction action : actions) { try { - @SuppressWarnings("removal") - InputStream is = AccessController.doPrivileged(action); + InputStream is = action.run(); if(is == null) continue; Soundbank sbk; try (is) { @@ -778,9 +779,8 @@ public InputStream run() { /* * Save generated soundbank to disk for faster future use. */ - @SuppressWarnings("removal") - OutputStream out = AccessController - .doPrivileged((PrivilegedAction) () -> { + OutputStream out = + ((RunnableAction) () -> { try { File userhome = new File(System .getProperty("user.home"), ".gervill"); @@ -798,7 +798,7 @@ public InputStream run() { } catch (final FileNotFoundException ignored) { } return null; - }); + }).run(); if (out != null) { try (out) { ((SF2Soundbank) defaultSoundBank).save(out); @@ -897,28 +897,24 @@ public MidiDevice.Info getDeviceInfo() { return info; } - @SuppressWarnings("removal") private Properties getStoredProperties() { - return AccessController - .doPrivileged((PrivilegedAction) () -> { - Properties p = new Properties(); - String notePath = "/com/sun/media/sound/softsynthesizer"; - try { - Preferences prefroot = Preferences.userRoot(); - if (prefroot.nodeExists(notePath)) { - Preferences prefs = prefroot.node(notePath); - String[] prefs_keys = prefs.keys(); - for (String prefs_key : prefs_keys) { - String val = prefs.get(prefs_key, null); - if (val != null) { - p.setProperty(prefs_key, val); - } - } - } - } catch (final BackingStoreException ignored) { + Properties p = new Properties(); + String notePath = "/com/sun/media/sound/softsynthesizer"; + try { + Preferences prefroot = Preferences.userRoot(); + if (prefroot.nodeExists(notePath)) { + Preferences prefs = prefroot.node(notePath); + String[] prefs_keys = prefs.keys(); + for (String prefs_key : prefs_keys) { + String val = prefs.get(prefs_key, null); + if (val != null) { + p.setProperty(prefs_key, val); } - return p; - }); + } + } + } catch (final BackingStoreException ignored) { + } + return p; } @Override diff --git a/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java b/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java index 56084ec8f90..592482823db 100644 --- a/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java +++ b/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -625,7 +625,6 @@ public static WindowListener add(WindowListener a, WindowListener b) { * @return the resulting listener * @since 1.4 */ - @SuppressWarnings("overloads") public static WindowStateListener add(WindowStateListener a, WindowStateListener b) { return (WindowStateListener)addInternal(a, b); @@ -828,7 +827,6 @@ public static WindowListener remove(WindowListener l, WindowListener oldl) { * @return the resulting listener * @since 1.4 */ - @SuppressWarnings("overloads") public static WindowStateListener remove(WindowStateListener l, WindowStateListener oldl) { return (WindowStateListener) removeInternal(l, oldl); diff --git a/src/java.desktop/share/classes/java/awt/Component.java b/src/java.desktop/share/classes/java/awt/Component.java index ad0b87fd3fc..71618eea95b 100644 --- a/src/java.desktop/share/classes/java/awt/Component.java +++ b/src/java.desktop/share/classes/java/awt/Component.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, 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 @@ -627,14 +627,10 @@ static class AWTTreeLock {} initIDs(); } - @SuppressWarnings("removal") - String s = java.security.AccessController.doPrivileged( - new GetPropertyAction("awt.image.incrementaldraw")); + String s = System.getProperty("awt.image.incrementaldraw"); isInc = (s == null || s.equals("true")); - @SuppressWarnings("removal") - String s2 = java.security.AccessController.doPrivileged( - new GetPropertyAction("awt.image.redrawrate")); + String s2 = System.getProperty("awt.image.redrawrate"); incRate = (s2 != null) ? Integer.parseInt(s2) : 100; } @@ -1431,15 +1427,7 @@ public Point getMousePosition() throws HeadlessException { throw new HeadlessException(); } - @SuppressWarnings("removal") - PointerInfo pi = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public PointerInfo run() { - return MouseInfo.getPointerInfo(); - } - } - ); - + PointerInfo pi = MouseInfo.getPointerInfo(); synchronized (getTreeLock()) { Component inTheSameWindow = findUnderMouseInWindow(pi); if (!isSameOrAncestorOf(inTheSameWindow, true)) { @@ -6253,14 +6241,7 @@ private boolean checkCoalescing() { } // Need to check non-bootstraps. - @SuppressWarnings("removal") - Boolean enabled = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Boolean run() { - return isCoalesceEventsOverriden(clazz); - } - } - ); + Boolean enabled = isCoalesceEventsOverriden(clazz); coalesceMap.put(clazz, enabled); return enabled; } @@ -7434,7 +7415,6 @@ final void setFocusTraversalKeys_NoIDCheck(int id, Set k } final Set getFocusTraversalKeys_NoIDCheck(int id) { // Okay to return Set directly because it is an unmodifiable view - @SuppressWarnings("unchecked") Set keystrokes = (focusTraversalKeys != null) ? focusTraversalKeys[id] : null; @@ -8381,7 +8361,6 @@ public void add(PopupMenu popup) { * @see #add(PopupMenu) * @since 1.1 */ - @SuppressWarnings("unchecked") public void remove(MenuComponent popup) { synchronized (getTreeLock()) { if (popups == null) { diff --git a/src/java.desktop/share/classes/java/awt/Container.java b/src/java.desktop/share/classes/java/awt/Container.java index c8289aa7fcc..63bd7467d91 100644 --- a/src/java.desktop/share/classes/java/awt/Container.java +++ b/src/java.desktop/share/classes/java/awt/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, 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 @@ -814,7 +814,6 @@ public void setComponentZOrder(Component comp, int index) { * to new heavyweight parent. * @since 1.5 */ - @SuppressWarnings("deprecation") private void reparentTraverse(ContainerPeer parentPeer, Container child) { checkTreeLock(); @@ -838,7 +837,6 @@ private void reparentTraverse(ContainerPeer parentPeer, Container child) { * Container must be heavyweight. * @since 1.5 */ - @SuppressWarnings("deprecation") private void reparentChild(Component comp) { checkTreeLock(); if (comp == null) { @@ -1576,10 +1574,8 @@ public boolean isValidateRoot() { } // Don't lazy-read because every app uses invalidate() - @SuppressWarnings("removal") - private static final boolean isJavaAwtSmartInvalidate - = AccessController.doPrivileged( - new GetBooleanAction("java.awt.smartInvalidate")); + private static final boolean isJavaAwtSmartInvalidate = + Boolean.getBoolean("java.awt.smartInvalidate"); /** * Invalidates the parent of the container unless the container @@ -2632,14 +2628,7 @@ public Point getMousePosition(boolean allowChildren) throws HeadlessException { if (GraphicsEnvironment.isHeadless()) { throw new HeadlessException(); } - @SuppressWarnings("removal") - PointerInfo pi = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public PointerInfo run() { - return MouseInfo.getPointerInfo(); - } - } - ); + PointerInfo pi = MouseInfo.getPointerInfo(); synchronized (getTreeLock()) { Component inTheSameWindow = findUnderMouseInWindow(pi); if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) { @@ -4212,7 +4201,6 @@ final void recursiveApplyCurrentShape(int fromZorder, int toZorder) { } } - @SuppressWarnings("deprecation") private void recursiveShowHeavyweightChildren() { if (!hasHeavyweightDescendants() || !isVisible()) { return; @@ -4234,7 +4222,6 @@ private void recursiveShowHeavyweightChildren() { } } - @SuppressWarnings("deprecation") private void recursiveHideHeavyweightChildren() { if (!hasHeavyweightDescendants()) { return; @@ -4256,7 +4243,6 @@ private void recursiveHideHeavyweightChildren() { } } - @SuppressWarnings("deprecation") private void recursiveRelocateHeavyweightChildren(Point origin) { for (int index = 0; index < getComponentCount(); index++) { Component comp = getComponent(index); @@ -4738,33 +4724,17 @@ private Component retargetMouseEnterExit(Component targetOver, MouseEvent e, * from other heavyweight containers will generate enter/exit * events in this container */ - @SuppressWarnings("removal") private void startListeningForOtherDrags() { //System.out.println("Adding AWTEventListener"); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - nativeContainer.getToolkit().addAWTEventListener( - LightweightDispatcher.this, - AWTEvent.MOUSE_EVENT_MASK | - AWTEvent.MOUSE_MOTION_EVENT_MASK); - return null; - } - } - ); + nativeContainer.getToolkit().addAWTEventListener( + LightweightDispatcher.this, + AWTEvent.MOUSE_EVENT_MASK | + AWTEvent.MOUSE_MOTION_EVENT_MASK); } - @SuppressWarnings("removal") private void stopListeningForOtherDrags() { //System.out.println("Removing AWTEventListener"); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this); - return null; - } - } - ); + nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this); } /* diff --git a/src/java.desktop/share/classes/java/awt/Cursor.java b/src/java.desktop/share/classes/java/awt/Cursor.java index cfccf06723b..8a595f61285 100644 --- a/src/java.desktop/share/classes/java/awt/Cursor.java +++ b/src/java.desktop/share/classes/java/awt/Cursor.java @@ -29,8 +29,6 @@ import java.io.InputStream; import java.io.Serial; import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; import java.util.Hashtable; import java.util.Properties; import java.util.StringTokenizer; @@ -332,11 +330,7 @@ public static Cursor getSystemCustomCursor(final String name) } final Toolkit toolkit = Toolkit.getDefaultToolkit(); final String file = RESOURCE_PREFIX + fileName; - @SuppressWarnings("removal") - final InputStream in = AccessController.doPrivileged( - (PrivilegedAction) () -> { - return Cursor.class.getResourceAsStream(file); - }); + final InputStream in = Cursor.class.getResourceAsStream(file); try (in) { Image image = toolkit.createImage(in.readAllBytes()); cursor = toolkit.createCustomCursor(image, hotPoint, localized); @@ -428,7 +422,6 @@ public String toString() { /* * load the cursor.properties file */ - @SuppressWarnings("removal") private static void loadSystemCustomCursorProperties() throws AWTException { synchronized (systemCustomCursors) { if (systemCustomCursorProperties != null) { @@ -437,14 +430,8 @@ private static void loadSystemCustomCursorProperties() throws AWTException { systemCustomCursorProperties = new Properties(); try { - AccessController.doPrivileged( - (PrivilegedExceptionAction) () -> { - try (InputStream is = Cursor.class - .getResourceAsStream(PROPERTIES_FILE)) { - systemCustomCursorProperties.load(is); - } - return null; - }); + InputStream is = Cursor.class.getResourceAsStream(PROPERTIES_FILE); + systemCustomCursorProperties.load(is); } catch (Exception e) { systemCustomCursorProperties = null; throw new AWTException("Exception: " + e.getClass() + " " + diff --git a/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java b/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java index e416e791e8d..8ee336548d2 100644 --- a/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java +++ b/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ import java.awt.peer.LightweightPeer; import java.io.Serial; import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; @@ -86,21 +84,14 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { initStatic(); } - @SuppressWarnings("removal") private static void initStatic() { AWTAccessor.setDefaultKeyboardFocusManagerAccessor( new AWTAccessor.DefaultKeyboardFocusManagerAccessor() { public void consumeNextKeyTyped(DefaultKeyboardFocusManager dkfm, KeyEvent e) { dkfm.consumeNextKeyTyped(e); - } + } }); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - fxAppThreadIsDispatchThread = - "true".equals(System.getProperty("javafx.embed.singleThread")); - return null; - } - }); + fxAppThreadIsDispatchThread = "true".equals(System.getProperty("javafx.embed.singleThread")); } /** @@ -1096,7 +1087,6 @@ void clearMarkers() { } } - @SuppressWarnings("deprecation") private boolean preDispatchKeyEvent(KeyEvent ke) { if (((AWTEvent) ke).isPosted) { Component focusOwner = getFocusOwner(); diff --git a/src/java.desktop/share/classes/java/awt/Desktop.java b/src/java.desktop/share/classes/java/awt/Desktop.java index 025889755b8..89a78518873 100644 --- a/src/java.desktop/share/classes/java/awt/Desktop.java +++ b/src/java.desktop/share/classes/java/awt/Desktop.java @@ -42,8 +42,6 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Objects; import javax.swing.JMenuBar; @@ -936,11 +934,7 @@ public boolean moveToTrash(File file) { sm.checkDelete(file.getPath()); } checkActionSupport(Action.MOVE_TO_TRASH); - final File finalFile = file; - AccessController.doPrivileged((PrivilegedAction) () -> { - checkFileValidation(finalFile); - return null; - }); + checkFileValidation(file); return peer.moveToTrash(file); } } diff --git a/src/java.desktop/share/classes/java/awt/Dialog.java b/src/java.desktop/share/classes/java/awt/Dialog.java index a0d22fbb327..03449200478 100644 --- a/src/java.desktop/share/classes/java/awt/Dialog.java +++ b/src/java.desktop/share/classes/java/awt/Dialog.java @@ -34,8 +34,6 @@ import java.io.ObjectInputStream; import java.io.Serial; import java.security.AccessControlException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Iterator; import java.util.concurrent.atomic.AtomicLong; @@ -1052,9 +1050,7 @@ public void show() { modalityPushed(); try { - @SuppressWarnings("removal") - final EventQueue eventQueue = AccessController.doPrivileged( - (PrivilegedAction) Toolkit.getDefaultToolkit()::getSystemEventQueue); + EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); secondaryLoop = eventQueue.createSecondaryLoop(() -> true, modalFilter, 0); if (!secondaryLoop.enter()) { secondaryLoop = null; diff --git a/src/java.desktop/share/classes/java/awt/EventQueue.java b/src/java.desktop/share/classes/java/awt/EventQueue.java index 4dce257f727..f79ff285a79 100644 --- a/src/java.desktop/share/classes/java/awt/EventQueue.java +++ b/src/java.desktop/share/classes/java/awt/EventQueue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,6 @@ import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; - import java.util.EmptyStackException; import sun.awt.*; @@ -45,11 +42,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.atomic.AtomicInteger; -import java.security.AccessControlContext; - -import jdk.internal.access.SharedSecrets; -import jdk.internal.access.JavaSecurityAccess; - /** * {@code EventQueue} is a platform-independent class * that queues events, both from the underlying peer classes @@ -229,13 +221,8 @@ public long getMostRecentEventTime(EventQueue eventQueue) { }); } - @SuppressWarnings("removal") private static boolean fxAppThreadIsDispatchThread = - AccessController.doPrivileged(new PrivilegedAction() { - public Boolean run() { - return "true".equals(System.getProperty("javafx.embed.singleThread")); - } - }); + "true".equals(System.getProperty("javafx.embed.singleThread")); /** * Initializes a new instance of {@code EventQueue}. @@ -668,9 +655,6 @@ public AWTEvent peekEvent(int id) { return null; } - private static final JavaSecurityAccess javaSecurityAccess = - SharedSecrets.getJavaSecurityAccess(); - /** * Dispatches an event. The manner in which the event is * dispatched depends upon the type of the event and the @@ -711,59 +695,25 @@ public AWTEvent peekEvent(int id) { */ protected void dispatchEvent(final AWTEvent event) { final Object src = event.getSource(); - final PrivilegedAction action = new PrivilegedAction() { - public Void run() { - // In case fwDispatcher is installed and we're already on the - // dispatch thread (e.g. performing DefaultKeyboardFocusManager.sendMessage), - // dispatch the event straight away. - if (fwDispatcher == null || isDispatchThreadImpl()) { - dispatchEventImpl(event, src); - } else { - fwDispatcher.scheduleDispatch(new Runnable() { - @Override - public void run() { - if (dispatchThread.filterAndCheckEvent(event)) { - dispatchEventImpl(event, src); - } - } - }); - } - return null; - } - }; - - @SuppressWarnings("removal") - final AccessControlContext stack = AccessController.getContext(); - @SuppressWarnings("removal") - final AccessControlContext srcAcc = getAccessControlContextFrom(src); - @SuppressWarnings("removal") - final AccessControlContext eventAcc = event.getAccessControlContext(); - if (srcAcc == null) { - javaSecurityAccess.doIntersectionPrivilege(action, stack, eventAcc); + // In case fwDispatcher is installed and we're already on the + // dispatch thread (e.g. performing DefaultKeyboardFocusManager.sendMessage), + // dispatch the event straight away. + if (fwDispatcher == null || isDispatchThreadImpl()) { + dispatchEventImpl(event, src); } else { - javaSecurityAccess.doIntersectionPrivilege( - new PrivilegedAction() { - public Void run() { - javaSecurityAccess.doIntersectionPrivilege(action, eventAcc); - return null; + fwDispatcher.scheduleDispatch(new Runnable() { + @Override + public void run() { + if (dispatchThread.filterAndCheckEvent(event)) { + dispatchEventImpl(event, src); } - }, stack, srcAcc); + } + }); } } - @SuppressWarnings("removal") - private static AccessControlContext getAccessControlContextFrom(Object src) { - return src instanceof Component ? - ((Component)src).getAccessControlContext() : - src instanceof MenuComponent ? - ((MenuComponent)src).getAccessControlContext() : - src instanceof TrayIcon ? - ((TrayIcon)src).getAccessControlContext() : - null; - } - /** - * Called from dispatchEvent() under a correct AccessControlContext + * Called from dispatchEvent() */ private void dispatchEventImpl(final AWTEvent event, final Object src) { event.isPosted = true; @@ -1108,26 +1058,17 @@ final boolean isDispatchThreadImpl() { } } - @SuppressWarnings({"deprecation", "removal"}) + @SuppressWarnings("removal") final void initDispatchThread() { pushPopLock.lock(); try { if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) { - dispatchThread = AccessController.doPrivileged( - new PrivilegedAction() { - public EventDispatchThread run() { - EventDispatchThread t = - new EventDispatchThread(threadGroup, - name, - EventQueue.this); - t.setContextClassLoader(classLoader); - t.setPriority(Thread.NORM_PRIORITY + 1); - t.setDaemon(false); - AWTAutoShutdown.getInstance().notifyThreadBusy(t); - return t; - } - } - ); + EventDispatchThread t = new EventDispatchThread(threadGroup, name, EventQueue.this); + t.setContextClassLoader(classLoader); + t.setPriority(Thread.NORM_PRIORITY + 1); + t.setDaemon(false); + AWTAutoShutdown.getInstance().notifyThreadBusy(t); + dispatchThread = t; dispatchThread.start(); } } finally { diff --git a/src/java.desktop/share/classes/java/awt/Font.java b/src/java.desktop/share/classes/java/awt/Font.java index ff5c29a2758..3df4632f9d3 100644 --- a/src/java.desktop/share/classes/java/awt/Font.java +++ b/src/java.desktop/share/classes/java/awt/Font.java @@ -44,8 +44,6 @@ import java.io.Serial; import java.lang.ref.SoftReference; import java.nio.file.Files; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; import java.text.AttributedCharacterIterator.Attribute; import java.text.CharacterIterator; import java.util.EventListener; @@ -1095,7 +1093,6 @@ public static Font createFont(int fontFormat, InputStream fontStream) } } - @SuppressWarnings("removal") private static Font[] createFont0(int fontFormat, InputStream fontStream, boolean allFonts, CreatedFontTracker tracker) @@ -1107,27 +1104,14 @@ private static Font[] createFont0(int fontFormat, InputStream fontStream, } boolean copiedFontData = false; try { - final File tFile = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public File run() throws IOException { - return Files.createTempFile("+~JF", ".tmp").toFile(); - } - } - ); + final File tFile = Files.createTempFile("+~JF", ".tmp").toFile(); if (tracker != null) { tracker.add(tFile); } int totalSize = 0; try { - final OutputStream outStream = - AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public OutputStream run() throws IOException { - return new FileOutputStream(tFile); - } - } - ); + final OutputStream outStream = new FileOutputStream(tFile); if (tracker != null) { tracker.set(tFile, outStream); } @@ -1181,14 +1165,7 @@ public OutputStream run() throws IOException { if (tracker != null) { tracker.subBytes(totalSize); } - AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Void run() { - tFile.delete(); - return null; - } - } - ); + tFile.delete(); } } } catch (Throwable t) { diff --git a/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java b/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java index 2e89aa6f672..4936d5d396d 100644 --- a/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java +++ b/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java @@ -26,8 +26,6 @@ package java.awt; import java.awt.image.BufferedImage; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Locale; import sun.awt.PlatformGraphicsInfo; @@ -137,20 +135,16 @@ static String getHeadlessMessage() { * @return the value of the property "java.awt.headless" * @since 1.4 */ - @SuppressWarnings("removal") private static boolean getHeadlessProperty() { if (headless == null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - String nm = System.getProperty("java.awt.headless"); + String nm = System.getProperty("java.awt.headless"); - if (nm == null) { - headless = defaultHeadless = - PlatformGraphicsInfo.getDefaultHeadlessProperty(); - } else { - headless = Boolean.valueOf(nm); - } - return null; - }); + if (nm == null) { + headless = defaultHeadless = + PlatformGraphicsInfo.getDefaultHeadlessProperty(); + } else { + headless = Boolean.valueOf(nm); + } } return headless; } diff --git a/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java b/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java index 0ca86f3433b..eb623213a77 100644 --- a/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java +++ b/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java @@ -40,9 +40,6 @@ import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; - import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -601,14 +598,8 @@ private void _clearGlobalFocusOwner() { peer.clearGlobalFocusOwner(activeWindow); } - @SuppressWarnings("removal") void clearGlobalFocusOwnerPriv() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - clearGlobalFocusOwner(); - return null; - } - }); + clearGlobalFocusOwner(); } Component getNativeFocusOwner() { @@ -1194,14 +1185,8 @@ public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) { newFocusCycleRoot); } - @SuppressWarnings("removal") void setGlobalCurrentFocusCycleRootPriv(final Container newFocusCycleRoot) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - setGlobalCurrentFocusCycleRoot(newFocusCycleRoot); - return null; - } - }); + setGlobalCurrentFocusCycleRoot(newFocusCycleRoot); } /** diff --git a/src/java.desktop/share/classes/java/awt/MediaTracker.java b/src/java.desktop/share/classes/java/awt/MediaTracker.java index 2435dd0ba33..408d68ffe14 100644 --- a/src/java.desktop/share/classes/java/awt/MediaTracker.java +++ b/src/java.desktop/share/classes/java/awt/MediaTracker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, 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 @@ -927,7 +927,6 @@ void setStatus(int flag) { * The entry of the list of {@code Images} that is being tracked by the * {@code MediaTracker}. */ -@SuppressWarnings("serial") // MediaEntry does not have a no-arg ctor class ImageMediaEntry extends MediaEntry implements ImageObserver, java.io.Serializable { @SuppressWarnings("serial") // Not statically typed as Serializable diff --git a/src/java.desktop/share/classes/java/awt/SequencedEvent.java b/src/java.desktop/share/classes/java/awt/SequencedEvent.java index 410437a5c9e..e04757e195f 100644 --- a/src/java.desktop/share/classes/java/awt/SequencedEvent.java +++ b/src/java.desktop/share/classes/java/awt/SequencedEvent.java @@ -26,8 +26,6 @@ package java.awt; import java.io.Serial; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.LinkedList; import sun.awt.AWTAccessor; @@ -45,7 +43,6 @@ * * @author David Mendenhall */ -@SuppressWarnings("removal") class SequencedEvent extends AWTEvent implements ActiveEvent { /** @@ -80,13 +77,7 @@ public AWTEvent create(AWTEvent event) { return new SequencedEvent(event); } }); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - fxAppThreadIsDispatchThread = - "true".equals(System.getProperty("javafx.embed.singleThread")); - return null; - } - }); + fxAppThreadIsDispatchThread = "true".equals(System.getProperty("javafx.embed.singleThread")); } private static final class SequencedEventsFilter implements EventFilter { diff --git a/src/java.desktop/share/classes/java/awt/SplashScreen.java b/src/java.desktop/share/classes/java/awt/SplashScreen.java index 78ec4ed7aa0..737c1a5c080 100644 --- a/src/java.desktop/share/classes/java/awt/SplashScreen.java +++ b/src/java.desktop/share/classes/java/awt/SplashScreen.java @@ -121,7 +121,7 @@ public final class SplashScreen { * @return the {@link SplashScreen} instance, or {@code null} if there is * none or it has already been closed */ - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") public static SplashScreen getSplashScreen() { synchronized (SplashScreen.class) { if (GraphicsEnvironment.isHeadless()) { @@ -129,13 +129,7 @@ public static SplashScreen getSplashScreen() { } // SplashScreen class is now a singleton if (!wasClosed && theInstance == null) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("splashscreen"); - return null; - } - }); + System.loadLibrary("splashscreen"); long ptr = _getInstance(); if (ptr != 0 && _isVisible(ptr)) { theInstance = new SplashScreen(ptr); diff --git a/src/java.desktop/share/classes/java/awt/Toolkit.java b/src/java.desktop/share/classes/java/awt/Toolkit.java index 19b0ab9019a..d181fb6f536 100644 --- a/src/java.desktop/share/classes/java/awt/Toolkit.java +++ b/src/java.desktop/share/classes/java/awt/Toolkit.java @@ -56,8 +56,6 @@ import java.io.File; import java.io.FileInputStream; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.EventListener; @@ -396,18 +394,12 @@ public abstract ColorModel getColorModel() * properties are set up properly before any classes dependent upon them * are initialized. */ - @SuppressWarnings("removal") private static void initAssistiveTechnologies() { // Get accessibility properties final String sep = File.separator; final Properties properties = new Properties(); - - atNames = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public String run() { - // Try loading the per-user accessibility properties file. try { File propsFile = new File( @@ -459,9 +451,7 @@ public String run() { System.setProperty("javax.accessibility.assistive_technologies", classNames); } } - return classNames; - } - }); + atNames = classNames; } /** @@ -512,7 +502,6 @@ private static void fallbackToLoadClassForAT(String atName) { * {@code null} it is ignored. All other errors are handled via an AWTError * exception. */ - @SuppressWarnings("removal") private static void loadAssistiveTechnologies() { // Load any assistive technologies if (atNames != null && !atNames.isBlank()) { @@ -521,20 +510,17 @@ private static void loadAssistiveTechnologies() { .map(String::trim) .collect(Collectors.toSet()); final Map providers = new HashMap<>(); - AccessController.doPrivileged((PrivilegedAction) () -> { - try { - for (AccessibilityProvider p : ServiceLoader.load(AccessibilityProvider.class, cl)) { - String name = p.getName(); - if (names.contains(name) && !providers.containsKey(name)) { - p.activate(); - providers.put(name, p); - } + try { + for (AccessibilityProvider p : ServiceLoader.load(AccessibilityProvider.class, cl)) { + String name = p.getName(); + if (names.contains(name) && !providers.containsKey(name)) { + p.activate(); + providers.put(name, p); } - } catch (java.util.ServiceConfigurationError | Exception e) { - newAWTError(e, "Could not load or activate service provider"); } - return null; - }); + } catch (java.util.ServiceConfigurationError | Exception e) { + newAWTError(e, "Could not load or activate service provider"); + } names.stream() .filter(n -> !providers.containsKey(n)) .forEach(Toolkit::fallbackToLoadClassForAT); @@ -1302,16 +1288,10 @@ private static void setPlatformResources(ResourceBundle bundle) { * directly. -hung */ private static boolean loaded = false; - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") static void loadLibraries() { if (!loaded) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); loaded = true; } } @@ -1320,7 +1300,6 @@ public Void run() { initStatic(); } - @SuppressWarnings("removal") private static void initStatic() { AWTAccessor.setToolkitAccessor( new AWTAccessor.ToolkitAccessor() { @@ -1330,17 +1309,11 @@ public void setPlatformResources(ResourceBundle bundle) { } }); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - try { - resources = ResourceBundle.getBundle("sun.awt.resources.awt"); - } catch (MissingResourceException e) { - // No resource file; defaults will be used. - } - return null; - } - }); + try { + resources = ResourceBundle.getBundle("sun.awt.resources.awt"); + } catch (MissingResourceException e) { + // No resource file; defaults will be used. + } // ensure that the proper libraries are loaded loadLibraries(); diff --git a/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java b/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java index d239a600697..50a66e997f9 100644 --- a/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java +++ b/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java @@ -29,9 +29,6 @@ import java.util.TimerTask; import java.util.concurrent.atomic.AtomicBoolean; -import java.security.PrivilegedAction; -import java.security.AccessController; - import sun.awt.PeerEvent; import sun.util.logging.PlatformLogger; @@ -164,7 +161,6 @@ public WaitDispatchSupport(EventDispatchThread dispatchThread, /** * {@inheritDoc} */ - @SuppressWarnings("removal") @Override public boolean enter() { if (log.isLoggable(PlatformLogger.Level.FINE)) { @@ -230,13 +226,7 @@ public void run() { // The event will be handled after the new event pump // starts. Thus, the enter() method will not hang. // - // Event pump should be privileged. See 6300270. - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - run.run(); - return null; - } - }); + run.run(); } else { if (log.isLoggable(PlatformLogger.Level.FINEST)) { log.finest("On non-dispatch thread: " + currentThread); diff --git a/src/java.desktop/share/classes/java/awt/Window.java b/src/java.desktop/share/classes/java/awt/Window.java index a1e9d48d9d4..9b855739443 100644 --- a/src/java.desktop/share/classes/java/awt/Window.java +++ b/src/java.desktop/share/classes/java/awt/Window.java @@ -48,7 +48,6 @@ import java.io.Serializable; import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.EventListener; @@ -414,13 +413,9 @@ public static enum Type { initIDs(); } - @SuppressWarnings("removal") - String s = java.security.AccessController.doPrivileged( - new GetPropertyAction("java.awt.syncLWRequests")); + String s = System.getProperty("java.awt.syncLWRequests"); systemSyncLWRequests = "true".equals(s); - @SuppressWarnings("removal") - String s2 = java.security.AccessController.doPrivileged( - new GetPropertyAction("java.awt.Window.locationByPlatform")); + String s2 = System.getProperty("java.awt.Window.locationByPlatform"); locationByPlatformProp = "true".equals(s2); } @@ -505,7 +500,6 @@ private void init(GraphicsConfiguration gc) { weakThis = new WeakReference(this); addToWindowList(); - setWarningString(); this.cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); this.visible = false; @@ -804,7 +798,6 @@ public void removeNotify() { * @see Component#isDisplayable * @see #setMinimumSize */ - @SuppressWarnings("deprecation") public void pack() { Container parent = this.parent; if (parent != null && parent.peer == null) { @@ -1376,24 +1369,6 @@ public final String getWarningString() { return warningString; } - @SuppressWarnings("removal") - private void setWarningString() { - warningString = null; - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkPermission(AWTPermissions.TOPLEVEL_WINDOW_PERMISSION); - } catch (SecurityException se) { - // make sure the privileged action is only - // for getting the property! We don't want the - // above checkPermission call to always succeed! - warningString = AccessController.doPrivileged( - new GetPropertyAction("awt.appletWarning", - "Java Applet Window")); - } - } - } - /** * Gets the {@code Locale} object that is associated * with this window, if the locale has been set. @@ -2978,7 +2953,6 @@ private void writeObject(ObjectOutputStream s) throws IOException { // user's code. // private void initDeserializedWindow() { - setWarningString(); inputContextLock = new Object(); // Deserialized Windows are not yet visible. @@ -3629,7 +3603,6 @@ public float getOpacity() { * * @since 1.7 */ - @SuppressWarnings("deprecation") public void setOpacity(float opacity) { synchronized (getTreeLock()) { if (opacity < 0.0f || opacity > 1.0f) { diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java index b4e71b3c839..729d8123a24 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java @@ -48,8 +48,6 @@ import java.io.OutputStream; import java.io.Serial; import java.io.Serializable; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Objects; import java.util.StringTokenizer; @@ -1341,13 +1339,8 @@ private static File getProfileFile(String fileName) { * fileName. If there is no built-in profile with such name, then the method * returns {@code null}. */ - @SuppressWarnings("removal") private static InputStream getStandardProfileInputStream(String fileName) { - return AccessController.doPrivileged( - (PrivilegedAction) () -> { - return PCMM.class.getResourceAsStream("profiles/" + fileName); - }, null, new FilePermission("<>", "read"), - new RuntimePermission("accessSystemModules")); + return PCMM.class.getResourceAsStream("profiles/" + fileName); } /** diff --git a/src/java.desktop/share/classes/java/awt/dnd/DragSource.java b/src/java.desktop/share/classes/java/awt/dnd/DragSource.java index 01945662e46..b5da544c46d 100644 --- a/src/java.desktop/share/classes/java/awt/dnd/DragSource.java +++ b/src/java.desktop/share/classes/java/awt/dnd/DragSource.java @@ -40,13 +40,11 @@ import java.io.ObjectOutputStream; import java.io.Serial; import java.io.Serializable; -import java.security.AccessController; import java.util.EventListener; import sun.awt.AWTAccessor; import sun.awt.AWTAccessor.DragSourceContextAccessor; import sun.awt.dnd.SunDragSourceContextPeer; -import sun.security.action.GetIntegerAction; /** * The {@code DragSource} is the entity responsible @@ -907,9 +905,7 @@ private void readObject(ObjectInputStream s) * @since 1.5 */ public static int getDragThreshold() { - @SuppressWarnings("removal") - int ts = AccessController.doPrivileged( - new GetIntegerAction("awt.dnd.drag.threshold", 0)).intValue(); + int ts = Integer.getInteger("awt.dnd.drag.threshold", 0); if (ts > 0) { return ts; } else { diff --git a/src/java.desktop/share/classes/java/awt/event/FocusEvent.java b/src/java.desktop/share/classes/java/awt/event/FocusEvent.java index 4fb9043e5b7..27da2e8b4bb 100644 --- a/src/java.desktop/share/classes/java/awt/event/FocusEvent.java +++ b/src/java.desktop/share/classes/java/awt/event/FocusEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -391,7 +391,6 @@ public final Cause getCause() { * @since 9 */ @Serial - @SuppressWarnings("serial") Object readResolve() throws ObjectStreamException { if (cause != null) { return this; diff --git a/src/java.desktop/share/classes/java/awt/event/NativeLibLoader.java b/src/java.desktop/share/classes/java/awt/event/NativeLibLoader.java index 27a2c439747..8b0d46d05e0 100644 --- a/src/java.desktop/share/classes/java/awt/event/NativeLibLoader.java +++ b/src/java.desktop/share/classes/java/awt/event/NativeLibLoader.java @@ -52,14 +52,8 @@ class NativeLibLoader { * For now, we know it's done by the implementation, and we assume * that the name of the library is "awt". -br. */ - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") static void loadLibraries() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); } } diff --git a/src/java.desktop/share/classes/java/awt/image/BufferedImage.java b/src/java.desktop/share/classes/java/awt/image/BufferedImage.java index cfbebd68710..09c96a6560f 100644 --- a/src/java.desktop/share/classes/java/awt/image/BufferedImage.java +++ b/src/java.desktop/share/classes/java/awt/image/BufferedImage.java @@ -31,8 +31,6 @@ import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Hashtable; import java.util.Set; import java.util.Vector; @@ -800,26 +798,16 @@ else if (offs[3] == 0 && ccm.hasAlpha()) { } // else if ((raster instanceof ByteComponentRaster) && } - @SuppressWarnings("removal") private static boolean isStandard(ColorModel cm, WritableRaster wr) { final Class cmClass = cm.getClass(); final Class wrClass = wr.getClass(); final Class smClass = wr.getSampleModel().getClass(); - final PrivilegedAction checkClassLoadersAction = - new PrivilegedAction() - { - - @Override - public Boolean run() { - final ClassLoader std = System.class.getClassLoader(); + final ClassLoader std = System.class.getClassLoader(); - return (cmClass.getClassLoader() == std) && - (smClass.getClassLoader() == std) && - (wrClass.getClassLoader() == std); - } - }; - return AccessController.doPrivileged(checkClassLoadersAction); + return (cmClass.getClassLoader() == std) && + (smClass.getClassLoader() == std) && + (wrClass.getClassLoader() == std); } /** diff --git a/src/java.desktop/share/classes/java/awt/image/ColorModel.java b/src/java.desktop/share/classes/java/awt/image/ColorModel.java index a0aa8fddc10..b2d568cb09f 100644 --- a/src/java.desktop/share/classes/java/awt/image/ColorModel.java +++ b/src/java.desktop/share/classes/java/awt/image/ColorModel.java @@ -202,16 +202,10 @@ public abstract class ColorModel implements Transparency{ * that the name of the library is "awt". -br. */ private static boolean loaded = false; - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") static void loadLibraries() { if (!loaded) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); loaded = true; } } diff --git a/src/java.desktop/share/classes/java/beans/Beans.java b/src/java.desktop/share/classes/java/beans/Beans.java index 247f6982471..e35a751a42e 100644 --- a/src/java.desktop/share/classes/java/beans/Beans.java +++ b/src/java.desktop/share/classes/java/beans/Beans.java @@ -105,7 +105,7 @@ public static Object instantiate(ClassLoader cls, String beanName) throws IOExce * @deprecated this method will be removed when java.beans.beancontext is removed */ @Deprecated(since = "23", forRemoval = true) - @SuppressWarnings({"deprecation", "removal"}) + @SuppressWarnings("removal") public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException { diff --git a/src/java.desktop/share/classes/java/beans/EventHandler.java b/src/java.desktop/share/classes/java/beans/EventHandler.java index b3c630ae5c9..eb892f34985 100644 --- a/src/java.desktop/share/classes/java/beans/EventHandler.java +++ b/src/java.desktop/share/classes/java/beans/EventHandler.java @@ -28,9 +28,6 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; import java.lang.reflect.Method; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ReflectUtil; @@ -281,8 +278,6 @@ public class EventHandler implements InvocationHandler { private String action; private final String eventPropertyName; private final String listenerMethodName; - @SuppressWarnings("removal") - private final AccessControlContext acc = AccessController.getContext(); /** * Creates a new {@code EventHandler} object; @@ -421,20 +416,7 @@ private Object applyGetters(Object target, String getters) { * * @see EventHandler */ - @SuppressWarnings("removal") public Object invoke(final Object proxy, final Method method, final Object[] arguments) { - AccessControlContext acc = this.acc; - if ((acc == null) && (System.getSecurityManager() != null)) { - throw new SecurityException("AccessControlContext is not set"); - } - return AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - return invokeInternal(proxy, method, arguments); - } - }, acc); - } - - private Object invokeInternal(Object proxy, Method method, Object[] arguments) { String methodName = method.getName(); if (method.getDeclaringClass() == Object.class) { // Handle the Object public methods. @@ -689,7 +671,7 @@ public static T create(Class listenerInterface, * @see EventHandler * @see Proxy#newProxyInstance */ - @SuppressWarnings("removal") + @SuppressWarnings("unchecked") public static T create(Class listenerInterface, Object target, String action, String eventPropertyName, @@ -705,12 +687,7 @@ public static T create(Class listenerInterface, } final ClassLoader loader = getClassLoader(listenerInterface); final Class[] interfaces = {listenerInterface}; - return AccessController.doPrivileged(new PrivilegedAction() { - @SuppressWarnings("unchecked") - public T run() { - return (T) Proxy.newProxyInstance(loader, interfaces, handler); - } - }); + return (T) Proxy.newProxyInstance(loader, interfaces, handler); } private static ClassLoader getClassLoader(Class type) { diff --git a/src/java.desktop/share/classes/java/beans/MetaData.java b/src/java.desktop/share/classes/java/beans/MetaData.java index e3cf55a85c5..0a12e7dcee8 100644 --- a/src/java.desktop/share/classes/java/beans/MetaData.java +++ b/src/java.desktop/share/classes/java/beans/MetaData.java @@ -41,9 +41,6 @@ import java.lang.reflect.Modifier; import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; - import java.util.*; import javax.swing.Box; @@ -1319,28 +1316,22 @@ private static Object getBeanAttribute(Class type, String attribute) { } } - @SuppressWarnings("removal") static Object getPrivateFieldValue(Object instance, String name) { Field field = fields.get(name); if (field == null) { int index = name.lastIndexOf('.'); final String className = name.substring(0, index); final String fieldName = name.substring(1 + index); - field = AccessController.doPrivileged(new PrivilegedAction() { - public Field run() { - try { - Field field = Class.forName(className).getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } - catch (ClassNotFoundException exception) { - throw new IllegalStateException("Could not find class", exception); - } - catch (NoSuchFieldException exception) { - throw new IllegalStateException("Could not find field", exception); - } - } - }); + try { + field = Class.forName(className).getDeclaredField(fieldName); + field.setAccessible(true); + } + catch (ClassNotFoundException exception) { + throw new IllegalStateException("Could not find class", exception); + } + catch (NoSuchFieldException exception) { + throw new IllegalStateException("Could not find field", exception); + } fields.put(name, field); } try { diff --git a/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java b/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java index 34ca9d20403..7b6fd131c24 100644 --- a/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java +++ b/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java @@ -29,8 +29,6 @@ import java.awt.Toolkit; import java.awt.image.ImageProducer; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * This is a support class to make it easier for people to provide @@ -154,10 +152,8 @@ public Image getIcon(final int iconKind) { * @return an image object. May be null if the load failed. * @see java.beans.SimpleBeanInfo#loadImage(String) */ - @SuppressWarnings("removal") private Image loadStandardImage(final String resourceName) { - return AccessController.doPrivileged( - (PrivilegedAction) () -> loadImage(resourceName)); + return loadImage(resourceName); } /** diff --git a/src/java.desktop/share/classes/java/beans/Statement.java b/src/java.desktop/share/classes/java/beans/Statement.java index d079a0b24a9..bf1c62be78b 100644 --- a/src/java.desktop/share/classes/java/beans/Statement.java +++ b/src/java.desktop/share/classes/java/beans/Statement.java @@ -29,10 +29,6 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import com.sun.beans.finder.ClassFinder; import com.sun.beans.finder.ConstructorFinder; @@ -69,8 +65,6 @@ public void exceptionThrown(Exception e) { } }; - @SuppressWarnings("removal") - private final AccessControlContext acc = AccessController.getContext(); private final Object target; private final String methodName; private final Object[] arguments; @@ -174,28 +168,7 @@ public void execute() throws Exception { invoke(); } - @SuppressWarnings("removal") Object invoke() throws Exception { - AccessControlContext acc = this.acc; - if ((acc == null) && (System.getSecurityManager() != null)) { - throw new SecurityException("AccessControlContext is not set"); - } - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Object run() throws Exception { - return invokeInternal(); - } - }, - acc - ); - } - catch (PrivilegedActionException exception) { - throw exception.getException(); - } - } - - private Object invokeInternal() throws Exception { Object target = getTarget(); String methodName = getMethodName(); diff --git a/src/java.desktop/share/classes/java/beans/XMLDecoder.java b/src/java.desktop/share/classes/java/beans/XMLDecoder.java index 8a7e6b9984a..febba84d2a1 100644 --- a/src/java.desktop/share/classes/java/beans/XMLDecoder.java +++ b/src/java.desktop/share/classes/java/beans/XMLDecoder.java @@ -29,9 +29,6 @@ import java.io.Closeable; import java.io.InputStream; import java.io.IOException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import org.xml.sax.InputSource; import org.xml.sax.helpers.DefaultHandler; @@ -64,8 +61,6 @@ * @author Philip Milne */ public class XMLDecoder implements AutoCloseable { - @SuppressWarnings("removal") - private final AccessControlContext acc = AccessController.getContext(); private final DocumentHandler handler = new DocumentHandler(); private final InputSource input; private Object owner; @@ -189,21 +184,12 @@ private void close(Closeable in) { } } - @SuppressWarnings("removal") private boolean parsingComplete() { if (this.input == null) { return false; } if (this.array == null) { - if ((this.acc == null) && (null != System.getSecurityManager())) { - throw new SecurityException("AccessControlContext is not set"); - } - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - XMLDecoder.this.handler.parse(XMLDecoder.this.input); - return null; - } - }, this.acc); + XMLDecoder.this.handler.parse(XMLDecoder.this.input); this.array = this.handler.getObjects(); } return true; diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextChildComponentProxy.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextChildComponentProxy.java index 91d22ecce3b..9f79d1c27a9 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextChildComponentProxy.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextChildComponentProxy.java @@ -41,7 +41,6 @@ * @see java.beans.beancontext.BeanContextSupport */ -@SuppressWarnings("removal") @Deprecated(since = "23", forRemoval = true) public interface BeanContextChildComponentProxy { diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextContainerProxy.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextContainerProxy.java index 3c6e0656c50..4fe6758b21f 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextContainerProxy.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextContainerProxy.java @@ -40,7 +40,6 @@ * @see java.beans.beancontext.BeanContextSupport */ -@SuppressWarnings("removal") @Deprecated(since = "23", forRemoval = true) public interface BeanContextContainerProxy { diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java index 11fe3fff730..60c80edee35 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java @@ -35,7 +35,6 @@ * services. */ -@SuppressWarnings("removal") @Deprecated(since = "23", forRemoval = true) public interface BeanContextServiceProviderBeanInfo extends BeanInfo { diff --git a/src/java.desktop/share/classes/javax/imageio/ImageIO.java b/src/java.desktop/share/classes/javax/imageio/ImageIO.java index b11641c82ca..316a74a22ea 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageIO.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageIO.java @@ -165,10 +165,8 @@ private static synchronized CacheInfo getCacheInfo() { * Returns the default temporary (cache) directory as defined by the * java.io.tmpdir system property. */ - @SuppressWarnings("removal") private static String getTempDir() { - GetPropertyAction a = new GetPropertyAction("java.io.tmpdir"); - return AccessController.doPrivileged(a); + return System.getProperty("java.io.tmpdir"); } /** diff --git a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java index 3954f886f47..b94d6a85a02 100644 --- a/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java +++ b/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java @@ -28,8 +28,6 @@ import org.w3c.dom.Node; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * An abstract class to be extended by objects that represent metadata @@ -398,12 +396,9 @@ public IIOMetadataFormat getMetadataFormat(String formatName) { throw new IllegalArgumentException("Unsupported format name"); } try { - final String className = formatClassName; // Try to load from the module of the IIOMetadata implementation // for this plugin since the IIOMetadataImpl is part of the plugin - PrivilegedAction> pa = () -> { return getMetadataFormatClass(className); }; - @SuppressWarnings("removal") - Class cls = AccessController.doPrivileged(pa); + Class cls = getMetadataFormatClass(formatClassName); Method meth = cls.getMethod("getInstance"); return (IIOMetadataFormat) meth.invoke(null); } catch (Exception e) { diff --git a/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java b/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java index b80e6370293..1ea7146ae4a 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java @@ -25,8 +25,6 @@ package javax.imageio.spi; -import java.security.PrivilegedAction; -import java.security.AccessController; import java.util.Iterator; import com.sun.imageio.spi.FileImageInputStreamSpi; import com.sun.imageio.spi.FileImageOutputStreamSpi; @@ -197,30 +195,14 @@ public void registerApplicationClasspathSpis() { } } - @SuppressWarnings("removal") private void registerInstalledProviders() { - /* - We need to load installed providers - in the privileged mode in order to - be able read corresponding jar files even if - file read capability is restricted (like the - applet context case). - */ - PrivilegedAction doRegistration = - new PrivilegedAction() { - public Object run() { - Iterator> categories = getCategories(); - while (categories.hasNext()) { - @SuppressWarnings("unchecked") - Class c = (Class)categories.next(); - for (IIOServiceProvider p : ServiceLoader.loadInstalled(c)) { - registerServiceProvider(p); - } - } - return this; - } - }; - - AccessController.doPrivileged(doRegistration); + Iterator> categories = getCategories(); + while (categories.hasNext()) { + @SuppressWarnings("unchecked") + Class c = (Class)categories.next(); + for (IIOServiceProvider p : ServiceLoader.loadInstalled(c)) { + registerServiceProvider(p); + } + } } } diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java b/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java index 7abefdd9431..f74415a8a38 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java @@ -26,8 +26,6 @@ package javax.imageio.spi; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; @@ -584,10 +582,7 @@ private IIOMetadataFormat getMetadataFormat(String formatName, } try { // Try to load from the same location as the module of the SPI - final String className = formatClassName; - PrivilegedAction> pa = () -> { return getMetadataFormatClass(className); }; - @SuppressWarnings("removal") - Class cls = AccessController.doPrivileged(pa); + Class cls = getMetadataFormatClass(formatClassName); Method meth = cls.getMethod("getInstance"); return (IIOMetadataFormat) meth.invoke(null); } catch (Exception e) { diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java index 3e0bc06b361..0ba532b0b83 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java @@ -25,9 +25,6 @@ package javax.imageio.spi; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -731,8 +728,6 @@ class SubRegistry { // No way to express heterogeneous map, we want // Map, T>, where T is ? final Map, Object> map = new HashMap<>(); - @SuppressWarnings("removal") - final Map, AccessControlContext> accMap = new HashMap<>(); public SubRegistry(ServiceRegistry registry, Class category) { this.registry = registry; @@ -748,7 +743,6 @@ public synchronized boolean registerServiceProvider(Object provider) { deregisterServiceProvider(oprovider); } map.put(provider.getClass(), provider); - accMap.put(provider.getClass(), AccessController.getContext()); poset.add(provider); if (provider instanceof RegisterableService) { RegisterableService rs = (RegisterableService)provider; @@ -773,7 +767,6 @@ public synchronized boolean deregisterServiceProvider(Object provider) { if (provider == oprovider) { map.remove(provider.getClass()); - accMap.remove(provider.getClass()); poset.remove(provider); if (provider instanceof RegisterableService) { RegisterableService rs = (RegisterableService)provider; @@ -815,26 +808,17 @@ public synchronized boolean unsetOrdering(Object firstProvider, return (T)map.get(providerClass); } - @SuppressWarnings("removal") public synchronized void clear() { Iterator iter = map.values().iterator(); while (iter.hasNext()) { Object provider = iter.next(); iter.remove(); - if (provider instanceof RegisterableService) { - RegisterableService rs = (RegisterableService)provider; - AccessControlContext acc = accMap.get(provider.getClass()); - if (acc != null || System.getSecurityManager() == null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - rs.onDeregistration(registry, category); - return null; - }, acc); - } + if (provider instanceof RegisterableService rs) { + rs.onDeregistration(registry, category); } } poset.clear(); - accMap.clear(); } @SuppressWarnings("removal") diff --git a/src/java.desktop/share/classes/javax/print/DocFlavor.java b/src/java.desktop/share/classes/javax/print/DocFlavor.java index 448cc78d9e1..9db970cc779 100644 --- a/src/java.desktop/share/classes/javax/print/DocFlavor.java +++ b/src/java.desktop/share/classes/javax/print/DocFlavor.java @@ -410,10 +410,7 @@ public class DocFlavor implements Serializable, Cloneable { * @spec https://www.rfc-editor.org/info/rfc2278 * RFC 2278: IANA Charset Registration Procedures */ - @SuppressWarnings("removal") - public static final String hostEncoding = - java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("file.encoding")); + public static final String hostEncoding = System.getProperty("file.encoding"); /** * MIME type. diff --git a/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java b/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java index 2931a1cbae0..29c7b420f7c 100644 --- a/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java +++ b/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java @@ -335,7 +335,6 @@ public abstract PrintService[] getPrintServices(DocFlavor flavor, * * @return all lookup services for this environment */ - @SuppressWarnings("removal") private static ArrayList getAllLookupServices() { synchronized (PrintServiceLookup.class) { ArrayList listOfLookupServices = getListOfLookupServices(); @@ -344,32 +343,11 @@ private static ArrayList getAllLookupServices() { } else { listOfLookupServices = initListOfLookupServices(); } - try { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() { - Iterator iterator = - ServiceLoader.load(PrintServiceLookup.class). - iterator(); - ArrayList los = getListOfLookupServices(); - while (iterator.hasNext()) { - try { - los.add(iterator.next()); - } catch (ServiceConfigurationError err) { - /* In the applet case, we continue */ - if (System.getSecurityManager() != null) { - err.printStackTrace(); - } else { - throw err; - } - } - } - return null; - } - }); - } catch (java.security.PrivilegedActionException e) { + Iterator iterator = ServiceLoader.load(PrintServiceLookup.class).iterator(); + ArrayList los = getListOfLookupServices(); + while (iterator.hasNext()) { + los.add(iterator.next()); } - return listOfLookupServices; } } diff --git a/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java b/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java index 29033cb7147..5247d4ef861 100644 --- a/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java +++ b/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java @@ -183,43 +183,23 @@ private static ArrayList initListOfFactories() { * * @return all factories */ - @SuppressWarnings("removal") private static ArrayList getAllFactories() { synchronized (StreamPrintServiceFactory.class) { - ArrayList listOfFactories = getListOfFactories(); - if (listOfFactories != null) { - return listOfFactories; - } else { - listOfFactories = initListOfFactories(); - } + ArrayList listOfFactories = getListOfFactories(); + if (listOfFactories != null) { + return listOfFactories; + } else { + listOfFactories = initListOfFactories(); + } - try { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() { - Iterator iterator = - ServiceLoader.load - (StreamPrintServiceFactory.class).iterator(); - ArrayList lof = getListOfFactories(); - while (iterator.hasNext()) { - try { - lof.add(iterator.next()); - } catch (ServiceConfigurationError err) { - /* In the applet case, we continue */ - if (System.getSecurityManager() != null) { - err.printStackTrace(); - } else { - throw err; - } - } - } - return null; - } - }); - } catch (java.security.PrivilegedActionException e) { - } - return listOfFactories; + Iterator iterator = + ServiceLoader.load(StreamPrintServiceFactory.class).iterator(); + ArrayList lof = getListOfFactories(); + while (iterator.hasNext()) { + lof.add(iterator.next()); + } + return listOfFactories; } } diff --git a/src/java.desktop/share/classes/javax/swing/AbstractAction.java b/src/java.desktop/share/classes/javax/swing/AbstractAction.java index 6a22a985d69..2bf40e810c6 100644 --- a/src/java.desktop/share/classes/javax/swing/AbstractAction.java +++ b/src/java.desktop/share/classes/javax/swing/AbstractAction.java @@ -32,12 +32,9 @@ import java.io.ObjectOutputStream; import java.io.Serial; import java.io.Serializable; -import java.security.AccessController; import javax.swing.event.SwingPropertyChangeSupport; -import sun.security.action.GetPropertyAction; - /** * This class provides default implementations for the JFC Action * interface. Standard behaviors like the get and set methods for @@ -81,14 +78,11 @@ public abstract class AbstractAction implements Action, Cloneable, Serializable * Whether or not to reconfigure all action properties from the * specified event. */ - @SuppressWarnings("removal") static boolean shouldReconfigure(PropertyChangeEvent e) { if (e.getPropertyName() == null) { synchronized(AbstractAction.class) { if (RECONFIGURE_ON_NULL == null) { - RECONFIGURE_ON_NULL = Boolean.valueOf( - AccessController.doPrivileged(new GetPropertyAction( - "swing.actions.reconfigureOnNull", "false"))); + RECONFIGURE_ON_NULL = Boolean.getBoolean("swing.actions.reconfigureOnNull"); } return RECONFIGURE_ON_NULL; } diff --git a/src/java.desktop/share/classes/javax/swing/DebugGraphics.java b/src/java.desktop/share/classes/javax/swing/DebugGraphics.java index 9a9a4fbe70f..1d6c52c4680 100644 --- a/src/java.desktop/share/classes/javax/swing/DebugGraphics.java +++ b/src/java.desktop/share/classes/javax/swing/DebugGraphics.java @@ -27,8 +27,6 @@ import java.awt.*; import java.awt.image.*; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.text.AttributedCharacterIterator; /** @@ -79,7 +77,6 @@ public class DebugGraphics extends Graphics { * applications, it is for internal use only. When called directly * it will create an un-usable instance. */ - @SuppressWarnings("removal") public DebugGraphics() { super(); buffer = null; @@ -87,14 +84,7 @@ public DebugGraphics() { // Creates a Graphics context when the constructor is called. if (this.graphics == null) { - StackWalker walker = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public StackWalker run() { - StackWalker stackwalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); - return stackwalker; - } - }); - + StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); if (walker.getCallerClass() != this.getClass()) { BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); this.graphics = bi.createGraphics(); diff --git a/src/java.desktop/share/classes/javax/swing/DefaultFocusManager.java b/src/java.desktop/share/classes/javax/swing/DefaultFocusManager.java index 4413721097d..47cca584452 100644 --- a/src/java.desktop/share/classes/javax/swing/DefaultFocusManager.java +++ b/src/java.desktop/share/classes/javax/swing/DefaultFocusManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -47,7 +47,6 @@ * @author David Mendenhall * @since 1.2 */ -@SuppressWarnings("serial") // Obsolete class public class DefaultFocusManager extends FocusManager { final FocusTraversalPolicy gluePolicy = diff --git a/src/java.desktop/share/classes/javax/swing/ImageIcon.java b/src/java.desktop/share/classes/javax/swing/ImageIcon.java index 2eeac8961bc..2bae31ba31f 100644 --- a/src/java.desktop/share/classes/javax/swing/ImageIcon.java +++ b/src/java.desktop/share/classes/javax/swing/ImageIcon.java @@ -44,10 +44,6 @@ import java.io.Serial; import java.io.Serializable; import java.net.URL; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; import java.util.Locale; import javax.accessibility.Accessible; @@ -105,27 +101,19 @@ public class ImageIcon implements Icon, Serializable, Accessible { * It is left for backward compatibility only. * @deprecated since 1.8 */ - @SuppressWarnings("removal") @Deprecated - protected static final Component component - = AccessController.doPrivileged(new PrivilegedAction() { - public Component run() { - try { - final Component component = createNoPermsComponent(); - - // 6482575 - clear the appContext field so as not to leak it - AWTAccessor.getComponentAccessor(). - setAppContext(component, null); - - return component; - } catch (Throwable e) { - // We don't care about component. - // So don't prevent class initialisation. - e.printStackTrace(); - return null; - } + protected static final Component component = createComponent(); + + private static final Component createComponent() { + try { + Component component = new Component() {}; + // 6482575 - clear the appContext field so as not to leak it + AWTAccessor.getComponentAccessor().setAppContext(component, null); + return component; + } catch (Throwable t) { + return null; } - }); + } /** * Do not use this shared media tracker, which is used to load images. @@ -135,23 +123,6 @@ public Component run() { @Deprecated protected static final MediaTracker tracker = new MediaTracker(component); - @SuppressWarnings("removal") - private static Component createNoPermsComponent() { - // 7020198 - set acc field to no permissions and no subject - // Note, will have appContext set. - return AccessController.doPrivileged( - new PrivilegedAction() { - public Component run() { - return new Component() { - }; - } - }, - new AccessControlContext(new ProtectionDomain[]{ - new ProtectionDomain(null, null) - }) - ); - } - /** * Id used in loading images from MediaTracker. */ diff --git a/src/java.desktop/share/classes/javax/swing/JColorChooser.java b/src/java.desktop/share/classes/javax/swing/JColorChooser.java index 62c4fe8b083..89291be5f04 100644 --- a/src/java.desktop/share/classes/javax/swing/JColorChooser.java +++ b/src/java.desktop/share/classes/javax/swing/JColorChooser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -714,7 +714,6 @@ public void actionPerformed(ActionEvent e) { cancelButton.getAccessibleContext().setAccessibleDescription(cancelString); // The following few lines are used to register esc to close the dialog - @SuppressWarnings("serial") // anonymous class Action cancelKeyAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { ((AbstractButton)e.getSource()).fireActionPerformed(e); diff --git a/src/java.desktop/share/classes/javax/swing/JComponent.java b/src/java.desktop/share/classes/javax/swing/JComponent.java index 352fefeaacb..92f3f01ab3e 100644 --- a/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/src/java.desktop/share/classes/javax/swing/JComponent.java @@ -2949,7 +2949,7 @@ protected void processKeyEvent(KeyEvent e) { * * @since 1.3 */ - @SuppressWarnings({"deprecation", "removal"}) + @SuppressWarnings("deprecation") protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { InputMap map = getInputMap(condition, false); diff --git a/src/java.desktop/share/classes/javax/swing/JLayer.java b/src/java.desktop/share/classes/javax/swing/JLayer.java index c2076299e44..7ce28b2b723 100644 --- a/src/java.desktop/share/classes/javax/swing/JLayer.java +++ b/src/java.desktop/share/classes/javax/swing/JLayer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,6 @@ import java.io.ObjectInputStream; import java.io.Serial; import java.util.ArrayList; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * {@code JLayer} is a universal decorator for Swing components @@ -737,7 +735,6 @@ public void doLayout() { * * @return the AccessibleContext associated with this {@code JLayer}. */ - @SuppressWarnings("serial") // anonymous class public AccessibleContext getAccessibleContext() { if (accessibleContext == null) { accessibleContext = new AccessibleJComponent() { @@ -816,27 +813,14 @@ private long getCurrentEventMask() { return currentEventMask; } - @SuppressWarnings("removal") private void addAWTEventListener(final long eventMask) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - Toolkit.getDefaultToolkit(). - addAWTEventListener(LayerEventController.this, eventMask); - return null; - } - }); - + Toolkit.getDefaultToolkit(). + addAWTEventListener(LayerEventController.this, eventMask); } - @SuppressWarnings("removal") private void removeAWTEventListener() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - Toolkit.getDefaultToolkit(). - removeAWTEventListener(LayerEventController.this); - return null; - } - }); + Toolkit.getDefaultToolkit(). + removeAWTEventListener(LayerEventController.this); } private boolean isEventEnabled(long eventMask, int id) { diff --git a/src/java.desktop/share/classes/javax/swing/JPopupMenu.java b/src/java.desktop/share/classes/javax/swing/JPopupMenu.java index 29cc59b1bb1..d1fff6a11e0 100644 --- a/src/java.desktop/share/classes/javax/swing/JPopupMenu.java +++ b/src/java.desktop/share/classes/javax/swing/JPopupMenu.java @@ -119,11 +119,8 @@ public class JPopupMenu extends JComponent implements Accessible,MenuElement { new StringBuffer("JPopupMenu.defaultLWPopupEnabledKey"); /** Bug#4425878-Property javax.swing.adjustPopupLocationToFit introduced */ - @SuppressWarnings("removal") static boolean popupPositionFixDisabled = - java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "javax.swing.adjustPopupLocationToFit","")).equals("false"); + System.getProperty("javax.swing.adjustPopupLocationToFit","").equals("false"); transient Component invoker; transient Popup popup; diff --git a/src/java.desktop/share/classes/javax/swing/JRootPane.java b/src/java.desktop/share/classes/javax/swing/JRootPane.java index 0e2668b363a..44eb41248e6 100644 --- a/src/java.desktop/share/classes/javax/swing/JRootPane.java +++ b/src/java.desktop/share/classes/javax/swing/JRootPane.java @@ -26,13 +26,10 @@ import java.awt.*; import java.beans.*; -import java.security.AccessController; import javax.accessibility.*; import javax.swing.plaf.RootPaneUI; import java.io.Serializable; -import sun.security.action.GetBooleanAction; - /** * A lightweight container used behind the scenes by @@ -202,19 +199,15 @@ public class JRootPane extends JComponent implements Accessible { * Whether or not we should dump the stack when true double buffering * is disabled. Default is false. */ - @SuppressWarnings("removal") private static final boolean LOG_DISABLE_TRUE_DOUBLE_BUFFERING - = AccessController.doPrivileged(new GetBooleanAction( - "swing.logDoubleBufferingDisable")); + = Boolean.getBoolean("swing.logDoubleBufferingDisable"); /** * Whether or not we should ignore requests to disable true double * buffering. Default is false. */ - @SuppressWarnings("removal") private static final boolean IGNORE_DISABLE_TRUE_DOUBLE_BUFFERING - = AccessController.doPrivileged(new GetBooleanAction( - "swing.ignoreDoubleBufferingDisable")); + = Boolean.getBoolean("swing.ignoreDoubleBufferingDisable"); /** * Constant used for the windowDecorationStyle property. Indicates that diff --git a/src/java.desktop/share/classes/javax/swing/KeyStroke.java b/src/java.desktop/share/classes/javax/swing/KeyStroke.java index dcd87c74535..054d1ad72bb 100644 --- a/src/java.desktop/share/classes/javax/swing/KeyStroke.java +++ b/src/java.desktop/share/classes/javax/swing/KeyStroke.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,6 @@ * @author David Mendenhall * @since 1.2 */ -@SuppressWarnings("serial") // Same-version serialization only public class KeyStroke extends AWTKeyStroke { /** diff --git a/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/src/java.desktop/share/classes/javax/swing/RepaintManager.java index eb696a7b489..4799472d44f 100644 --- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java +++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java @@ -28,21 +28,15 @@ import java.awt.*; import java.awt.event.*; import java.awt.image.VolatileImage; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.applet.*; -import jdk.internal.access.JavaSecurityAccess; -import jdk.internal.access.SharedSecrets; import sun.awt.AWTAccessor; import sun.awt.AppContext; import sun.awt.DisplayChangedListener; import sun.awt.SunToolkit; import sun.java2d.SunGraphicsEnvironment; -import sun.security.action.GetPropertyAction; import com.sun.java.swing.SwingUtilities3; import java.awt.geom.AffineTransform; @@ -188,9 +182,6 @@ public class RepaintManager */ private final ProcessingRunnable processingRunnable; - private static final JavaSecurityAccess javaSecurityAccess = - SharedSecrets.getJavaSecurityAccess(); - /** * Listener installed to detect display changes. When display changes, * schedules a callback to notify all RepaintManagers of the display @@ -211,22 +202,13 @@ public void removeRepaintListener(RepaintManager rm, RepaintListener l) { } }); - @SuppressWarnings("removal") - var t1 = "true".equals(AccessController. - doPrivileged(new GetPropertyAction( - "swing.volatileImageBufferEnabled", "true"))); - volatileImageBufferEnabled = t1; + volatileImageBufferEnabled = "true".equals(System.getProperty("swing.volatileImageBufferEnabled", "true")); boolean headless = GraphicsEnvironment.isHeadless(); if (volatileImageBufferEnabled && headless) { volatileImageBufferEnabled = false; } - @SuppressWarnings("removal") - var t2 = "true".equals(AccessController.doPrivileged( - new GetPropertyAction("awt.nativeDoubleBuffering"))); - nativeDoubleBuffering = t2; - @SuppressWarnings("removal") - String bs = AccessController.doPrivileged( - new GetPropertyAction("swing.bufferPerWindow")); + nativeDoubleBuffering = "true".equals(System.getProperty("awt.nativeDoubleBuffering")); + String bs = System.getProperty("swing.bufferPerWindow"); if (headless) { BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF; } @@ -239,10 +221,7 @@ else if ("true".equals(bs)) { else { BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF; } - @SuppressWarnings("removal") - var t3 = "true".equals(AccessController.doPrivileged( - new GetPropertyAction("swing.handleTopLevelPaint", "true"))); - HANDLE_TOP_LEVEL_PAINT = t3; + HANDLE_TOP_LEVEL_PAINT = "true".equals(System.getProperty("swing.handleTopLevelPaint", "true")); GraphicsEnvironment ge = GraphicsEnvironment. getLocalGraphicsEnvironment(); if (ge instanceof SunGraphicsEnvironment) { @@ -611,21 +590,7 @@ void nativeQueueSurfaceDataRunnable(AppContext appContext, if (runnableList == null) { runnableList = new LinkedList(); } - runnableList.add(new Runnable() { - public void run() { - @SuppressWarnings("removal") - AccessControlContext stack = AccessController.getContext(); - @SuppressWarnings("removal") - AccessControlContext acc = - AWTAccessor.getComponentAccessor().getAccessControlContext(c); - javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { - public Void run() { - r.run(); - return null; - } - }, stack, acc); - } - }); + runnableList.add(r); } scheduleProcessingRunnable(appContext); } @@ -746,18 +711,7 @@ public void validateInvalidComponents() { int n = ic.size(); for(int i = 0; i < n; i++) { final Component c = ic.get(i); - @SuppressWarnings("removal") - AccessControlContext stack = AccessController.getContext(); - @SuppressWarnings("removal") - AccessControlContext acc = - AWTAccessor.getComponentAccessor().getAccessControlContext(c); - javaSecurityAccess.doIntersectionPrivilege( - new PrivilegedAction() { - public Void run() { - c.validate(); - return null; - } - }, stack, acc); + c.validate(); } } @@ -853,61 +807,50 @@ private void paintDirtyRegions( for (int j=0 ; j < count.get(); j++) { final int i = j; final Component dirtyComponent = roots.get(j); - @SuppressWarnings("removal") - AccessControlContext stack = AccessController.getContext(); - @SuppressWarnings("removal") - AccessControlContext acc = - AWTAccessor.getComponentAccessor().getAccessControlContext(dirtyComponent); - javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { - public Void run() { - Rectangle rect = tmpDirtyComponents.get(dirtyComponent); - // Sometimes when RepaintManager is changed during the painting - // we may get null here, see #6995769 for details - if (rect == null) { - return null; - } + Rectangle rect = tmpDirtyComponents.get(dirtyComponent); + // Sometimes when RepaintManager is changed during the painting + // we may get null here, see #6995769 for details + if (rect == null) { + continue; + } - int localBoundsH = dirtyComponent.getHeight(); - int localBoundsW = dirtyComponent.getWidth(); - SwingUtilities.computeIntersection(0, - 0, - localBoundsW, - localBoundsH, - rect); - if (dirtyComponent instanceof JComponent) { - ((JComponent)dirtyComponent).paintImmediately( - rect.x,rect.y,rect.width, rect.height); - } - else if (dirtyComponent.isShowing()) { - Graphics g = JComponent.safelyGetGraphics( - dirtyComponent, dirtyComponent); - // If the Graphics goes away, it means someone disposed of - // the window, don't do anything. - if (g != null) { - g.setClip(rect.x, rect.y, rect.width, rect.height); - try { - dirtyComponent.paint(g); - } finally { - g.dispose(); - } - } - } - // If the repaintRoot has been set, service it now and - // remove any components that are children of repaintRoot. - if (repaintRoot != null) { - adjustRoots(repaintRoot, roots, i + 1); - count.set(roots.size()); - paintManager.isRepaintingRoot = true; - repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(), - repaintRoot.getHeight()); - paintManager.isRepaintingRoot = false; - // Only service repaintRoot once. - repaintRoot = null; + int localBoundsH = dirtyComponent.getHeight(); + int localBoundsW = dirtyComponent.getWidth(); + SwingUtilities.computeIntersection(0, + 0, + localBoundsW, + localBoundsH, + rect); + if (dirtyComponent instanceof JComponent) { + ((JComponent)dirtyComponent).paintImmediately( + rect.x,rect.y,rect.width, rect.height); + } + else if (dirtyComponent.isShowing()) { + Graphics g = JComponent.safelyGetGraphics( + dirtyComponent, dirtyComponent); + // If the Graphics goes away, it means someone disposed of + // the window, don't do anything. + if (g != null) { + g.setClip(rect.x, rect.y, rect.width, rect.height); + try { + dirtyComponent.paint(g); + } finally { + g.dispose(); } - - return null; } - }, stack, acc); + } + // If the repaintRoot has been set, service it now and + // remove any components that are children of repaintRoot. + if (repaintRoot != null) { + adjustRoots(repaintRoot, roots, i + 1); + count.set(roots.size()); + paintManager.isRepaintingRoot = true; + repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(), + repaintRoot.getHeight()); + paintManager.isRepaintingRoot = false; + // Only service repaintRoot once. + repaintRoot = null; + } } } finally { painting = false; diff --git a/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java b/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java index 92f98fdfc99..ab306187e32 100644 --- a/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java +++ b/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java @@ -29,8 +29,6 @@ import java.util.*; import java.awt.FocusTraversalPolicy; import sun.util.logging.PlatformLogger; -import sun.security.action.GetPropertyAction; -import java.security.AccessController; /** * A FocusTraversalPolicy that determines traversal order by sorting the @@ -95,10 +93,8 @@ public class SortingFocusTraversalPolicy * When false, the default (tim-sort) algo is used, which may lead to an exception. * See: JDK-8048887 */ - @SuppressWarnings("removal") private static final boolean legacySortingFTPEnabled = "true".equals( - AccessController.doPrivileged( - new GetPropertyAction("swing.legacySortingFTPEnabled", "true"))); + System.getProperty("swing.legacySortingFTPEnabled", "true")); /** * Constructs a SortingFocusTraversalPolicy without a Comparator. diff --git a/src/java.desktop/share/classes/javax/swing/Spring.java b/src/java.desktop/share/classes/javax/swing/Spring.java index 751eef76435..cf4504f51f9 100644 --- a/src/java.desktop/share/classes/javax/swing/Spring.java +++ b/src/java.desktop/share/classes/javax/swing/Spring.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -127,7 +127,6 @@ * @author Philip Milne * @since 1.4 */ -@SuppressWarnings("serial") // Same-version serialization only public abstract class Spring { /** diff --git a/src/java.desktop/share/classes/javax/swing/SpringLayout.java b/src/java.desktop/share/classes/javax/swing/SpringLayout.java index 27641690e22..76050d31ce3 100644 --- a/src/java.desktop/share/classes/javax/swing/SpringLayout.java +++ b/src/java.desktop/share/classes/javax/swing/SpringLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -184,7 +184,6 @@ * @author Joe Winchester * @since 1.4 */ -@SuppressWarnings("serial") // Same-version serialization only public class SpringLayout implements LayoutManager2 { private Map componentConstraints = new HashMap(); diff --git a/src/java.desktop/share/classes/javax/swing/SwingPaintEventDispatcher.java b/src/java.desktop/share/classes/javax/swing/SwingPaintEventDispatcher.java index d0e34256ed4..1cabf129db1 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingPaintEventDispatcher.java +++ b/src/java.desktop/share/classes/javax/swing/SwingPaintEventDispatcher.java @@ -28,12 +28,9 @@ import java.awt.Container; import java.awt.Rectangle; import java.awt.event.PaintEvent; -import java.security.AccessController; import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.event.IgnorePaintEvent; -import sun.security.action.GetBooleanAction; -import sun.security.action.GetPropertyAction; /** * Swing's PaintEventDispatcher. If the component specified by the PaintEvent @@ -41,16 +38,15 @@ * will forward the request to the RepaintManager for eventual painting. * */ -@SuppressWarnings("removal") class SwingPaintEventDispatcher extends sun.awt.PaintEventDispatcher { private static final boolean SHOW_FROM_DOUBLE_BUFFER; private static final boolean ERASE_BACKGROUND; static { - SHOW_FROM_DOUBLE_BUFFER = "true".equals(AccessController.doPrivileged( - new GetPropertyAction("swing.showFromDoubleBuffer", "true"))); - ERASE_BACKGROUND = AccessController.doPrivileged( - new GetBooleanAction("swing.nativeErase")); + SHOW_FROM_DOUBLE_BUFFER = + "true".equals(System.getProperty("swing.showFromDoubleBuffer", "true")); + ERASE_BACKGROUND = + "true".equals(System.getProperty("swing.swing.nativeErase", "false")); } public PaintEvent createPaintEvent(Component component, int x, int y, diff --git a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java index 40970622956..89fe8970531 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -40,8 +40,6 @@ import javax.swing.event.MenuDragMouseEvent; import javax.swing.plaf.UIResource; import javax.swing.text.View; -import java.security.AccessController; -import sun.security.action.GetPropertyAction; import sun.awt.AppContext; import sun.awt.AWTAccessor; @@ -75,12 +73,9 @@ public class SwingUtilities implements SwingConstants * Returns true if setTransferHandler should change the * DropTarget. */ - @SuppressWarnings("removal") private static boolean getSuppressDropTarget() { if (!checkedSuppressDropSupport) { - suppressDropSupport = Boolean.parseBoolean( - AccessController.doPrivileged( - new GetPropertyAction("suppressSwingDropSupport"))); + suppressDropSupport = Boolean.getBoolean("suppressSwingDropSupport"); checkedSuppressDropSupport = true; } return suppressDropSupport; diff --git a/src/java.desktop/share/classes/javax/swing/SwingWorker.java b/src/java.desktop/share/classes/javax/swing/SwingWorker.java index 4eacdfcbf50..a8f1e754aab 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingWorker.java +++ b/src/java.desktop/share/classes/javax/swing/SwingWorker.java @@ -31,8 +31,6 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; @@ -797,7 +795,6 @@ public Thread newThread(final Runnable r) { final ExecutorService es = executorService; appContext.addPropertyChangeListener(AppContext.DISPOSED_PROPERTY_NAME, new PropertyChangeListener() { - @SuppressWarnings("removal") @Override public void propertyChange(PropertyChangeEvent pce) { boolean disposed = (Boolean)pce.getNewValue(); @@ -807,14 +804,7 @@ public void propertyChange(PropertyChangeEvent pce) { final ExecutorService executorService = executorServiceRef.get(); if (executorService != null) { - AccessController.doPrivileged( - new PrivilegedAction() { - public Void run() { - executorService.shutdown(); - return null; - } - } - ); + executorService.shutdown(); } } } diff --git a/src/java.desktop/share/classes/javax/swing/Timer.java b/src/java.desktop/share/classes/javax/swing/Timer.java index 4974aee0b7c..46051d92df1 100644 --- a/src/java.desktop/share/classes/javax/swing/Timer.java +++ b/src/java.desktop/share/classes/javax/swing/Timer.java @@ -32,9 +32,6 @@ import java.io.ObjectInputStream; import java.io.Serial; import java.io.Serializable; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.EventListener; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; @@ -209,25 +206,6 @@ public Timer(int delay, ActionListener listener) { } } - /* - * The timer's AccessControlContext. - */ - @SuppressWarnings("removal") - private transient volatile AccessControlContext acc = - AccessController.getContext(); - - /** - * Returns the acc this timer was constructed with. - */ - @SuppressWarnings("removal") - final AccessControlContext getAccessControlContext() { - if (acc == null) { - throw new SecurityException( - "Timer is missing AccessControlContext"); - } - return acc; - } - /** * DoPostEvent is a runnable class that fires actionEvents to * the listeners on the EventDispatchThread, via invokeLater. @@ -609,15 +587,9 @@ void cancelEvent() { } - @SuppressWarnings("removal") void post() { - if (notify.compareAndSet(false, true) || !coalesce) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - SwingUtilities.invokeLater(doPostEvent); - return null; - } - }, getAccessControlContext()); + if (notify.compareAndSet(false, true) || !coalesce) { + SwingUtilities.invokeLater(doPostEvent); } } @@ -625,12 +597,10 @@ Lock getLock() { return lock; } - @SuppressWarnings("removal") @Serial private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { - this.acc = AccessController.getContext(); ObjectInputStream.GetField f = in.readFields(); EventListenerList newListenerList = (EventListenerList) diff --git a/src/java.desktop/share/classes/javax/swing/TimerQueue.java b/src/java.desktop/share/classes/javax/swing/TimerQueue.java index 2743baefae6..249593caa7e 100644 --- a/src/java.desktop/share/classes/javax/swing/TimerQueue.java +++ b/src/java.desktop/share/classes/javax/swing/TimerQueue.java @@ -25,8 +25,6 @@ package javax.swing; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.concurrent.*; import java.util.concurrent.locks.*; import java.util.concurrent.atomic.AtomicLong; @@ -83,7 +81,6 @@ public static TimerQueue sharedInstance() { } - @SuppressWarnings("removal") void startIfNeeded() { if (! running) { runningLock.lock(); @@ -92,15 +89,11 @@ void startIfNeeded() { } try { final ThreadGroup threadGroup = AppContext.getAppContext().getThreadGroup(); - AccessController.doPrivileged((PrivilegedAction) () -> { - String name = "TimerQueue"; - Thread timerThread = - new Thread(threadGroup, this, name, 0, false); - timerThread.setDaemon(true); - timerThread.setPriority(Thread.NORM_PRIORITY); - timerThread.start(); - return null; - }); + String name = "TimerQueue"; + Thread timerThread = new Thread(threadGroup, this, name, 0, false); + timerThread.setDaemon(true); + timerThread.setPriority(Thread.NORM_PRIORITY); + timerThread.start(); running = true; } finally { runningLock.unlock(); diff --git a/src/java.desktop/share/classes/javax/swing/UIDefaults.java b/src/java.desktop/share/classes/javax/swing/UIDefaults.java index 97f061fdb3d..62939b90e70 100644 --- a/src/java.desktop/share/classes/javax/swing/UIDefaults.java +++ b/src/java.desktop/share/classes/javax/swing/UIDefaults.java @@ -51,7 +51,6 @@ import java.beans.PropertyChangeListener; import java.security.AccessController; import java.security.AccessControlContext; -import java.security.PrivilegedAction; import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ReflectUtil; @@ -341,25 +340,19 @@ private Map getResourceCache(Locale l) { * Test if the specified baseName of the ROOT locale is in java.desktop module. * JDK always defines the resource bundle of the ROOT locale. */ - @SuppressWarnings("removal") private static boolean isDesktopResourceBundle(String baseName) { Module thisModule = UIDefaults.class.getModule(); - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Boolean run() { - Class c = Class.forName(thisModule, baseName); - if (c != null) { - return true; - } else { - String resourceName = baseName.replace('.', '/') + ".properties"; - try (InputStream in = thisModule.getResourceAsStream(resourceName)) { - return in != null; - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } + Class c = Class.forName(thisModule, baseName); + if (c != null) { + return true; + } else { + String resourceName = baseName.replace('.', '/') + ".properties"; + try (InputStream in = thisModule.getResourceAsStream(resourceName)) { + return in != null; + } catch (IOException e) { + throw new UncheckedIOException(e); } - }); + } } /** @@ -1141,52 +1134,41 @@ public ProxyLazyValue(String c, String m, Object[] o) { * @param table a UIDefaults table * @return the created Object */ - @SuppressWarnings("removal") public Object createValue(final UIDefaults table) { - // In order to pick up the security policy in effect at the - // time of creation we use a doPrivileged with the - // AccessControlContext that was in place when this was created. - if (acc == null && System.getSecurityManager() != null) { - throw new SecurityException("null AccessControlContext"); - } - return AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - try { - Class c; - Object cl; - // See if we should use a separate ClassLoader - if (table == null || !((cl = table.get("ClassLoader")) - instanceof ClassLoader)) { - cl = Thread.currentThread(). - getContextClassLoader(); - if (cl == null) { - // Fallback to the system class loader. - cl = ClassLoader.getSystemClassLoader(); - } - } - ReflectUtil.checkPackageAccess(className); - c = Class.forName(className, true, (ClassLoader)cl); - SwingUtilities2.checkAccess(c.getModifiers()); - if (methodName != null) { - Class[] types = getClassArray(args); - Method m = c.getMethod(methodName, types); - return MethodUtil.invoke(m, c, args); - } else { - Class[] types = getClassArray(args); - Constructor constructor = c.getConstructor(types); - SwingUtilities2.checkAccess(constructor.getModifiers()); - return constructor.newInstance(args); - } - } catch(Exception e) { - // Ideally we would throw an exception, unfortunately - // often times there are errors as an initial look and - // feel is loaded before one can be switched. Perhaps a - // flag should be added for debugging, so that if true - // the exception would be thrown. + try { + Class c; + Object cl; + // See if we should use a separate ClassLoader + if (table == null || !((cl = table.get("ClassLoader")) + instanceof ClassLoader)) { + cl = Thread.currentThread(). + getContextClassLoader(); + if (cl == null) { + // Fallback to the system class loader. + cl = ClassLoader.getSystemClassLoader(); } - return null; } - }, acc); + ReflectUtil.checkPackageAccess(className); + c = Class.forName(className, true, (ClassLoader)cl); + SwingUtilities2.checkAccess(c.getModifiers()); + if (methodName != null) { + Class[] types = getClassArray(args); + Method m = c.getMethod(methodName, types); + return MethodUtil.invoke(m, c, args); + } else { + Class[] types = getClassArray(args); + Constructor constructor = c.getConstructor(types); + SwingUtilities2.checkAccess(constructor.getModifiers()); + return constructor.newInstance(args); + } + } catch(Exception e) { + // Ideally we would throw an exception, unfortunately + // often times there are errors as an initial look and + // feel is loaded before one can be switched. Perhaps a + // flag should be added for debugging, so that if true + // the exception would be thrown. + } + return null; } /* diff --git a/src/java.desktop/share/classes/javax/swing/UIManager.java b/src/java.desktop/share/classes/javax/swing/UIManager.java index 4bed87dc562..752b37a5238 100644 --- a/src/java.desktop/share/classes/javax/swing/UIManager.java +++ b/src/java.desktop/share/classes/javax/swing/UIManager.java @@ -35,8 +35,6 @@ import java.awt.event.KeyEvent; -import java.security.AccessController; - import javax.swing.plaf.ComponentUI; import javax.swing.border.Border; @@ -55,7 +53,6 @@ import sun.awt.SunToolkit; import sun.awt.OSInfo; -import sun.security.action.GetPropertyAction; import sun.swing.SwingUtilities2; import java.util.HashMap; import java.util.Objects; @@ -292,8 +289,6 @@ private static String makeInstalledLAFKey(String laf, String attr) { */ private static String makeSwingPropertiesFilename() { String sep = File.separator; - // No need to wrap this in a doPrivileged as it's called from - // a doPrivileged. String javaHome = System.getProperty("java.home"); if (javaHome == null) { javaHome = ""; @@ -650,9 +645,7 @@ public static void setLookAndFeel(String className) * @see #getCrossPlatformLookAndFeelClassName */ public static String getSystemLookAndFeelClassName() { - @SuppressWarnings("removal") - String systemLAF = AccessController.doPrivileged( - new GetPropertyAction("swing.systemlaf")); + String systemLAF = System.getProperty("swing.systemlaf"); if (systemLAF != null) { return systemLAF; } @@ -691,9 +684,7 @@ public static String getSystemLookAndFeelClassName() { * @see #getSystemLookAndFeelClassName */ public static String getCrossPlatformLookAndFeelClassName() { - @SuppressWarnings("removal") - String laf = AccessController.doPrivileged( - new GetPropertyAction("swing.crossplatformlaf")); + String laf = System.getProperty("swing.crossplatformlaf"); if (laf != null) { return laf; } @@ -1270,7 +1261,6 @@ public static PropertyChangeListener[] getPropertyChangeListeners() { } } - @SuppressWarnings("removal") private static Properties loadSwingProperties() { /* Don't bother checking for Swing properties if untrusted, as @@ -1282,46 +1272,38 @@ private static Properties loadSwingProperties() else { final Properties props = new Properties(); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - if (OSInfo.getOSType() == OSInfo.OSType.MACOSX) { - props.put(defaultLAFKey, getSystemLookAndFeelClassName()); - } + if (OSInfo.getOSType() == OSInfo.OSType.MACOSX) { + props.put(defaultLAFKey, getSystemLookAndFeelClassName()); + } - try { - File file = new File(makeSwingPropertiesFilename()); + try { + File file = new File(makeSwingPropertiesFilename()); - if (file.exists()) { - // InputStream has been buffered in Properties - // class - try (FileInputStream ins = new FileInputStream(file)) { - props.load(ins); - } - } - } - catch (Exception e) { - // No such file, or file is otherwise non-readable. + if (file.exists()) { + // InputStream has been buffered in Properties + // class + try (FileInputStream ins = new FileInputStream(file)) { + props.load(ins); } - - // Check whether any properties were overridden at the - // command line. - checkProperty(props, defaultLAFKey); - checkProperty(props, auxiliaryLAFsKey); - checkProperty(props, multiplexingLAFKey); - checkProperty(props, installedLAFsKey); - checkProperty(props, disableMnemonicKey); - // Don't care about return value. - return null; } - }); + } + catch (Exception e) { + // No such file, or file is otherwise non-readable. + } + + // Check whether any properties were overridden at the + // command line. + checkProperty(props, defaultLAFKey); + checkProperty(props, auxiliaryLAFsKey); + checkProperty(props, multiplexingLAFKey); + checkProperty(props, installedLAFsKey); + checkProperty(props, disableMnemonicKey); + return props; } } private static void checkProperty(Properties props, String key) { - // No need to do catch the SecurityException here, this runs - // in a doPrivileged. String value = System.getProperty(key); if (value != null) { props.put(key, value); diff --git a/src/java.desktop/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java b/src/java.desktop/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java index eb3920857a6..f1d012ad178 100644 --- a/src/java.desktop/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java +++ b/src/java.desktop/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,6 @@ * * @author Steve Wilson */ -@SuppressWarnings("serial") // Same-version serialization only public class ColorChooserComponentFactory { private ColorChooserComponentFactory() { } // can't instantiate diff --git a/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java b/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java index cfe90a8ec8c..6e9f9f26b37 100644 --- a/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java +++ b/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java @@ -32,8 +32,6 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; @@ -917,13 +915,7 @@ public boolean isDrive(File dir) { } public boolean isFloppyDrive(final File dir) { - @SuppressWarnings("removal") - String path = AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return dir.getAbsolutePath(); - } - }); - + String path = dir.getAbsolutePath(); return path != null && (path.equals("A:\\") || path.equals("B:\\")); } @@ -942,7 +934,6 @@ public File createFileObject(String path) { return super.createFileObject(path); } - @SuppressWarnings("serial") // anonymous class protected File createFileSystemRoot(File f) { // Problem: Removable drives on Windows return false on f.exists() // Workaround: Override exists() to always return true. diff --git a/src/java.desktop/share/classes/javax/swing/plaf/LayerUI.java b/src/java.desktop/share/classes/javax/swing/plaf/LayerUI.java index 61fad895c38..00b7cfc0e5d 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/LayerUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/LayerUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -615,7 +615,6 @@ public void applyPropertyChange(PropertyChangeEvent evt, JLayer l) * baseline */ public int getBaseline(JComponent c, int width, int height) { - @SuppressWarnings("unchecked") JLayer l = (JLayer) c; if (l.getView() != null) { return l.getView().getBaseline(width, height); @@ -633,7 +632,6 @@ public int getBaseline(JComponent c, int width, int height) { * size changes */ public Component.BaselineResizeBehavior getBaselineResizeBehavior(JComponent c) { - @SuppressWarnings("unchecked") JLayer l = (JLayer) c; if (l.getView() != null) { return l.getView().getBaselineResizeBehavior(); @@ -666,7 +664,6 @@ public void doLayout(JLayer l) { * @return preferred size for the passed {@code JLayer} */ public Dimension getPreferredSize(JComponent c) { - @SuppressWarnings("unchecked") JLayer l = (JLayer) c; Component view = l.getView(); if (view != null) { @@ -684,7 +681,6 @@ public Dimension getPreferredSize(JComponent c) { * @return minimal size for the passed {@code JLayer} */ public Dimension getMinimumSize(JComponent c) { - @SuppressWarnings("unchecked") JLayer l = (JLayer) c; Component view = l.getView(); if (view != null) { @@ -702,7 +698,6 @@ public Dimension getMinimumSize(JComponent c) { * @return maximum size for the passed {@code JLayer} */ public Dimension getMaximumSize(JComponent c) { - @SuppressWarnings("unchecked") JLayer l = (JLayer) c; Component view = l.getView(); if (view != null) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java index a1bd07282c1..24af28c94c0 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -49,7 +49,6 @@ * * @author Jeff Dinkins */ -@SuppressWarnings("serial") // Same-version serialization only public class BasicCheckBoxUI extends BasicRadioButtonUI { private static final Object BASIC_CHECK_BOX_UI_KEY = new Object(); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxEditor.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxEditor.java index 0e5eab8285b..b2a8c58eb2e 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxEditor.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -173,7 +173,6 @@ public void setBorder(Border b) { * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. */ - @SuppressWarnings("serial") // Same-version serialization only public static class UIResource extends BasicComboBoxEditor implements javax.swing.plaf.UIResource { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java index 6be306d5572..2d1a458e0d7 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -1792,12 +1792,9 @@ public void propertyChange(PropertyChangeEvent e) { comboBox.revalidate(); } } else { - @SuppressWarnings("unchecked") JComboBox comboBox = (JComboBox)e.getSource(); if ( propertyName == "model" ) { - @SuppressWarnings("unchecked") ComboBoxModel newModel = (ComboBoxModel)e.getNewValue(); - @SuppressWarnings("unchecked") ComboBoxModel oldModel = (ComboBoxModel)e.getOldValue(); if ( oldModel != null && listDataListener != null ) { @@ -2012,7 +2009,6 @@ public Dimension minimumLayoutSize(Container parent) { } public void layoutContainer(Container parent) { - @SuppressWarnings("unchecked") JComboBox cb = (JComboBox)parent; int width = cb.getWidth(); int height = cb.getHeight(); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java index 57bd6664e1a..bdce05ae866 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -696,7 +696,6 @@ public void valueChanged(ListSelectionEvent evt) { if(!evt.getValueIsAdjusting()) { JFileChooser chooser = getFileChooser(); FileSystemView fsv = chooser.getFileSystemView(); - @SuppressWarnings("unchecked") JList list = (JList)evt.getSource(); int fsm = chooser.getFileSelectionMode(); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java index 4c40dc2d278..2e1d894cc8f 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java @@ -393,12 +393,9 @@ public View create(Element elem) { private static Boolean useOV = null; - @SuppressWarnings("removal") private static void setAllowHTMLObject() { if (useOV == null) { - useOV = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "swing.html.object")); + useOV = Boolean.getBoolean("swing.html.object"); }; SwingAccessor.setAllowHTMLObject(useOV); } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java index 53eb25a76d7..0a4aa03dce9 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -1579,7 +1579,6 @@ private Handler getHandler() { * @see #installKeyboardActions * @see #installUI */ - @SuppressWarnings("serial") // Same-version serialization only public class MouseInputHandler implements MouseInputListener { /** @@ -1703,7 +1702,6 @@ protected FocusListener createFocusListener() { * @see #getCellBounds * @see #installUI */ - @SuppressWarnings("serial") // Same-version serialization only public class ListSelectionHandler implements ListSelectionListener { /** @@ -1769,7 +1767,6 @@ private void redrawList() { * @see #createListDataListener * @see #installUI */ - @SuppressWarnings("serial") // Same-version serialization only public class ListDataHandler implements ListDataListener { /** @@ -1842,7 +1839,6 @@ protected ListDataListener createListDataListener() { * @see #createPropertyChangeListener * @see #installUI */ - @SuppressWarnings("serial") // Same-version serialization only public class PropertyChangeHandler implements PropertyChangeListener { /** @@ -2653,9 +2649,7 @@ public void propertyChange(PropertyChangeEvent e) { * listDataListener from the old model and add it to the new one. */ if (propertyName == "model") { - @SuppressWarnings("unchecked") ListModel oldModel = (ListModel)e.getOldValue(); - @SuppressWarnings("unchecked") ListModel newModel = (ListModel)e.getNewValue(); if (oldModel != null) { oldModel.removeListDataListener(listDataListener); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java index 4041bfca714..12b871d6efd 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -45,8 +45,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashSet; import java.util.Locale; @@ -194,7 +192,6 @@ public void propertyChange(PropertyChangeEvent prpChg) { /** * {@inheritDoc} */ - @SuppressWarnings("removal") public void uninitialize() { AppContext context = AppContext.getAppContext(); synchronized (BasicPopupMenuUI.MOUSE_GRABBER_KEY) { @@ -212,7 +209,7 @@ public void uninitialize() { } if(invocator != null) { - AccessController.doPrivileged(invocator); + invocator.run(); invocator = null; } @@ -2082,25 +2079,18 @@ private byte[] loadAudioData(final String soundFile){ * Class.getResourceAsStream just returns raw * bytes, which we can convert to a sound. */ - @SuppressWarnings("removal") - byte[] buffer = AccessController.doPrivileged( - new PrivilegedAction() { - public byte[] run() { - try { - InputStream resource = BasicLookAndFeel.this. - getClass().getResourceAsStream(soundFile); - if (resource == null) { - return null; - } - try (BufferedInputStream in = new BufferedInputStream(resource)) { - return in.readAllBytes(); - } - } catch (IOException ioe) { - System.err.println(ioe.toString()); - return null; - } + byte[] buffer = null; + try { + InputStream resource = BasicLookAndFeel.this. + getClass().getResourceAsStream(soundFile); + if (resource != null) { + try (BufferedInputStream in = new BufferedInputStream(resource)) { + buffer = in.readAllBytes(); } - }); + } + } catch (IOException ioe) { + System.err.println(ioe.toString()); + } if (buffer == null) { System.err.println(getClass().getName() + "/" + soundFile + " not found."); @@ -2190,11 +2180,10 @@ static void playSound(JComponent c, Object actionKey) { * This class contains listener that watches for all the mouse * events that can possibly invoke popup on the component */ - class AWTEventHelper implements AWTEventListener,PrivilegedAction { - @SuppressWarnings("removal") + class AWTEventHelper implements AWTEventListener { AWTEventHelper() { super(); - AccessController.doPrivileged(this); + run(); } public Object run() { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java index 82547a4e036..07036eedbf6 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -39,10 +39,6 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Locale; -import java.security.AccessController; - -import sun.security.action.GetPropertyAction; - /** * Provides the basic look and feel for a JOptionPane. @@ -482,7 +478,6 @@ protected void addMessageComponents(Container container, if (nl >= 0) { // break up newlines if (nl == 0) { - @SuppressWarnings("serial") // anonymous class JPanel breakPanel = new JPanel() { public Dimension getPreferredSize() { Font f = getFont(); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java index db68e126afa..28a797f6937 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -776,22 +776,14 @@ void uninstall() { } } - @SuppressWarnings("removal") void grabWindow(MenuElement[] newPath) { // A grab needs to be added final Toolkit tk = Toolkit.getDefaultToolkit(); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - tk.addAWTEventListener(MouseGrabber.this, - AWTEvent.MOUSE_EVENT_MASK | - AWTEvent.MOUSE_MOTION_EVENT_MASK | - AWTEvent.MOUSE_WHEEL_EVENT_MASK | - AWTEvent.WINDOW_EVENT_MASK | sun.awt.SunToolkit.GRAB_EVENT_MASK); - return null; - } - } - ); + tk.addAWTEventListener(MouseGrabber.this, + AWTEvent.MOUSE_EVENT_MASK | + AWTEvent.MOUSE_MOTION_EVENT_MASK | + AWTEvent.MOUSE_WHEEL_EVENT_MASK | + AWTEvent.WINDOW_EVENT_MASK | sun.awt.SunToolkit.GRAB_EVENT_MASK); Component invoker = newPath[0].getComponent(); if (invoker instanceof JPopupMenu) { @@ -812,18 +804,10 @@ public Object run() { } } - @SuppressWarnings("removal") void ungrabWindow() { final Toolkit tk = Toolkit.getDefaultToolkit(); // The grab should be removed - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - tk.removeAWTEventListener(MouseGrabber.this); - return null; - } - } - ); + tk.removeAWTEventListener(MouseGrabber.this); realUngrabWindow(); } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneDivider.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneDivider.java index 119e12276c7..cd59bf8433b 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneDivider.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneDivider.java @@ -746,7 +746,6 @@ public void mouseExited(MouseEvent e) { * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. */ - @SuppressWarnings("serial") // Same-version serialization only protected class DragController { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java index 31d20ab7b93..5ff68f78d38 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -899,7 +899,6 @@ public BasicSplitPaneDivider getDivider() { * * @return the default non continuous layout divider */ - @SuppressWarnings("serial") // anonymous class protected Component createDefaultNonContinuousLayoutDivider() { return new Canvas() { public void paint(Graphics g) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextAreaUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextAreaUI.java index 2f5f86f872a..1d7128b7ac9 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextAreaUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextAreaUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -49,7 +49,6 @@ * * @author Timothy Prinzing */ -@SuppressWarnings("serial") // Same-version serialization only public class BasicTextAreaUI extends BasicTextUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java index f3795336207..35c1d0e30b5 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -51,7 +51,6 @@ * * @author Timothy Prinzing */ -@SuppressWarnings("serial") // Same-version serialization only public class BasicTextFieldUI extends BasicTextUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextPaneUI.java index a76308dbec6..bf1587f826c 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -47,7 +47,6 @@ * * @author Timothy Prinzing */ -@SuppressWarnings("serial") // Same-version serialization only public class BasicTextPaneUI extends BasicEditorPaneUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java index e0e1a2e5ed6..41ab6137976 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -554,13 +554,11 @@ private Border createNonRolloverToggleBorder() { @Deprecated(since = "17", forRemoval = true) protected JFrame createFloatingFrame(JToolBar toolbar) { Window window = SwingUtilities.getWindowAncestor(toolbar); - @SuppressWarnings("serial") // anonymous class JFrame frame = new JFrame(toolbar.getName(), (window != null) ? window.getGraphicsConfiguration() : null) { // Override createRootPane() to automatically resize // the frame when contents change protected JRootPane createRootPane() { - @SuppressWarnings("serial") // anonymous class JRootPane rootPane = new JRootPane() { private boolean packing = false; @@ -606,7 +604,6 @@ public ToolBarDialog(Dialog owner, String title, boolean modal) { // Override createRootPane() to automatically resize // the frame when contents change protected JRootPane createRootPane() { - @SuppressWarnings("serial") // anonymous class JRootPane rootPane = new JRootPane() { private boolean packing = false; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/ComboPopup.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/ComboPopup.java index 122db235334..71865b4f19f 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/ComboPopup.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/ComboPopup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -46,7 +46,6 @@ * * @author Tom Santos */ -@SuppressWarnings("serial") // Same-version serialization only public interface ComboPopup { /** * Shows the popup diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/DefaultMetalTheme.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/DefaultMetalTheme.java index e6d44c0fae4..8ee862fb0b3 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/DefaultMetalTheme.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/DefaultMetalTheme.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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,7 +30,6 @@ import java.awt.*; import sun.awt.AppContext; -import sun.security.action.GetPropertyAction; import sun.swing.SwingUtilities2; /** @@ -88,7 +87,6 @@ * * @author Steve Wilson */ -@SuppressWarnings("serial") // Same-version serialization only public class DefaultMetalTheme extends MetalTheme { /** * Whether or not fonts should be plain. This is only used if @@ -182,9 +180,7 @@ static String getDefaultPropertyName(int key) { } static { - @SuppressWarnings("removal") - Object boldProperty = java.security.AccessController.doPrivileged( - new GetPropertyAction("swing.boldMetal")); + Object boldProperty = System.getProperty("swing.boldMetal"); if (boldProperty == null || !"false".equals(boldProperty)) { PLAIN_FONTS = false; } @@ -371,7 +367,7 @@ public FontDelegate() { public FontUIResource getFont(int type) { int mappedType = defaultMapping[type]; if (fonts[type] == null) { - Font f = getPrivilegedFont(mappedType); + Font f = getFontForType(mappedType); if (f == null) { f = new Font(getDefaultFontName(type), @@ -385,18 +381,10 @@ public FontUIResource getFont(int type) { /** * This is the same as invoking - * Font.getFont(key), with the exception - * that it is wrapped inside a doPrivileged call. + * Font.getFont(key) */ - @SuppressWarnings("removal") - protected Font getPrivilegedFont(final int key) { - return java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Font run() { - return Font.getFont(getDefaultPropertyName(key)); - } - } - ); + protected Font getFontForType(final int key) { + return Font.getFont(getDefaultPropertyName(key)); } } @@ -405,21 +393,21 @@ public Font run() { */ private static class WindowsFontDelegate extends FontDelegate { private MetalFontDesktopProperty[] props; - private boolean[] checkedPrivileged; + private boolean[] checked; public WindowsFontDelegate() { props = new MetalFontDesktopProperty[6]; - checkedPrivileged = new boolean[6]; + checked = new boolean[6]; } public FontUIResource getFont(int type) { if (fonts[type] != null) { return fonts[type]; } - if (!checkedPrivileged[type]) { - Font f = getPrivilegedFont(type); + if (!checked[type]) { + Font f = getFontForType(type); - checkedPrivileged[type] = true; + checked[type] = true; if (f != null) { fonts[type] = new FontUIResource(f); return fonts[type]; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalButtonUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalButtonUI.java index 2a0b1928fb7..0bbbab7b45f 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalButtonUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalButtonUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -50,7 +50,6 @@ * * @author Tom Santos */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalButtonUI extends BasicButtonUI { // NOTE: These are not really needed, but at this point we can't pull diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java index 0470d15718a..558f1987e4d 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -51,7 +51,6 @@ * @author Michael C. Albers * */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalCheckBoxUI extends MetalRadioButtonUI { // NOTE: MetalCheckBoxUI inherits from MetalRadioButtonUI instead diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalComboBoxEditor.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalComboBoxEditor.java index 6765e034452..bac9a821a75 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalComboBoxEditor.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalComboBoxEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -135,7 +135,6 @@ public Insets getBorderInsets(Component c, Insets insets) { * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. */ - @SuppressWarnings("serial") // Same-version serialization only public static class UIResource extends MetalComboBoxEditor implements javax.swing.plaf.UIResource { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java index 23803dafde9..a7b8718ca8d 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -238,7 +238,6 @@ public void installComponents(JFileChooser fc) { topPanel.add(lookInLabel, BorderLayout.BEFORE_LINE_BEGINS); // CurrentDir ComboBox - @SuppressWarnings("serial") // anonymous class JComboBox tmp1 = new JComboBox() { public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); @@ -381,7 +380,6 @@ public void propertyChange(PropertyChangeEvent e) { populateFileNameLabel(); fileNamePanel.add(fileNameLabel); - @SuppressWarnings("serial") // anonymous class JTextField tmp2 = new JTextField(35) { public Dimension getMaximumSize() { return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java index e46091c523c..41d90d31dd4 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -36,7 +36,6 @@ import java.beans.PropertyChangeListener; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; -import java.security.AccessController; import javax.swing.ButtonModel; import javax.swing.DefaultButtonModel; @@ -65,7 +64,6 @@ import sun.awt.AppContext; import sun.awt.OSInfo; import sun.awt.SunToolkit; -import sun.security.action.GetPropertyAction; import sun.swing.DefaultLayoutStyle; import sun.swing.SwingAccessor; import sun.swing.SwingUtilities2; @@ -145,9 +143,7 @@ static boolean isWindows() { if (!checkedWindows) { if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { isWindows = true; - @SuppressWarnings("removal") - String systemFonts = AccessController.doPrivileged( - new GetPropertyAction("swing.useSystemFontSettings")); + String systemFonts = System.getProperty("swing.useSystemFontSettings"); useSystemFonts = Boolean.parseBoolean(systemFonts); } checkedWindows = true; @@ -1662,9 +1658,7 @@ public static MetalTheme getCurrentTheme() { else { // Create the default theme. We prefer Ocean, but will // use DefaultMetalTheme if told to. - @SuppressWarnings("removal") - String theme = AccessController.doPrivileged( - new GetPropertyAction("swing.metalTheme")); + String theme = System.getProperty("swing.metalTheme"); if ("steel".equals(theme)) { currentTheme = new DefaultMetalTheme(); } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalProgressBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalProgressBarUI.java index 5f316cbb209..b5dddfc1274 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalProgressBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalProgressBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -44,7 +44,6 @@ * * @author Michael C. Albers */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalProgressBarUI extends BasicProgressBarUI { private Rectangle innards; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java index 8bd1f9acc0a..712046737eb 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ * @author Michael C. Albers (Metal modifications) * @author Jeff Dinkins (original BasicRadioButtonCode) */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalRadioButtonUI extends BasicRadioButtonUI { private static final Object METAL_RADIO_BUTTON_UI_KEY = new Object(); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java index 81ea2fe28ee..b243c5ca472 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -77,7 +77,6 @@ * @author Terry Kellerman * @since 1.4 */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalRootPaneUI extends BasicRootPaneUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollPaneUI.java index e90d8657ae5..e94edc28b65 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -50,7 +50,6 @@ * * @author Steve Wilson */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalScrollPaneUI extends BasicScrollPaneUI { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSeparatorUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSeparatorUI.java index 9140577b895..fe8a45aa979 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSeparatorUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSeparatorUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -50,7 +50,6 @@ * * @author Jeff Shapiro */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalSeparatorUI extends BasicSeparatorUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSliderUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSliderUI.java index 03133596822..c31ee81c729 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSliderUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSliderUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -50,7 +50,6 @@ * * @author Tom Santos */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalSliderUI extends BasicSliderUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSplitPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSplitPaneUI.java index ee888771ff2..aba58db389b 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSplitPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalSplitPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,6 @@ * * @author Steve Wilson */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalSplitPaneUI extends BasicSplitPaneUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTabbedPaneUI.java index d73ef0d6613..8f9229d4cbd 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTabbedPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -47,7 +47,6 @@ * * @author Tom Santos */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalTabbedPaneUI extends BasicTabbedPaneUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTextFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTextFieldUI.java index 9a59f99fdce..e7bbc0baf69 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTextFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalTextFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -47,7 +47,6 @@ * * @author Steve Wilson */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalTextFieldUI extends BasicTextFieldUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java index 325f30f7e0a..088a54ba6b2 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -55,7 +55,6 @@ * * @author Tom Santos */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalToggleButtonUI extends BasicToggleButtonUI { private static final Object METAL_TOGGLE_BUTTON_UI_KEY = new Object(); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToolTipUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToolTipUI.java index 6cf5314b4a0..258a37b8dbb 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToolTipUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalToolTipUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -49,7 +49,6 @@ * * @author Steve Wilson */ -@SuppressWarnings("serial") // Same-version serialization only public class MetalToolTipUI extends BasicToolTipUI { static MetalToolTipUI sharedInstance = new MetalToolTipUI(); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalUtils.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalUtils.java index 5ed2cd9b5ce..79902886848 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalUtils.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -210,7 +210,6 @@ static int getInt(Object key, int defaultValue) { */ static boolean drawGradient(Component c, Graphics g, String key, int x, int y, int w, int h, boolean vertical) { - @SuppressWarnings("unchecked") java.util.List gradient = (java.util.List)UIManager.get(key); if (gradient == null || !(g instanceof Graphics2D)) { return false; @@ -275,7 +274,6 @@ public void paint(Component c, Graphics2D g, protected void paintToImage(Component c, Image image, Graphics g, int w, int h, Object[] args) { Graphics2D g2 = (Graphics2D)g; - @SuppressWarnings("unchecked") java.util.List gradient = (java.util.List)args[0]; boolean isVertical = ((Boolean)args[1]).booleanValue(); // Render to the VolatileImage diff --git a/src/java.desktop/share/classes/javax/swing/plaf/multi/MultiLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/multi/MultiLookAndFeel.java index 3862a5ab871..a2d3edd659d 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/multi/MultiLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/multi/MultiLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -56,7 +56,6 @@ * * @author Willie Walker */ -@SuppressWarnings("serial") // Same-version serialization only public class MultiLookAndFeel extends LookAndFeel { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java index 9dfd422f6dd..96ef2541c7b 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,21 @@ */ package javax.swing.plaf.nimbus; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; import java.awt.image.BufferedImage; -import java.util.*; -import javax.swing.*; +import javax.swing.JDesktopPane; +import javax.swing.JSlider; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.Painter; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import javax.swing.plaf.UIResource; import javax.swing.plaf.synth.SynthContext; import javax.swing.plaf.synth.SynthPainter; import javax.swing.plaf.synth.SynthConstants; @@ -531,7 +540,11 @@ public void paintDesktopIconBorder(SynthContext context, public void paintDesktopPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { - paintBackground(context, g, x, y, w, h, null); + if (context.getComponent() instanceof JDesktopPane pane) { + if (pane.getBackground() instanceof UIResource) { + paintBackground(context, g, x, y, w, h, null); + } + } } /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java index 0b82788032e..23e6e8ec4a3 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -76,7 +76,6 @@ public static ComponentUI createUI(JComponent c) { @Override protected void installComponents() { if (UIManager.getBoolean("InternalFrame.useTaskBar")) { - @SuppressWarnings("serial") // anonymous class JToggleButton tmp = new JToggleButton(frame.getTitle(), frame.getFrameIcon()) { @Override public String getToolTipText() { return getText(); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java index 52ab14a359f..f8bf123ca89 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -376,7 +376,6 @@ protected Dimension getMinimumThumbSize() { */ @Override protected JButton createDecreaseButton(int orientation) { - @SuppressWarnings("serial") // anonymous class SynthArrowButton synthArrowButton = new SynthArrowButton(orientation) { @Override public boolean contains(int x, int y) { @@ -406,7 +405,6 @@ public boolean contains(int x, int y) { */ @Override protected JButton createIncreaseButton(int orientation) { - @SuppressWarnings("serial") // anonymous class SynthArrowButton synthArrowButton = new SynthArrowButton(orientation) { @Override public boolean contains(int x, int y) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java index 49a9689409f..4ac76dec282 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -277,7 +277,6 @@ private void setDividerDraggingColor(Graphics g, int loc) { * {@inheritDoc} */ @Override - @SuppressWarnings("serial") // anonymous class protected Component createDefaultNonContinuousLayoutDivider() { return new Canvas() { public void paint(Graphics g) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java index 3d4c41d9677..956a4ee2fcc 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -51,7 +51,6 @@ * @author Shannon Hickey * @since 1.7 */ -@SuppressWarnings("serial") // Same-version serialization only public class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI { private Handler handler = new Handler(); private SynthStyle style; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java index 61fd591d9af..02ab78d14e8 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -50,7 +50,6 @@ * @author Shannon Hickey * @since 1.7 */ -@SuppressWarnings("serial") // Same-version serialization only public class SynthTextFieldUI extends BasicTextFieldUI implements SynthUI { private Handler handler = new Handler(); private SynthStyle style; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java index 4aa5567aa26..c966b979e32 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -47,7 +47,6 @@ * @author Shannon Hickey * @since 1.7 */ -@SuppressWarnings("serial") // Same-version serialization only public class SynthTextPaneUI extends SynthEditorPaneUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java index f9d0d6eb1fa..0e9caf3ebd8 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -771,7 +771,6 @@ public SynthTreeCellEditor(JTree tree, @Override protected TreeCellEditor createTreeCellEditor() { - @SuppressWarnings("serial") // anonymous class JTextField tf = new JTextField() { @Override public String getName() { diff --git a/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java b/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java index 6c21e71c2ef..de849476772 100644 --- a/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java @@ -147,14 +147,7 @@ protected AbstractDocument(Content data, AttributeContext context) { if (defaultI18NProperty == null) { // determine default setting for i18n support - @SuppressWarnings("removal") - String o = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public String run() { - return System.getProperty(I18NProperty); - } - } - ); + String o = System.getProperty(I18NProperty); if (o != null) { defaultI18NProperty = Boolean.valueOf(o); } else { diff --git a/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java b/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java index 60ca2d72634..757eccfcd53 100644 --- a/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -1182,7 +1182,6 @@ public String getName() { * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. */ - @SuppressWarnings("serial") // Same-version serialization only public static class ElementSpec { /** diff --git a/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java b/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java index 21e2b6115e3..03e04d1c1a7 100644 --- a/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java +++ b/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java @@ -26,9 +26,6 @@ import com.sun.beans.util.Cache; -import java.security.AccessController; -import java.security.PrivilegedAction; - import java.beans.JavaBean; import java.beans.BeanProperty; import java.beans.Transient; @@ -1130,7 +1127,6 @@ private static HashMap getKeymapTable() { * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. */ - @SuppressWarnings("serial") // Same-version serialization only public static class KeyBinding { /** @@ -3954,7 +3950,6 @@ public String toString() { * Maps from class name to Boolean indicating if * processInputMethodEvent has been overridden. */ - @SuppressWarnings("removal") private static Cache,Boolean> METHOD_OVERRIDDEN = new Cache,Boolean>(Cache.Kind.WEAK, Cache.Kind.STRONG) { /** @@ -3969,17 +3964,12 @@ public Boolean create(final Class type) { if (get(type.getSuperclass())) { return Boolean.TRUE; } - return AccessController.doPrivileged( - new PrivilegedAction() { - public Boolean run() { - try { - type.getDeclaredMethod("processInputMethodEvent", InputMethodEvent.class); - return Boolean.TRUE; - } catch (NoSuchMethodException exception) { - return Boolean.FALSE; - } - } - }); + try { + type.getDeclaredMethod("processInputMethodEvent", InputMethodEvent.class); + return Boolean.TRUE; + } catch (NoSuchMethodException exception) { + return Boolean.FALSE; + } } }; diff --git a/src/java.desktop/share/classes/javax/swing/text/PlainView.java b/src/java.desktop/share/classes/javax/swing/text/PlainView.java index 6697ca4e2a3..148238354b5 100644 --- a/src/java.desktop/share/classes/javax/swing/text/PlainView.java +++ b/src/java.desktop/share/classes/javax/swing/text/PlainView.java @@ -27,8 +27,6 @@ import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Objects; import javax.swing.event.*; import java.lang.ref.SoftReference; @@ -839,20 +837,13 @@ static boolean getFPMethodOverridden(Class cls, String method, return isFPMethodOverridden; } - @SuppressWarnings("removal") private static boolean checkFPMethodOverridden(final Class className, final String methodName, final FPMethodArgs methodArgs) { - return AccessController - .doPrivileged(new PrivilegedAction() { - @Override - public Boolean run() { - return isFPMethodOverridden(methodName, className, - methodArgs.getMethodArguments(false), - methodArgs.getMethodArguments(true)); - } - }); + return isFPMethodOverridden(methodName, className, + methodArgs.getMethodArguments(false), + methodArgs.getMethodArguments(true)); } private static boolean isFPMethodOverridden(String method, diff --git a/src/java.desktop/share/classes/javax/swing/text/SimpleAttributeSet.java b/src/java.desktop/share/classes/javax/swing/text/SimpleAttributeSet.java index 30a47c02a1f..ad6afb14092 100644 --- a/src/java.desktop/share/classes/javax/swing/text/SimpleAttributeSet.java +++ b/src/java.desktop/share/classes/javax/swing/text/SimpleAttributeSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -48,7 +48,6 @@ * * @author Tim Prinzing */ -@SuppressWarnings("serial") // Same-version serialization only public class SimpleAttributeSet implements MutableAttributeSet, Serializable, Cloneable { /** diff --git a/src/java.desktop/share/classes/javax/swing/text/StyledEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/StyledEditorKit.java index e2630c93623..636196de69c 100644 --- a/src/java.desktop/share/classes/javax/swing/text/StyledEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/StyledEditorKit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -171,7 +171,6 @@ public Object clone() { /** * Creates the AttributeSet used for the selection. */ - @SuppressWarnings("serial") // anonymous class private void createInputAttributes() { inputAttributes = new SimpleAttributeSet() { public AttributeSet getResolveParent() { diff --git a/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java b/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java index 8d6980eaaea..0bceae3acee 100644 --- a/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java +++ b/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -352,7 +352,6 @@ protected final Segment getLineBuffer() { * @param p1 the ending document location to use * @return the break position */ - @SuppressWarnings("deprecation") protected int calculateBreakPosition(int p0, int p1) { int p; Segment segment = SegmentCache.getSharedSegment(); @@ -798,7 +797,6 @@ public Shape modelToView(int pos, Shape a, Position.Bias b) * given point in the view * @see View#viewToModel */ - @SuppressWarnings("deprecation") public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) { // PENDING(prinz) implement bias properly bias[0] = Position.Bias.Forward; diff --git a/src/java.desktop/share/classes/javax/swing/text/html/FormView.java b/src/java.desktop/share/classes/javax/swing/text/html/FormView.java index 8af4f9e2f1e..47f10e1abb2 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/FormView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/FormView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -382,7 +382,6 @@ private void removeStaleListenerForModel(Object model) { // BasicListUI$Handler. // For JComboBox, there are 2 stale ListDataListeners, which are // BasicListUI$Handler and BasicComboBoxUI$Handler. - @SuppressWarnings("unchecked") AbstractListModel listModel = (AbstractListModel) model; String listenerClass1 = "javax.swing.plaf.basic.BasicListUI$Handler"; @@ -850,7 +849,6 @@ private void loadSelectData(AttributeSet attr, StringBuilder buffer) { } } } else if (m instanceof ComboBoxModel) { - @SuppressWarnings("unchecked") ComboBoxModel model = (ComboBoxModel)m; Option option = (Option)model.getSelectedItem(); if (option != null) { @@ -962,7 +960,6 @@ void resetForm() { } catch (BadLocationException e) { } } else if (m instanceof OptionListModel) { - @SuppressWarnings("unchecked") OptionListModel model = (OptionListModel) m; int size = model.getSize(); for (int i = 0; i < size; i++) { @@ -975,7 +972,6 @@ void resetForm() { } } } else if (m instanceof OptionComboBoxModel) { - @SuppressWarnings("unchecked") OptionComboBoxModel model = (OptionComboBoxModel) m; Option option = model.getInitialSelection(); if (option != null) { diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java index f17804e624d..53ceea32668 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java @@ -53,8 +53,6 @@ import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Enumeration; import javax.accessibility.Accessible; @@ -471,22 +469,13 @@ public StyleSheet getStyleSheet() { /** * Fetch a resource relative to the HTMLEditorKit classfile. - * If this is called on 1.2 the loading will occur under the - * protection of a doPrivileged call to allow the HTMLEditorKit - * to function when used in an applet. * * @param name the name of the resource, relative to the * HTMLEditorKit class * @return a stream representing the resource */ - @SuppressWarnings("removal") static InputStream getResourceAsStream(final String name) { - return AccessController.doPrivileged( - new PrivilegedAction() { - public InputStream run() { - return HTMLEditorKit.class.getResourceAsStream(name); - } - }); + return HTMLEditorKit.class.getResourceAsStream(name); } /** diff --git a/src/java.desktop/share/classes/javax/swing/text/html/parser/ParserDelegator.java b/src/java.desktop/share/classes/javax/swing/text/html/parser/ParserDelegator.java index 0dbeb996778..bf360574f6d 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/parser/ParserDelegator.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/parser/ParserDelegator.java @@ -35,8 +35,6 @@ import java.io.Reader; import java.io.Serial; import java.io.Serializable; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * Responsible for starting up a new DocumentParser @@ -131,14 +129,8 @@ public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharS * ParserDelegator class. * @return a stream representing the resource */ - @SuppressWarnings("removal") static InputStream getResourceAsStream(final String name) { - return AccessController.doPrivileged( - new PrivilegedAction() { - public InputStream run() { - return ParserDelegator.class.getResourceAsStream(name); - } - }); + return ParserDelegator.class.getResourceAsStream(name); } @Serial diff --git a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java index 60cfd585c73..3afaf828417 100644 --- a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java +++ b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java @@ -37,8 +37,6 @@ import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; @@ -644,13 +642,7 @@ public void setCharacterSet(String name) { char[] set = characterSets.get(name); if (set == null) { - @SuppressWarnings("removal") - InputStream charsetStream = AccessController.doPrivileged( - new PrivilegedAction() { - public InputStream run() { - return RTFReader.class.getResourceAsStream("charsets/" + name + ".txt"); - } - }); + InputStream charsetStream = RTFReader.class.getResourceAsStream("charsets/" + name + ".txt"); set = readCharset(charsetStream); defineCharacterSet(name, set); } diff --git a/src/java.desktop/share/classes/javax/swing/tree/AbstractLayoutCache.java b/src/java.desktop/share/classes/javax/swing/tree/AbstractLayoutCache.java index d3435231e7f..97383785dca 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/AbstractLayoutCache.java +++ b/src/java.desktop/share/classes/javax/swing/tree/AbstractLayoutCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,6 @@ * * @author Scott Violet */ -@SuppressWarnings("serial") // Same-version serialization only public abstract class AbstractLayoutCache implements RowMapper { /** Object responsible for getting the size of a node. */ protected NodeDimensions nodeDimensions; diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeCellEditor.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeCellEditor.java index 2397f51f7a6..4662c95c01f 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeCellEditor.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeCellEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -537,7 +537,6 @@ protected Container createContainer() { */ protected TreeCellEditor createTreeCellEditor() { Border aBorder = UIManager.getBorder("Tree.editorBorder"); - @SuppressWarnings("serial") // Safe: outer class is non-serializable DefaultCellEditor editor = new DefaultCellEditor (new DefaultTextField(aBorder)) { public boolean shouldSelectCell(EventObject event) { diff --git a/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java b/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java index bb7fb64f7f1..5a81de507db 100644 --- a/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java +++ b/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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,8 +26,6 @@ package sun.awt; import java.awt.AWTEvent; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Map; @@ -323,7 +321,6 @@ public void run() { } } - @SuppressWarnings("serial") static AWTEvent getShutdownEvent() { return new AWTEvent(getInstance(), 0) { }; @@ -333,17 +330,13 @@ static AWTEvent getShutdownEvent() { * Creates and starts a new blocker thread. Doesn't return until * the new blocker thread starts. */ - @SuppressWarnings("removal") private void activateBlockerThread() { - AccessController.doPrivileged((PrivilegedAction) () -> { - String name = "AWT-Shutdown"; - Thread thread = new Thread( - ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); - thread.setContextClassLoader(null); - thread.setDaemon(false); - blockerThread = thread; - return thread; - }).start(); + String name = "AWT-Shutdown"; + Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); + thread.setContextClassLoader(null); + thread.setDaemon(false); + blockerThread = thread; + thread.start(); try { /* Wait for the blocker thread to start. */ mainLock.wait(); diff --git a/src/java.desktop/share/classes/sun/awt/AppContext.java b/src/java.desktop/share/classes/sun/awt/AppContext.java index fa098af556d..a35d89f6a0c 100644 --- a/src/java.desktop/share/classes/sun/awt/AppContext.java +++ b/src/java.desktop/share/classes/sun/awt/AppContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ import java.awt.Toolkit; import java.awt.GraphicsEnvironment; import java.awt.event.InvocationEvent; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; @@ -229,20 +227,13 @@ public boolean isDisposed() { * @see sun.awt.SunToolkit * @since 1.2 */ - @SuppressWarnings("removal") AppContext(ThreadGroup threadGroup) { numAppContexts.incrementAndGet(); this.threadGroup = threadGroup; threadGroup2appContext.put(threadGroup, this); - this.contextClassLoader = - AccessController.doPrivileged(new PrivilegedAction() { - public ClassLoader run() { - return Thread.currentThread().getContextClassLoader(); - } - }); - + this.contextClassLoader = Thread.currentThread().getContextClassLoader(); // Initialize push/pop lock and its condition to be used by all the // EventQueues within this AppContext Lock eventQueuePushPopLock = new ReentrantLock(); @@ -254,26 +245,19 @@ public ClassLoader run() { private static final ThreadLocal threadAppContext = new ThreadLocal(); - @SuppressWarnings("removal") private static void initMainAppContext() { // On the main Thread, we get the ThreadGroup, make a corresponding // AppContext, and instantiate the Java EventQueue. This way, legacy // code is unaffected by the move to multiple AppContext ability. - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - ThreadGroup currentThreadGroup = - Thread.currentThread().getThreadGroup(); - ThreadGroup parentThreadGroup = currentThreadGroup.getParent(); - while (parentThreadGroup != null) { - // Find the root ThreadGroup to construct our main AppContext - currentThreadGroup = parentThreadGroup; - parentThreadGroup = currentThreadGroup.getParent(); - } + ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup(); + ThreadGroup parentThreadGroup = currentThreadGroup.getParent(); + while (parentThreadGroup != null) { + // Find the root ThreadGroup to construct our main AppContext + currentThreadGroup = parentThreadGroup; + parentThreadGroup = currentThreadGroup.getParent(); + } - mainAppContext = SunToolkit.createNewAppContext(currentThreadGroup); - return null; - } - }); + mainAppContext = SunToolkit.createNewAppContext(currentThreadGroup); } /** @@ -284,7 +268,6 @@ public Void run() { * @see java.lang.ThreadGroup * @since 1.2 */ - @SuppressWarnings("removal") public static AppContext getAppContext() { // we are standalone app, return the main app context if (numAppContexts.get() == 1 && mainAppContext != null) { @@ -294,69 +277,53 @@ public static AppContext getAppContext() { AppContext appContext = threadAppContext.get(); if (null == appContext) { - appContext = AccessController.doPrivileged(new PrivilegedAction() - { - public AppContext run() { - // Get the current ThreadGroup, and look for it and its - // parents in the hash from ThreadGroup to AppContext -- - // it should be found, because we use createNewContext() - // when new AppContext objects are created. - ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup(); - ThreadGroup threadGroup = currentThreadGroup; - - // Special case: we implicitly create the main app context - // if no contexts have been created yet. This covers standalone apps - // and excludes applets because by the time applet starts - // a number of contexts have already been created by the plugin. - synchronized (getAppContextLock) { - if (numAppContexts.get() == 0) { - if (System.getProperty("javaplugin.version") == null && - System.getProperty("javawebstart.version") == null) { - initMainAppContext(); - } else if (System.getProperty("javafx.version") != null && - threadGroup.getParent() != null) { - // Swing inside JavaFX case - SunToolkit.createNewAppContext(); - } - } + // Get the current ThreadGroup, and look for it and its + // parents in the hash from ThreadGroup to AppContext -- + // it should be found, because we use createNewContext() + // when new AppContext objects are created. + ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup(); + ThreadGroup threadGroup = currentThreadGroup; + + // Special case: we implicitly create the main app context + // if no contexts have been created yet. This covers standalone apps + // and excludes applets because by the time applet starts + // a number of contexts have already been created by the plugin. + synchronized (getAppContextLock) { + if (numAppContexts.get() == 0) { + if (System.getProperty("javaplugin.version") == null && + System.getProperty("javawebstart.version") == null) { + initMainAppContext(); + } else if (System.getProperty("javafx.version") != null && + threadGroup.getParent() != null) { + // Swing inside JavaFX case + SunToolkit.createNewAppContext(); } + } + } - AppContext context = threadGroup2appContext.get(threadGroup); - while (context == null) { - threadGroup = threadGroup.getParent(); - if (threadGroup == null) { - // We've got up to the root thread group and did not find an AppContext - // Try to get it from the security manager - SecurityManager securityManager = System.getSecurityManager(); - if (securityManager != null) { - ThreadGroup smThreadGroup = securityManager.getThreadGroup(); - if (smThreadGroup != null) { - /* - * If we get this far then it's likely that - * the ThreadGroup does not actually belong - * to the applet, so do not cache it. - */ - return threadGroup2appContext.get(smThreadGroup); - } - } - return null; - } - context = threadGroup2appContext.get(threadGroup); - } + AppContext context = threadGroup2appContext.get(threadGroup); + while (context == null) { + threadGroup = threadGroup.getParent(); + if (threadGroup == null) { + // We've got up to the root thread group and did not find an AppContext + // We have nowhere else to look, and this is not supposed to happen. + // return null from this whole method. + return null; + } + context = threadGroup2appContext.get(threadGroup); + } - // In case we did anything in the above while loop, we add - // all the intermediate ThreadGroups to threadGroup2appContext - // so we won't spin again. - for (ThreadGroup tg = currentThreadGroup; tg != threadGroup; tg = tg.getParent()) { - threadGroup2appContext.put(tg, context); - } + // In case we did anything in the above while loop, we add + // all the intermediate ThreadGroups to threadGroup2appContext + // so we won't spin again. + for (ThreadGroup tg = currentThreadGroup; tg != threadGroup; tg = tg.getParent()) { + threadGroup2appContext.put(tg, context); + } - // Now we're done, so we cache the latest key/value pair. - threadAppContext.set(context); + // Now we're done, so we cache the latest key/value pair. + threadAppContext.set(context); - return context; - } - }); + appContext = context; } return appContext; @@ -395,7 +362,6 @@ public static boolean isMainContext(AppContext ctx) { * contained within this AppContext * @since 1.2 */ - @SuppressWarnings({"deprecation", "removal"}) public void dispose() throws IllegalThreadStateException { System.err.println( """ @@ -439,19 +405,13 @@ public void run() { log.finer("exception occurred while disposing app context", t); } } - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - if (!GraphicsEnvironment.isHeadless() && SystemTray.isSupported()) - { - SystemTray systemTray = SystemTray.getSystemTray(); - TrayIcon[] trayIconsToDispose = systemTray.getTrayIcons(); - for (TrayIcon ti : trayIconsToDispose) { - systemTray.remove(ti); - } - } - return null; - } - }); + if (!GraphicsEnvironment.isHeadless() && SystemTray.isSupported()) { + SystemTray systemTray = SystemTray.getSystemTray(); + TrayIcon[] trayIconsToDispose = systemTray.getTrayIcons(); + for (TrayIcon ti : trayIconsToDispose) { + systemTray.remove(ti); + } + } // Alert PropertyChangeListeners that the GUI has been disposed. if (changeSupport != null) { changeSupport.firePropertyChange(GUI_DISPOSED, false, true); @@ -546,25 +506,6 @@ public void run() { } } - static final class CreateThreadAction implements PrivilegedAction { - private final AppContext appContext; - private final Runnable runnable; - - CreateThreadAction(AppContext ac, Runnable r) { - appContext = ac; - runnable = r; - } - - public Thread run() { - Thread t = new Thread(appContext.getThreadGroup(), - runnable, "AppContext Disposer", 0, false); - t.setContextClassLoader(appContext.getContextClassLoader()); - t.setPriority(Thread.NORM_PRIORITY + 1); - t.setDaemon(true); - return t; - } - } - static void stopEventDispatchThreads() { for (AppContext appContext: getAppContexts()) { if (appContext.isDisposed()) { @@ -576,9 +517,11 @@ static void stopEventDispatchThreads() { if (appContext != AppContext.getAppContext()) { // Create a thread that belongs to the thread group associated // with the AppContext and invokes EventQueue.postEvent. - PrivilegedAction action = new CreateThreadAction(appContext, r); - @SuppressWarnings("removal") - Thread thread = AccessController.doPrivileged(action); + Thread thread = new Thread(appContext.getThreadGroup(), + r, "AppContext Disposer", 0, false); + thread.setContextClassLoader(appContext.getContextClassLoader()); + thread.setPriority(Thread.NORM_PRIORITY + 1); + thread.setDaemon(true); thread.start(); } else { r.run(); @@ -806,14 +749,8 @@ public synchronized PropertyChangeListener[] getPropertyChangeListeners( // Set up JavaAWTAccess in SharedSecrets static { SharedSecrets.setJavaAWTAccess(new JavaAWTAccess() { - @SuppressWarnings("removal") private boolean hasRootThreadGroup(final AppContext ecx) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Boolean run() { - return ecx.threadGroup.getParent() == null; - } - }); + return ecx.threadGroup.getParent() == null; } /** diff --git a/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java b/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java index a19e4f394e1..a6293d4efea 100644 --- a/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java +++ b/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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,8 +30,6 @@ import java.io.ObjectStreamException; import java.io.Serial; import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * This class exists for deserialization compatibility only. @@ -61,7 +59,6 @@ private enum Cause { RETARGETED } - @SuppressWarnings("serial") private static final Component dummy = new Component(){}; private final Cause cause; @@ -72,7 +69,6 @@ private CausedFocusEvent(Component source, int id, boolean temporary, throw new IllegalStateException(); } - @SuppressWarnings("removal") @Serial Object readResolve() throws ObjectStreamException { FocusEvent.Cause newCause; @@ -119,17 +115,11 @@ Object readResolve() throws ObjectStreamException { focusEvent.setSource(null); try { final Field consumedField = FocusEvent.class.getField("consumed"); - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - consumedField.setAccessible(true); - try { - consumedField.set(focusEvent, consumed); - } catch (IllegalAccessException e) { - } - return null; - } - }); + consumedField.setAccessible(true); + try { + consumedField.set(focusEvent, consumed); + } catch (IllegalAccessException e) { + } } catch (NoSuchFieldException e) { } diff --git a/src/java.desktop/share/classes/sun/awt/DebugSettings.java b/src/java.desktop/share/classes/sun/awt/DebugSettings.java index 9d89b6519b7..b95ac44ba54 100644 --- a/src/java.desktop/share/classes/sun/awt/DebugSettings.java +++ b/src/java.desktop/share/classes/sun/awt/DebugSettings.java @@ -108,18 +108,11 @@ public static DebugSettings getInstance() { * Load debug properties from file, then override * with any command line specified properties */ - @SuppressWarnings("removal") private synchronized void loadProperties() { // setup initial properties - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - loadDefaultProperties(); - loadFileProperties(); - loadSystemProperties(); - return null; - } - }); + loadDefaultProperties(); + loadFileProperties(); + loadSystemProperties(); // echo the initial property settings to stdout if (log.isLoggable(PlatformLogger.Level.FINE)) { diff --git a/src/java.desktop/share/classes/sun/awt/FontConfiguration.java b/src/java.desktop/share/classes/sun/awt/FontConfiguration.java index 9fffa09ed6c..0054382e8f6 100644 --- a/src/java.desktop/share/classes/sun/awt/FontConfiguration.java +++ b/src/java.desktop/share/classes/sun/awt/FontConfiguration.java @@ -35,8 +35,6 @@ import java.io.OutputStream; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -120,7 +118,7 @@ public FontConfiguration(SunFontManager fm, this.preferPropFonts = preferPropFonts; /* fontConfig should be initialised by default constructor, and * its data tables can be shared, since readFontConfigFile doesn't - * update any other state. Also avoid a doPrivileged block. + * update any other state. */ initFontConfig(); } @@ -156,20 +154,8 @@ public boolean fontFilesArePresent() { short fontNameID = compFontNameIDs[0][0][0]; short fileNameID = getComponentFileID(fontNameID); final String fileName = mapFileName(getComponentFileName(fileNameID)); - @SuppressWarnings("removal") - Boolean exists = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Boolean run() { - try { - File f = new File(fileName); - return Boolean.valueOf(f.exists()); - } - catch (Exception e) { - return Boolean.FALSE; - } - } - }); - return exists.booleanValue(); + File f = new File(fileName); + return f.exists(); } private void findFontConfigFile() { @@ -960,18 +946,11 @@ private CharsetEncoder getFontCharsetEncoder(final String charsetName, !charsetName.startsWith("sun.font.")) { fc = Charset.forName(charsetName); } else { - @SuppressWarnings("removal") - Class fcc = AccessController.doPrivileged(new PrivilegedAction>() { - public Class run() { - try { - return Class.forName(charsetName, true, - ClassLoader.getSystemClassLoader()); - } catch (ClassNotFoundException e) { - } - return null; - } - }); - + Class fcc = null; + try { + fcc = Class.forName(charsetName, true, ClassLoader.getSystemClassLoader()); + } catch (ClassNotFoundException e) { + } if (fcc != null) { try { fc = (Charset) fcc.getDeclaredConstructor().newInstance(); diff --git a/src/java.desktop/share/classes/sun/awt/FontDescriptor.java b/src/java.desktop/share/classes/sun/awt/FontDescriptor.java index 046ecce16da..4a16cd8d811 100644 --- a/src/java.desktop/share/classes/sun/awt/FontDescriptor.java +++ b/src/java.desktop/share/classes/sun/awt/FontDescriptor.java @@ -120,10 +120,7 @@ public boolean useUnicode() { } static boolean isLE; static { - @SuppressWarnings("removal") - String enc = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.io.unicode.encoding", - "UnicodeBig")); + String enc = System.getProperty("sun.io.unicode.encoding", "UnicodeBig"); isLE = !"UnicodeBig".equals(enc); } } diff --git a/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java b/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java index 86b957398f7..ef50d883ee5 100644 --- a/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java +++ b/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -104,7 +104,6 @@ public static boolean shouldFocusOnClick(Component component) { /* * Posts proper lost/gain focus events to the event queue. */ - @SuppressWarnings("deprecation") public static boolean deliverFocus(Component lightweightChild, Component target, boolean temporary, diff --git a/src/java.desktop/share/classes/sun/awt/LightweightFrame.java b/src/java.desktop/share/classes/sun/awt/LightweightFrame.java index cd1cdf3ebd5..205b8034b7e 100644 --- a/src/java.desktop/share/classes/sun/awt/LightweightFrame.java +++ b/src/java.desktop/share/classes/sun/awt/LightweightFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -88,7 +88,6 @@ public LightweightFrame() { @Override public final void toFront() {} @Override public final void toBack() {} - @SuppressWarnings("deprecation") @Override public void addNotify() { synchronized (getTreeLock()) { if (!isDisplayable()) { diff --git a/src/java.desktop/share/classes/sun/awt/NativeLibLoader.java b/src/java.desktop/share/classes/sun/awt/NativeLibLoader.java index 868ebdf3699..4bb49ae0b10 100644 --- a/src/java.desktop/share/classes/sun/awt/NativeLibLoader.java +++ b/src/java.desktop/share/classes/sun/awt/NativeLibLoader.java @@ -52,14 +52,8 @@ class NativeLibLoader { * For now, we know it's done by the implementation, and we assume * that the name of the library is "awt". -br. */ - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") static void loadLibraries() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); } } diff --git a/src/java.desktop/share/classes/sun/awt/SunToolkit.java b/src/java.desktop/share/classes/sun/awt/SunToolkit.java index 355ee995c8c..1dc6c2f3920 100644 --- a/src/java.desktop/share/classes/sun/awt/SunToolkit.java +++ b/src/java.desktop/share/classes/sun/awt/SunToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -79,7 +79,6 @@ import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.net.URL; -import java.security.AccessController; import java.util.ArrayList; import java.util.Collections; import java.util.Locale; @@ -100,8 +99,6 @@ import sun.awt.image.URLImageSource; import sun.font.FontDesignMetrics; import sun.net.util.URLUtil; -import sun.security.action.GetBooleanAction; -import sun.security.action.GetPropertyAction; import sun.util.logging.PlatformLogger; import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING; @@ -122,14 +119,12 @@ public abstract class SunToolkit extends Toolkit initStatic(); } - @SuppressWarnings("removal") private static void initStatic() { - if (AccessController.doPrivileged(new GetBooleanAction("sun.awt.nativedebug"))) { + if (Boolean.getBoolean("sun.awt.nativedebug")) { DebugSettings.init(); } touchKeyboardAutoShowIsEnabled = Boolean.parseBoolean( - GetPropertyAction.privilegedGetProperty( - "awt.touchKeyboardAutoShowIsEnabled", "true")); + System.getProperty("awt.touchKeyboardAutoShowIsEnabled", "true")); } /** @@ -231,9 +226,8 @@ public abstract KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() * } */ - @SuppressWarnings("removal") private static final ReentrantLock AWT_LOCK = new ReentrantLock( - AccessController.doPrivileged(new GetBooleanAction("awt.lock.fair"))); + Boolean.getBoolean("awt.lock.fair")); private static final Condition AWT_LOCK_COND = AWT_LOCK.newCondition(); public static final void awtLock() { @@ -525,7 +519,6 @@ public static void executeOnEventHandlerThread(Object target, * Fixed 5064013: the InvocationEvent time should be equals * the time of the ActionEvent */ - @SuppressWarnings("serial") public static void executeOnEventHandlerThread(Object target, Runnable runnable, final long when) { @@ -673,18 +666,16 @@ private void disableBackgroundEraseImpl(Component component) { * Returns the value of "sun.awt.noerasebackground" property. Default * value is {@code false}. */ - @SuppressWarnings("removal") public static boolean getSunAwtNoerasebackground() { - return AccessController.doPrivileged(new GetBooleanAction("sun.awt.noerasebackground")); + return Boolean.getBoolean("sun.awt.noerasebackground"); } /** * Returns the value of "sun.awt.erasebackgroundonresize" property. Default * value is {@code false}. */ - @SuppressWarnings("removal") public static boolean getSunAwtErasebackgroundonresize() { - return AccessController.doPrivileged(new GetBooleanAction("sun.awt.erasebackgroundonresize")); + return Boolean.getBoolean("sun.awt.erasebackgroundonresize"); } @@ -1158,15 +1149,12 @@ public boolean enableInputMethodsForTextComponent() { /** * Returns the locale in which the runtime was started. */ - @SuppressWarnings("removal") public static Locale getStartupLocale() { if (startupLocale == null) { String language, region, country, variant; - language = AccessController.doPrivileged( - new GetPropertyAction("user.language", "en")); + language = System.getProperty("user.language", "en"); // for compatibility, check for old user.region property - region = AccessController.doPrivileged( - new GetPropertyAction("user.region")); + region = System.getProperty("user.region"); if (region != null) { // region can be of form country, country_variant, or _variant int i = region.indexOf('_'); @@ -1178,10 +1166,8 @@ public static Locale getStartupLocale() { variant = ""; } } else { - country = AccessController.doPrivileged( - new GetPropertyAction("user.country", "")); - variant = AccessController.doPrivileged( - new GetPropertyAction("user.variant", "")); + country = System.getProperty("user.country", ""); + variant = System.getProperty("user.variant", ""); } startupLocale = Locale.of(language, country, variant); } @@ -1202,9 +1188,7 @@ public Locale getDefaultKeyboardLocale() { * @return {@code true}, if XEmbed is needed, {@code false} otherwise */ public static boolean needsXEmbed() { - @SuppressWarnings("removal") - String noxembed = AccessController. - doPrivileged(new GetPropertyAction("sun.awt.noxembed", "false")); + String noxembed = System.getProperty("sun.awt.noxembed", "false"); if ("true".equals(noxembed)) { return false; } @@ -1236,9 +1220,8 @@ protected boolean needsXEmbedImpl() { * developer. If true, Toolkit should return an * XEmbed-server-enabled CanvasPeer instead of the ordinary CanvasPeer. */ - @SuppressWarnings("removal") protected final boolean isXEmbedServerRequested() { - return AccessController.doPrivileged(new GetBooleanAction("sun.awt.xembedserver")); + return Boolean.getBoolean("sun.awt.xembedserver"); } /** @@ -1569,7 +1552,6 @@ private boolean isEQEmpty() { * Should return {@code true} if more processing is * necessary, {@code false} otherwise. */ - @SuppressWarnings("serial") private final boolean waitForIdle(final long end) { if (timeout(end) <= 0) { return false; @@ -1758,16 +1740,13 @@ private static RenderingHints getDesktopAAHintsByName(String hintname) { * to be inapplicable in that case. In that headless case although * this method will return "true" the toolkit will return a null map. */ - @SuppressWarnings("removal") private static boolean useSystemAAFontSettings() { if (!checkedSystemAAFontSettings) { useSystemAAFontSettings = true; /* initially set this true */ String systemAAFonts = null; Toolkit tk = Toolkit.getDefaultToolkit(); if (tk instanceof SunToolkit) { - systemAAFonts = - AccessController.doPrivileged( - new GetPropertyAction("awt.useSystemAAFontSettings")); + systemAAFonts = System.getProperty("awt.useSystemAAFontSettings"); } if (systemAAFonts != null) { useSystemAAFontSettings = Boolean.parseBoolean(systemAAFonts); @@ -1861,11 +1840,9 @@ public static Window getContainingWindow(Component comp) { * Returns the value of "sun.awt.disableMixing" property. Default * value is {@code false}. */ - @SuppressWarnings("removal") public static synchronized boolean getSunAwtDisableMixing() { if (sunAwtDisableMixing == null) { - sunAwtDisableMixing = AccessController.doPrivileged( - new GetBooleanAction("sun.awt.disableMixing")); + sunAwtDisableMixing = Boolean.getBoolean("sun.awt.disableMixing"); } return sunAwtDisableMixing.booleanValue(); } diff --git a/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java b/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java index 23520de9eea..5014bb78ead 100644 --- a/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java +++ b/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java @@ -62,10 +62,6 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; import java.util.AbstractMap; import java.util.ArrayList; @@ -985,7 +981,6 @@ private static byte[] convertObjectToBytes(Object object) throws IOException { @SuppressWarnings("removal") private String removeSuspectedData(DataFlavor flavor, final Transferable contents, final String str) - throws IOException { if (null == System.getSecurityManager() || !flavor.isMimeTypeEqual("text/uri-list")) @@ -994,34 +989,25 @@ private String removeSuspectedData(DataFlavor flavor, final Transferable content } final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents); + StringBuilder allowedFiles = new StringBuilder(str.length()); + String [] uriArray = str.split("(\\s)+"); - try { - return AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - - StringBuilder allowedFiles = new StringBuilder(str.length()); - String [] uriArray = str.split("(\\s)+"); - - for (String fileName : uriArray) + for (String fileName : uriArray) + { + File file = new File(fileName); + if (file.exists() && + !(isFileInWebstartedCache(file) || + isForbiddenToRead(file, userProtectionDomain))) + { + if (0 != allowedFiles.length()) { - File file = new File(fileName); - if (file.exists() && - !(isFileInWebstartedCache(file) || - isForbiddenToRead(file, userProtectionDomain))) - { - if (0 != allowedFiles.length()) - { - allowedFiles.append("\\r\\n"); - } - - allowedFiles.append(fileName); - } + allowedFiles.append("\\r\\n"); } - return allowedFiles.toString(); - }); - } catch (PrivilegedActionException pae) { - throw new IOException(pae.getMessage(), pae); + allowedFiles.append(fileName); + } } + return allowedFiles.toString(); } private static ProtectionDomain getUserProtectionDomain(Transferable contents) { @@ -1047,25 +1033,19 @@ private boolean isForbiddenToRead (File file, ProtectionDomain protectionDomain) @SuppressWarnings("removal") private ArrayList castToFiles(final List files, final ProtectionDomain userProtectionDomain) throws IOException { - try { - return AccessController.doPrivileged((PrivilegedExceptionAction>) () -> { - ArrayList fileList = new ArrayList<>(); - for (Object fileObject : files) - { - File file = castToFile(fileObject); - if (file != null && - (null == System.getSecurityManager() || - !(isFileInWebstartedCache(file) || - isForbiddenToRead(file, userProtectionDomain)))) - { - fileList.add(file.getCanonicalPath()); - } - } - return fileList; - }); - } catch (PrivilegedActionException pae) { - throw new IOException(pae.getMessage()); + ArrayList fileList = new ArrayList<>(); + for (Object fileObject : files) + { + File file = castToFile(fileObject); + if (file != null && + (null == System.getSecurityManager() || + !(isFileInWebstartedCache(file) || + isForbiddenToRead(file, userProtectionDomain)))) + { + fileList.add(file.getCanonicalPath()); + } } + return fileList; } // It is important do not use user's successors @@ -1419,7 +1399,6 @@ public Object translateStream(InputStream str, DataFlavor flavor, * and also arbitrary Objects which have a constructor which takes an * instance of the Class as its sole parameter. */ - @SuppressWarnings("removal") private Object constructFlavoredObject(Object arg, DataFlavor flavor, Class clazz) throws IOException @@ -1429,15 +1408,7 @@ private Object constructFlavoredObject(Object arg, DataFlavor flavor, if (clazz.equals(dfrc)) { return arg; // simple case } else { - Constructor[] constructors; - - try { - constructors = AccessController.doPrivileged( - (PrivilegedAction[]>) dfrc::getConstructors); - } catch (SecurityException se) { - throw new IOException(se.getMessage()); - } - + Constructor[] constructors = dfrc.getConstructors(); Constructor constructor = Stream.of(constructors) .filter(c -> Modifier.isPublic(c.getModifiers())) .filter(c -> { diff --git a/src/java.desktop/share/classes/sun/awt/datatransfer/TransferableProxy.java b/src/java.desktop/share/classes/sun/awt/datatransfer/TransferableProxy.java index cf8660fa8fa..fffb3f98a3e 100644 --- a/src/java.desktop/share/classes/sun/awt/datatransfer/TransferableProxy.java +++ b/src/java.desktop/share/classes/sun/awt/datatransfer/TransferableProxy.java @@ -38,8 +38,6 @@ import java.io.OutputStream; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -111,28 +109,14 @@ final class ClassLoaderObjectOutputStream extends ObjectOutputStream { } protected void annotateClass(final Class cl) throws IOException { - @SuppressWarnings("removal") - ClassLoader classLoader = AccessController.doPrivileged( - new PrivilegedAction() { - public ClassLoader run() { - return cl.getClassLoader(); - } - }); - + ClassLoader classLoader = cl.getClassLoader(); Set s = new HashSet(1); s.add(cl.getName()); map.put(s, classLoader); } protected void annotateProxyClass(final Class cl) throws IOException { - @SuppressWarnings("removal") - ClassLoader classLoader = AccessController.doPrivileged( - new PrivilegedAction() { - public ClassLoader run() { - return cl.getClassLoader(); - } - }); - + ClassLoader classLoader = cl.getClassLoader(); Class[] interfaces = cl.getInterfaces(); Set s = new HashSet(interfaces.length); for (int i = 0; i < interfaces.length; i++) { diff --git a/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java b/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java index 3696d53945b..b937fb139a3 100644 --- a/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java +++ b/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java @@ -41,10 +41,6 @@ import java.awt.event.InvocationEvent; import java.awt.im.spi.InputMethodDescriptor; import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Hashtable; import java.util.Iterator; import java.util.Locale; @@ -252,24 +248,14 @@ private synchronized void waitForChangeRequest() { * initializes the input method locator list for all * installed input method descriptors. */ - @SuppressWarnings("removal") private void initializeInputMethodLocatorList() { synchronized (javaInputMethodLocatorList) { javaInputMethodLocatorList.clear(); - try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() { - for (InputMethodDescriptor descriptor : - ServiceLoader.load(InputMethodDescriptor.class, - ClassLoader.getSystemClassLoader())) { - ClassLoader cl = descriptor.getClass().getClassLoader(); - javaInputMethodLocatorList.add(new InputMethodLocator(descriptor, cl, null)); - } - return null; - } - }); - } catch (PrivilegedActionException e) { - e.printStackTrace(); + for (InputMethodDescriptor descriptor : + ServiceLoader.load(InputMethodDescriptor.class, + ClassLoader.getSystemClassLoader())) { + ClassLoader cl = descriptor.getClass().getClassLoader(); + javaInputMethodLocatorList.add(new InputMethodLocator(descriptor, cl, null)); } javaInputMethodCount = javaInputMethodLocatorList.size(); } @@ -594,13 +580,8 @@ private void writePreferredInputMethod(String path, String descriptorName) { } } - @SuppressWarnings("removal") private Preferences getUserRoot() { - return AccessController.doPrivileged(new PrivilegedAction() { - public Preferences run() { - return Preferences.userRoot(); - } - }); + return Preferences.userRoot(); } private Locale getAdvertisedLocale(InputMethodLocator locator, Locale locale) { diff --git a/src/java.desktop/share/classes/sun/awt/im/InputContext.java b/src/java.desktop/share/classes/sun/awt/im/InputContext.java index 6d3dc248abf..00703eb44c3 100644 --- a/src/java.desktop/share/classes/sun/awt/im/InputContext.java +++ b/src/java.desktop/share/classes/sun/awt/im/InputContext.java @@ -44,8 +44,6 @@ import java.awt.im.InputMethodRequests; import java.awt.im.spi.InputMethod; import java.lang.Character.Subset; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.text.MessageFormat; import java.util.Collection; import java.util.HashMap; @@ -1036,22 +1034,16 @@ public void windowDeactivated(WindowEvent e) {} /** * Initializes the input method selection key definition in preference trees */ - @SuppressWarnings("removal") private void initializeInputMethodSelectionKey() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - // Look in user's tree - Preferences root = Preferences.userRoot(); - inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root); - - if (inputMethodSelectionKey == null) { - // Look in system's tree - root = Preferences.systemRoot(); - inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root); - } - return null; - } - }); + // Look in user's tree + Preferences root = Preferences.userRoot(); + inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root); + + if (inputMethodSelectionKey == null) { + // Look in system's tree + root = Preferences.systemRoot(); + inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root); + } } private AWTKeyStroke getInputMethodSelectionKeyStroke(Preferences root) { diff --git a/src/java.desktop/share/classes/sun/awt/im/InputMethodContext.java b/src/java.desktop/share/classes/sun/awt/im/InputMethodContext.java index 96d53178783..a0f9baa3112 100644 --- a/src/java.desktop/share/classes/sun/awt/im/InputMethodContext.java +++ b/src/java.desktop/share/classes/sun/awt/im/InputMethodContext.java @@ -37,7 +37,6 @@ import java.awt.font.TextHitInfo; import java.awt.im.InputMethodRequests; import java.awt.im.spi.InputMethod; -import java.security.AccessController; import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator.Attribute; import java.text.AttributedString; @@ -72,9 +71,7 @@ public class InputMethodContext static { // check whether we should use below-the-spot input // get property from command line - @SuppressWarnings("removal") - String inputStyle = AccessController.doPrivileged - (new GetPropertyAction("java.awt.im.style", null)); + String inputStyle = System.getProperty("java.awt.im.style"); // get property from awt.properties file if (inputStyle == null) { inputStyle = Toolkit.getProperty("java.awt.im.style", null); diff --git a/src/java.desktop/share/classes/sun/awt/image/ImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/ImageDecoder.java index d09cfd9b2d8..c3691773f6e 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/ImageDecoder.java @@ -159,18 +159,11 @@ protected int imageComplete(int status, boolean done) { public abstract void produceImage() throws IOException, ImageFormatException; - @SuppressWarnings("removal") public void abort() { aborted = true; source.doneDecoding(this); close(); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - feeder.interrupt(); - return null; - } - }); + feeder.interrupt(); } public synchronized void close() { diff --git a/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java b/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java index e527dbfcb3f..88e830a2bf5 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java +++ b/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java @@ -276,7 +276,6 @@ private static void stoppingAnimation(Thread me) { /** * Create and start ImageFetcher threads in the appropriate ThreadGroup. */ - @SuppressWarnings("removal") private static void createFetchers(final FetcherInfo info) { // We need to instantiate a new ImageFetcher thread. // First, figure out which ThreadGroup we'll put the @@ -310,25 +309,18 @@ private static void createFetchers(final FetcherInfo info) { } final ThreadGroup fetcherGroup = fetcherThreadGroup; - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - for (int i = 0; i < info.fetchers.length; i++) { - if (info.fetchers[i] == null) { - ImageFetcher f = new ImageFetcher(fetcherGroup, i); - try { - f.start(); - info.fetchers[i] = f; - info.numFetchers++; - break; - } catch (Error e) { - } - } - } - return null; + for (int i = 0; i < info.fetchers.length; i++) { + if (info.fetchers[i] == null) { + ImageFetcher f = new ImageFetcher(fetcherGroup, i); + try { + f.start(); + info.fetchers[i] = f; + info.numFetchers++; + break; + } catch (Error e) { } - }); - return; + } + } } } diff --git a/src/java.desktop/share/classes/sun/awt/image/ImageWatched.java b/src/java.desktop/share/classes/sun/awt/image/ImageWatched.java index 0a1dd47fb55..c3198ac704b 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ImageWatched.java +++ b/src/java.desktop/share/classes/sun/awt/image/ImageWatched.java @@ -29,10 +29,6 @@ import java.awt.Image; import java.awt.image.ImageObserver; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; - public abstract class ImageWatched { public static Link endlink = new Link(); @@ -89,28 +85,16 @@ public boolean newInfo(Image img, int info, } } - static class AccWeakReference extends WeakReference { - - @SuppressWarnings("removal") - private final AccessControlContext acc; - - @SuppressWarnings("removal") - AccWeakReference(T ref) { - super(ref); - acc = AccessController.getContext(); - } - } - /* * Standard Link implementation to manage a Weak Reference * to an ImageObserver. */ public static class WeakLink extends Link { - private final AccWeakReference myref; + private final WeakReference myref; private Link next; public WeakLink(ImageObserver obs, Link next) { - myref = new AccWeakReference(obs); + myref = new WeakReference(obs); this.next = next; } @@ -136,20 +120,6 @@ public Link removeWatcher(ImageObserver iw) { return this; } - @SuppressWarnings("removal") - private static boolean update(ImageObserver iw, AccessControlContext acc, - Image img, int info, - int x, int y, int w, int h) { - - if (acc != null || System.getSecurityManager() != null) { - return AccessController.doPrivileged( - (PrivilegedAction) () -> { - return iw.imageUpdate(img, info, x, y, w, h); - }, acc); - } - return false; - } - public boolean newInfo(Image img, int info, int x, int y, int w, int h) { @@ -159,7 +129,7 @@ public boolean newInfo(Image img, int info, if (myiw == null) { // My referent is null so we must prune in a second pass. ret = true; - } else if (update(myiw, myref.acc, img, info, x, y, w, h) == false) { + } else if (myiw.imageUpdate(img, info, x, y, w, h) == false) { // My referent has lost interest so clear it and ask // for a pruning pass to remove it later. myref.clear(); diff --git a/src/java.desktop/share/classes/sun/awt/image/ImagingLib.java b/src/java.desktop/share/classes/sun/awt/image/ImagingLib.java index a98e6fc81fb..d37afcb7a8b 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ImagingLib.java +++ b/src/java.desktop/share/classes/sun/awt/image/ImagingLib.java @@ -37,8 +37,6 @@ import java.awt.image.RasterOp; import java.awt.image.Raster; import java.awt.image.WritableRaster; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * This class provides a hook to access platform-specific @@ -51,7 +49,7 @@ * (in which case our java code will be executed) or may throw * an exception. */ -@SuppressWarnings({"removal", "restricted"}) +@SuppressWarnings("restricted") public class ImagingLib { static boolean useLib = true; @@ -90,20 +88,14 @@ public static native int lookupByteRaster(Raster src, Raster dst, static { - PrivilegedAction doMlibInitialization = - new PrivilegedAction() { - public Boolean run() { - try { - System.loadLibrary("mlib_image"); - } catch (UnsatisfiedLinkError e) { - return Boolean.FALSE; - } - boolean success = init(); - return Boolean.valueOf(success); - } - }; + boolean success = false; + try { + System.loadLibrary("mlib_image"); + success = init(); + } catch (UnsatisfiedLinkError e) { + } - useLib = AccessController.doPrivileged(doMlibInitialization); + useLib = success; // // Cache the class references of the operations we know about diff --git a/src/java.desktop/share/classes/sun/awt/image/JPEGImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/JPEGImageDecoder.java index b976a716ded..eb1023bd694 100644 --- a/src/java.desktop/share/classes/sun/awt/image/JPEGImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/JPEGImageDecoder.java @@ -42,7 +42,7 @@ * * @author Jim Graham */ -@SuppressWarnings({"removal", "restricted"}) +@SuppressWarnings("restricted") public class JPEGImageDecoder extends ImageDecoder { private static ColorModel RGBcolormodel; private static ColorModel ARGBcolormodel; @@ -54,13 +54,7 @@ public class JPEGImageDecoder extends ImageDecoder { private ColorModel colormodel; static { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("javajpeg"); - return null; - } - }); + System.loadLibrary("javajpeg"); initIDs(InputStreamClass); RGBcolormodel = new DirectColorModel(24, 0xff0000, 0xff00, 0xff); ARGBcolormodel = ColorModel.getRGBdefault(); diff --git a/src/java.desktop/share/classes/sun/awt/image/NativeLibLoader.java b/src/java.desktop/share/classes/sun/awt/image/NativeLibLoader.java index e1fe5658e63..d971bf6e40d 100644 --- a/src/java.desktop/share/classes/sun/awt/image/NativeLibLoader.java +++ b/src/java.desktop/share/classes/sun/awt/image/NativeLibLoader.java @@ -52,14 +52,8 @@ class NativeLibLoader { * For now, we know it's done by the implementation, and we assume * that the name of the library is "awt". -br. */ - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") static void loadLibraries() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); } } diff --git a/src/java.desktop/share/classes/sun/awt/image/VSyncedBSManager.java b/src/java.desktop/share/classes/sun/awt/image/VSyncedBSManager.java index 8bb34dd6279..88403ca06a3 100644 --- a/src/java.desktop/share/classes/sun/awt/image/VSyncedBSManager.java +++ b/src/java.desktop/share/classes/sun/awt/image/VSyncedBSManager.java @@ -35,11 +35,8 @@ public abstract class VSyncedBSManager { private static VSyncedBSManager theInstance; - @SuppressWarnings("removal") private static final boolean vSyncLimit = - Boolean.parseBoolean(java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "sun.java2d.vsynclimit", "true"))); + Boolean.parseBoolean(System.getProperty("sun.java2d.vsynclimit", "true")); private static VSyncedBSManager getInstance(boolean create) { if (theInstance == null && create) { diff --git a/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java b/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java index fa4a1450bb4..303b57626d6 100644 --- a/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java +++ b/src/java.desktop/share/classes/sun/awt/util/PerformanceLogger.java @@ -72,7 +72,6 @@ * exist once those APIs are in place. * @author Chet Haase */ -@SuppressWarnings("removal") public class PerformanceLogger { // Timing values of global interest @@ -87,16 +86,12 @@ public class PerformanceLogger { private static long baseTime; static { - String perfLoggingProp = - java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.perflog")); + String perfLoggingProp = System.getProperty("sun.perflog"); if (perfLoggingProp != null) { perfLoggingOn = true; // Check if we should use nanoTime - String perfNanoProp = - java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.perflog.nano")); + String perfNanoProp = System.getProperty("sun.perflog.nano"); if (perfNanoProp != null) { useNanoTime = true; } @@ -107,21 +102,15 @@ public class PerformanceLogger { } if (logFileName != null) { if (logWriter == null) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - try { - File logFile = new File(logFileName); - logFile.createNewFile(); - logWriter = new FileWriter(logFile); - } catch (Exception e) { - System.out.println(e + ": Creating logfile " + - logFileName + - ". Log to console"); - } - return null; - } - }); + try { + File logFile = new File(logFileName); + logFile.createNewFile(); + logWriter = new FileWriter(logFile); + } catch (Exception e) { + System.out.println(e + ": Creating logfile " + + logFileName + + ". Log to console"); + } } } if (logWriter == null) { diff --git a/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java b/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java index 61f48e8d098..a144f14f4a9 100644 --- a/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java +++ b/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java @@ -27,8 +27,6 @@ import java.io.File; import java.io.OutputStream; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Semaphore; @@ -112,25 +110,21 @@ private static class TempFileDeletionHook { private static HashMap files = new HashMap<>(); private static Thread t = null; - @SuppressWarnings("removal") static void init() { if (t == null) { // Add a shutdown hook to remove the temp file. - AccessController.doPrivileged((PrivilegedAction) () -> { - /* The thread must be a member of a thread group - * which will not get GCed before VM exit. - * Make its parent the top-level thread group. - */ - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - t = new Thread(rootTG, TempFileDeletionHook::runHooks, - "TempFontFileDeleter", 0, false); - /* Set context class loader to null in order to avoid - * keeping a strong reference to an application classloader. - */ - t.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(t); - return null; - }); + /* The thread must be a member of a thread group + * which will not get GCed before VM exit. + * Make its parent the top-level thread group. + */ + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + t = new Thread(rootTG, TempFileDeletionHook::runHooks, + "TempFontFileDeleter", 0, false); + /* Set context class loader to null in order to avoid + * keeping a strong reference to an application classloader. + */ + t.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(t); } } diff --git a/src/java.desktop/share/classes/sun/font/FileFont.java b/src/java.desktop/share/classes/sun/font/FileFont.java index da5874518fa..47c6ea181f4 100644 --- a/src/java.desktop/share/classes/sun/font/FileFont.java +++ b/src/java.desktop/share/classes/sun/font/FileFont.java @@ -35,11 +35,7 @@ import sun.java2d.Disposer; import sun.java2d.DisposerRecord; -import java.io.IOException; import java.util.List; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; public abstract class FileFont extends PhysicalFont { @@ -252,84 +248,35 @@ private CreatedFontFileDisposerRecord(File file, int cnt, this.tracker = tracker; } - @SuppressWarnings("removal") public void dispose() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - synchronized (fontFile) { - count--; - if (count > 0) { - return null; - } - } - if (fontFile != null) { - try { - if (tracker != null) { - tracker.subBytes((int)fontFile.length()); - } - /* REMIND: is it possible that the file is - * still open? It will be closed when the - * font2D is disposed but could this code - * execute first? If so the file would not - * be deleted on MS-windows. - */ - fontFile.delete(); - /* remove from delete on exit hook list : */ - // FIXME: still need to be refactored - SunFontManager.getInstance().tmpFontFiles.remove(fontFile); - } catch (Exception e) { - } - } - return null; + synchronized (fontFile) { + count--; + if (count > 0) { + return; + } + } + if (fontFile != null) { + try { + if (tracker != null) { + tracker.subBytes((int)fontFile.length()); } - }); + /* REMIND: is it possible that the file is + * still open? It will be closed when the + * font2D is disposed but could this code + * execute first? If so the file would not + * be deleted on MS-windows. + */ + fontFile.delete(); + /* remove from delete on exit hook list : */ + // FIXME: still need to be refactored + SunFontManager.getInstance().tmpFontFiles.remove(fontFile); + } catch (Exception e) { + } + } } } - @SuppressWarnings("removal") protected String getPublicFileName() { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { return platName; - } - boolean canReadProperty = true; - - try { - sm.checkPropertyAccess("java.io.tmpdir"); - } catch (SecurityException e) { - canReadProperty = false; - } - - if (canReadProperty) { - return platName; - } - - final File f = new File(platName); - - Boolean isTmpFile = Boolean.FALSE; - try { - isTmpFile = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Boolean run() { - File tmp = new File(System.getProperty("java.io.tmpdir")); - try { - String tpath = tmp.getCanonicalPath(); - String fpath = f.getCanonicalPath(); - - return (fpath == null) || fpath.startsWith(tpath); - } catch (IOException e) { - return Boolean.TRUE; - } - } - } - ); - } catch (PrivilegedActionException e) { - // unable to verify whether value of java.io.tempdir will be - // exposed, so return only a name of the font file. - isTmpFile = Boolean.TRUE; - } - - return isTmpFile ? "temp file" : platName; } } diff --git a/src/java.desktop/share/classes/sun/font/FontManagerNativeLibrary.java b/src/java.desktop/share/classes/sun/font/FontManagerNativeLibrary.java index 9439f6ed857..51997571e75 100644 --- a/src/java.desktop/share/classes/sun/font/FontManagerNativeLibrary.java +++ b/src/java.desktop/share/classes/sun/font/FontManagerNativeLibrary.java @@ -27,39 +27,32 @@ import sun.awt.OSInfo; -@SuppressWarnings({"removal", "restricted"}) +@SuppressWarnings("restricted") public class FontManagerNativeLibrary { static { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - /* REMIND do we really have to load awt here? */ - System.loadLibrary("awt"); - if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { - /* Ideally fontmanager library should not depend on - particular implementation of the font scaler. - However, freetype scaler is basically small wrapper on - top of freetype library (that is used in binary form). + /* REMIND do we really have to load awt here? */ + System.loadLibrary("awt"); + if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { + /* Ideally fontmanager library should not depend on + particular implementation of the font scaler. + However, freetype scaler is basically small wrapper on + top of freetype library (that is used in binary form). - This wrapper is compiled into fontmanager and this make - fontmanger library depending on freetype library. + This wrapper is compiled into fontmanager and this make + fontmanger library depending on freetype library. - On Windows DLL's in the JRE's BIN directory cannot be - found by windows DLL loading as that directory is not - on the Windows PATH. + On Windows DLL's in the JRE's BIN directory cannot be + found by windows DLL loading as that directory is not + on the Windows PATH. - To avoid link error we have to load freetype explicitly - before we load fontmanager. + To avoid link error we have to load freetype explicitly + before we load fontmanager. - NB: consider moving freetype wrapper part to separate - shared library in order to avoid dependency. */ - System.loadLibrary("freetype"); - } - System.loadLibrary("fontmanager"); - - return null; - } - }); + NB: consider moving freetype wrapper part to separate + shared library in order to avoid dependency. */ + System.loadLibrary("freetype"); + } + System.loadLibrary("fontmanager"); } /* diff --git a/src/java.desktop/share/classes/sun/font/FontUtilities.java b/src/java.desktop/share/classes/sun/font/FontUtilities.java index bdccf99d1ed..30ec4f3db81 100644 --- a/src/java.desktop/share/classes/sun/font/FontUtilities.java +++ b/src/java.desktop/share/classes/sun/font/FontUtilities.java @@ -28,9 +28,7 @@ import java.awt.Font; import java.lang.ref.SoftReference; import java.util.concurrent.ConcurrentHashMap; -import java.security.AccessController; -import java.security.PrivilegedAction; import javax.swing.plaf.FontUIResource; import sun.awt.OSInfo; @@ -59,65 +57,57 @@ public final class FontUtilities { initStatic(); } - @SuppressWarnings("removal") + @SuppressWarnings("deprecation") // PlatformLogger.setLevel is deprecated. private static void initStatic() { - AccessController.doPrivileged(new PrivilegedAction() { - @SuppressWarnings("deprecation") // PlatformLogger.setLevel is deprecated. - @Override - public Object run() { - - isLinux = OSInfo.getOSType() == OSInfo.OSType.LINUX; - - isMacOSX = OSInfo.getOSType() == OSInfo.OSType.MACOSX; - if (isMacOSX) { - // os.version has values like 10.13.6, 10.14.6 - // If it is not positively recognised as 10.13 or less, - // assume it means 10.14 or some later version. - isMacOSX14 = true; - String version = System.getProperty("os.version", ""); - if (version.startsWith("10.")) { - version = version.substring(3); - int periodIndex = version.indexOf('.'); - if (periodIndex != -1) { - version = version.substring(0, periodIndex); - } - try { - int v = Integer.parseInt(version); - isMacOSX14 = (v >= 14); - } catch (NumberFormatException e) { - } - } - } - /* If set to "jdk", use the JDK's scaler rather than - * the platform one. This may be a no-op on platforms where - * JDK has been configured so that it always relies on the - * platform scaler. The principal case where it has an - * effect is that on Windows, 2D will never use GDI. - */ - String scalerStr = System.getProperty("sun.java2d.font.scaler"); - if (scalerStr != null) { - useJDKScaler = "jdk".equals(scalerStr); - } else { - useJDKScaler = false; + + isLinux = OSInfo.getOSType() == OSInfo.OSType.LINUX; + + isMacOSX = OSInfo.getOSType() == OSInfo.OSType.MACOSX; + if (isMacOSX) { + // os.version has values like 10.13.6, 10.14.6 + // If it is not positively recognised as 10.13 or less, + // assume it means 10.14 or some later version. + isMacOSX14 = true; + String version = System.getProperty("os.version", ""); + if (version.startsWith("10.")) { + version = version.substring(3); + int periodIndex = version.indexOf('.'); + if (periodIndex != -1) { + version = version.substring(0, periodIndex); } - isWindows = OSInfo.getOSType() == OSInfo.OSType.WINDOWS; - String debugLevel = - System.getProperty("sun.java2d.debugfonts"); - - if (debugLevel != null && !debugLevel.equals("false")) { - debugFonts = true; - logger = PlatformLogger.getLogger("sun.java2d"); - if (debugLevel.equals("warning")) { - logger.setLevel(PlatformLogger.Level.WARNING); - } else if (debugLevel.equals("severe")) { - logger.setLevel(PlatformLogger.Level.SEVERE); - } - logging = logger.isEnabled(); + try { + int v = Integer.parseInt(version); + isMacOSX14 = (v >= 14); + } catch (NumberFormatException e) { } - - return null; + } + } + /* If set to "jdk", use the JDK's scaler rather than + * the platform one. This may be a no-op on platforms where + * JDK has been configured so that it always relies on the + * platform scaler. The principal case where it has an + * effect is that on Windows, 2D will never use GDI. + */ + String scalerStr = System.getProperty("sun.java2d.font.scaler"); + if (scalerStr != null) { + useJDKScaler = "jdk".equals(scalerStr); + } else { + useJDKScaler = false; + } + isWindows = OSInfo.getOSType() == OSInfo.OSType.WINDOWS; + String debugLevel = + System.getProperty("sun.java2d.debugfonts"); + + if (debugLevel != null && !debugLevel.equals("false")) { + debugFonts = true; + logger = PlatformLogger.getLogger("sun.java2d"); + if (debugLevel.equals("warning")) { + logger.setLevel(PlatformLogger.Level.WARNING); + } else if (debugLevel.equals("severe")) { + logger.setLevel(PlatformLogger.Level.SEVERE); } - }); + logging = logger.isEnabled(); + } } /** diff --git a/src/java.desktop/share/classes/sun/font/StrikeCache.java b/src/java.desktop/share/classes/sun/font/StrikeCache.java index ea1369b4383..c0859c4c0af 100644 --- a/src/java.desktop/share/classes/sun/font/StrikeCache.java +++ b/src/java.desktop/share/classes/sun/font/StrikeCache.java @@ -263,7 +263,6 @@ static final byte getPixelByte(MemorySegment pixelData, long index) { initStatic(); } - @SuppressWarnings("removal") private static void initStatic() { if (nativeAddressSize < 4) { @@ -271,37 +270,28 @@ private static void initStatic() { nativeAddressSize); } - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - - /* Allow a client to override the reference type used to - * cache strikes. The default is "soft" which hints to keep - * the strikes around. This property allows the client to - * override this to "weak" which hint to the GC to free - * memory more aggressively. - */ - String refType = - System.getProperty("sun.java2d.font.reftype", "soft"); - cacheRefTypeWeak = refType.equals("weak"); - - String minStrikesStr = - System.getProperty("sun.java2d.font.minstrikes"); - if (minStrikesStr != null) { - try { - MINSTRIKES = Integer.parseInt(minStrikesStr); - if (MINSTRIKES <= 0) { - MINSTRIKES = 1; - } - } catch (NumberFormatException e) { - } + /* Allow a client to override the reference type used to + * cache strikes. The default is "soft" which hints to keep + * the strikes around. This property allows the client to + * override this to "weak" which hint to the GC to free + * memory more aggressively. + */ + String refType = System.getProperty("sun.java2d.font.reftype", "soft"); + cacheRefTypeWeak = refType.equals("weak"); + + String minStrikesStr = + System.getProperty("sun.java2d.font.minstrikes"); + if (minStrikesStr != null) { + try { + MINSTRIKES = Integer.parseInt(minStrikesStr); + if (MINSTRIKES <= 0) { + MINSTRIKES = 1; } - - recentStrikes = new FontStrike[MINSTRIKES]; - - return null; + } catch (NumberFormatException e) { } - }); + } + + recentStrikes = new FontStrike[MINSTRIKES]; } diff --git a/src/java.desktop/share/classes/sun/font/SunFontManager.java b/src/java.desktop/share/classes/sun/font/SunFontManager.java index 3aec139b56d..06dc4a90820 100644 --- a/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java @@ -33,8 +33,6 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -262,30 +260,24 @@ public FilenameFilter getType1Filter() { initStatic(); } - @SuppressWarnings("removal") private static void initStatic() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - FontManagerNativeLibrary.load(); - - // JNI throws an exception if a class/method/field is not found, - // so there's no need to do anything explicit here. - initIDs(); - - switch (StrikeCache.nativeAddressSize) { - case 8: longAddresses = true; break; - case 4: longAddresses = false; break; - default: throw new RuntimeException("Unexpected address size"); - } + FontManagerNativeLibrary.load(); - noType1Font = "true".equals(System.getProperty("sun.java2d.noType1Font")); - jreLibDirName = System.getProperty("java.home","") + File.separator + "lib"; - jreFontDirName = jreLibDirName + File.separator + "fonts"; + // JNI throws an exception if a class/method/field is not found, + // so there's no need to do anything explicit here. + initIDs(); - maxSoftRefCnt = Integer.getInteger("sun.java2d.font.maxSoftRefs", 10); - return null; - } - }); + switch (StrikeCache.nativeAddressSize) { + case 8: longAddresses = true; break; + case 4: longAddresses = false; break; + default: throw new RuntimeException("Unexpected address size"); + } + + noType1Font = "true".equals(System.getProperty("sun.java2d.noType1Font")); + jreLibDirName = System.getProperty("java.home","") + File.separator + "lib"; + jreFontDirName = jreLibDirName + File.separator + "fonts"; + + maxSoftRefCnt = Integer.getInteger("sun.java2d.font.maxSoftRefs", 10); } /** @@ -304,150 +296,142 @@ public TrueTypeFont getEUDCFont() { /* Initialise ptrs used by JNI methods */ private static native void initIDs(); - @SuppressWarnings("removal") protected SunFontManager() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - File badFontFile = - new File(jreFontDirName + File.separator + "badfonts.txt"); - if (badFontFile.exists()) { - badFonts = new ArrayList<>(); - try (FileInputStream fis = new FileInputStream(badFontFile); - BufferedReader br = new BufferedReader(new InputStreamReader(fis))) { - while (true) { - String name = br.readLine(); - if (name == null) { - break; - } else { - if (FontUtilities.debugFonts()) { - FontUtilities.logWarning("read bad font: " + name); - } - badFonts.add(name); - } + File badFontFile = + new File(jreFontDirName + File.separator + "badfonts.txt"); + if (badFontFile.exists()) { + badFonts = new ArrayList<>(); + try (FileInputStream fis = new FileInputStream(badFontFile); + BufferedReader br = new BufferedReader(new InputStreamReader(fis))) { + while (true) { + String name = br.readLine(); + if (name == null) { + break; + } else { + if (FontUtilities.debugFonts()) { + FontUtilities.logWarning("read bad font: " + name); } - } catch (IOException e) { + badFonts.add(name); } } + } catch (IOException e) { + } + } - /* Here we get the fonts in jre/lib/fonts and register - * them so they are always available and preferred over - * other fonts. This needs to be registered before the - * composite fonts as otherwise some native font that - * corresponds may be found as we don't have a way to - * handle two fonts of the same name, so the JRE one - * must be the first one registered. Pass "true" to - * registerFonts method as on-screen these JRE fonts - * always go through the JDK rasteriser. - */ - if (FontUtilities.isLinux) { - /* Linux font configuration uses these fonts */ - registerFontDir(jreFontDirName); - } - registerFontsInDir(jreFontDirName, true, Font2D.JRE_RANK, - true, false); - - /* Create the font configuration and get any font path - * that might be specified. - */ - fontConfig = createFontConfiguration(); - - String[] fontInfo = getDefaultPlatformFont(); - defaultFontName = fontInfo[0]; - if (defaultFontName == null && FontUtilities.debugFonts()) { - FontUtilities.logWarning("defaultFontName is null"); - } - defaultFontFileName = fontInfo[1]; - - String extraFontPath = fontConfig.getExtraFontPath(); - - /* In prior releases the debugging font path replaced - * all normally located font directories except for the - * JRE fonts dir. This directory is still always located - * and placed at the head of the path but as an - * augmentation to the previous behaviour the - * changes below allow you to additionally append to - * the font path by starting with append: or prepend by - * starting with a prepend: sign. Eg: to append - * -Dsun.java2d.fontpath=append:/usr/local/myfonts - * and to prepend - * -Dsun.java2d.fontpath=prepend:/usr/local/myfonts Disp - * - * If there is an appendedfontpath it in the font - * configuration it is used instead of searching the - * system for dirs. - * The behaviour of append and prepend is then similar - * to the normal case. ie it goes after what - * you prepend and * before what you append. If the - * sun.java2d.fontpath property is used, but it - * neither the append or prepend syntaxes is used then - * as except for the JRE dir the path is replaced and it - * is up to you to make sure that all the right - * directories are located. This is platform and - * locale-specific so its almost impossible to get - * right, so it should be used with caution. - */ - boolean prependToPath = false; - boolean appendToPath = false; - String dbgFontPath = System.getProperty("sun.java2d.fontpath"); - - if (dbgFontPath != null) { - if (dbgFontPath.startsWith("prepend:")) { - prependToPath = true; - dbgFontPath = - dbgFontPath.substring("prepend:".length()); - } else if (dbgFontPath.startsWith("append:")) { - appendToPath = true; - dbgFontPath = - dbgFontPath.substring("append:".length()); - } - } + /* Here we get the fonts in jre/lib/fonts and register + * them so they are always available and preferred over + * other fonts. This needs to be registered before the + * composite fonts as otherwise some native font that + * corresponds may be found as we don't have a way to + * handle two fonts of the same name, so the JRE one + * must be the first one registered. Pass "true" to + * registerFonts method as on-screen these JRE fonts + * always go through the JDK rasteriser. + */ + if (FontUtilities.isLinux) { + /* Linux font configuration uses these fonts */ + registerFontDir(jreFontDirName); + } + registerFontsInDir(jreFontDirName, true, Font2D.JRE_RANK, + true, false); - if (FontUtilities.debugFonts()) { - FontUtilities.logInfo("JRE font directory: " + jreFontDirName); - FontUtilities.logInfo("Extra font path: " + extraFontPath); - FontUtilities.logInfo("Debug font path: " + dbgFontPath); - } + /* Create the font configuration and get any font path + * that might be specified. + */ + fontConfig = createFontConfiguration(); + + String[] fontInfo = getDefaultPlatformFont(); + defaultFontName = fontInfo[0]; + if (defaultFontName == null && FontUtilities.debugFonts()) { + FontUtilities.logWarning("defaultFontName is null"); + } + defaultFontFileName = fontInfo[1]; + + String extraFontPath = fontConfig.getExtraFontPath(); + + /* In prior releases the debugging font path replaced + * all normally located font directories except for the + * JRE fonts dir. This directory is still always located + * and placed at the head of the path but as an + * augmentation to the previous behaviour the + * changes below allow you to additionally append to + * the font path by starting with append: or prepend by + * starting with a prepend: sign. Eg: to append + * -Dsun.java2d.fontpath=append:/usr/local/myfonts + * and to prepend + * -Dsun.java2d.fontpath=prepend:/usr/local/myfonts Disp + * + * If there is an appendedfontpath it in the font + * configuration it is used instead of searching the + * system for dirs. + * The behaviour of append and prepend is then similar + * to the normal case. ie it goes after what + * you prepend and * before what you append. If the + * sun.java2d.fontpath property is used, but it + * neither the append or prepend syntaxes is used then + * as except for the JRE dir the path is replaced and it + * is up to you to make sure that all the right + * directories are located. This is platform and + * locale-specific so its almost impossible to get + * right, so it should be used with caution. + */ + boolean prependToPath = false; + boolean appendToPath = false; + String dbgFontPath = System.getProperty("sun.java2d.fontpath"); - if (dbgFontPath != null) { - /* In debugging mode we register all the paths - * Caution: this is a very expensive call on Solaris:- - */ - fontPath = getPlatformFontPath(noType1Font); + if (dbgFontPath != null) { + if (dbgFontPath.startsWith("prepend:")) { + prependToPath = true; + dbgFontPath = + dbgFontPath.substring("prepend:".length()); + } else if (dbgFontPath.startsWith("append:")) { + appendToPath = true; + dbgFontPath = + dbgFontPath.substring("append:".length()); + } + } - if (extraFontPath != null) { - fontPath = extraFontPath + File.pathSeparator + fontPath; - } - if (appendToPath) { - fontPath += File.pathSeparator + dbgFontPath; - } else if (prependToPath) { - fontPath = dbgFontPath + File.pathSeparator + fontPath; - } else { - fontPath = dbgFontPath; - } - registerFontDirs(fontPath); - } else if (extraFontPath != null) { - /* If the font configuration contains an - * "appendedfontpath" entry, it is interpreted as a - * set of locations that should always be registered. - * It may be additional to locations normally found - * for that place, or it may be locations that need - * to have all their paths registered to locate all - * the needed platform names. - * This is typically when the same .TTF file is - * referenced from multiple font.dir files and all - * of these must be read to find all the native - * (XLFD) names for the font, so that X11 font APIs - * can be used for as many code points as possible. - */ - registerFontDirs(extraFontPath); - } + if (FontUtilities.debugFonts()) { + FontUtilities.logInfo("JRE font directory: " + jreFontDirName); + FontUtilities.logInfo("Extra font path: " + extraFontPath); + FontUtilities.logInfo("Debug font path: " + dbgFontPath); + } - initCompositeFonts(fontConfig, null); + if (dbgFontPath != null) { + /* In debugging mode we register all the paths + * Caution: this is a very expensive call on Solaris:- + */ + fontPath = getPlatformFontPath(noType1Font); - return null; + if (extraFontPath != null) { + fontPath = extraFontPath + File.pathSeparator + fontPath; } - }); + if (appendToPath) { + fontPath += File.pathSeparator + dbgFontPath; + } else if (prependToPath) { + fontPath = dbgFontPath + File.pathSeparator + fontPath; + } else { + fontPath = dbgFontPath; + } + registerFontDirs(fontPath); + } else if (extraFontPath != null) { + /* If the font configuration contains an + * "appendedfontpath" entry, it is interpreted as a + * set of locations that should always be registered. + * It may be additional to locations normally found + * for that place, or it may be locations that need + * to have all their paths registered to locate all + * the needed platform names. + * This is typically when the same .TTF file is + * referenced from multiple font.dir files and all + * of these must be read to find all the native + * (XLFD) names for the font, so that X11 font APIs + * can be used for as many code points as possible. + */ + registerFontDirs(extraFontPath); + } + initCompositeFonts(fontConfig, null); } public Font2DHandle getNewComposite(String family, int style, @@ -1095,7 +1079,6 @@ private static String dotStyleStr(int num) { private boolean haveCheckedUnreferencedFontFiles; - @SuppressWarnings("removal") private String[] getFontFilesFromPath(boolean noType1) { final FilenameFilter filter; if (noType1) { @@ -1103,34 +1086,30 @@ private String[] getFontFilesFromPath(boolean noType1) { } else { filter = new TTorT1Filter(); } - return AccessController.doPrivileged(new PrivilegedAction() { - public String[] run() { - if (pathDirs.length == 1) { - File dir = new File(pathDirs[0]); - String[] files = dir.list(filter); - if (files == null) { - return new String[0]; - } - for (int f=0; f fileList = new ArrayList<>(); - for (int i = 0; i< pathDirs.length; i++) { - File dir = new File(pathDirs[i]); - String[] files = dir.list(filter); - if (files == null) { - continue; - } - for (int f = 0; f < files.length ; f++) { - fileList.add(files[f].toLowerCase()); - } - } - return fileList.toArray(STR_ARRAY); + if (pathDirs.length == 1) { + File dir = new File(pathDirs[0]); + String[] files = dir.list(filter); + if (files == null) { + return new String[0]; + } + for (int f=0; f fileList = new ArrayList<>(); + for (int i = 0; i< pathDirs.length; i++) { + File dir = new File(pathDirs[i]); + String[] files = dir.list(filter); + if (files == null) { + continue; + } + for (int f = 0; f < files.length ; f++) { + fileList.add(files[f].toLowerCase()); } } - }); + return fileList.toArray(STR_ARRAY); + } } /* This is needed since some windows registry names don't match @@ -1430,7 +1409,6 @@ public HashMap populateHardcodedFileNameMap() { return new HashMap<>(0); } - @SuppressWarnings("removal") Font2D findFontFromPlatformMap(String lcName, int style) { HashMap platformFontMap = SunFontManager.platformFontMap; if (platformFontMap == null) { @@ -1524,20 +1502,16 @@ Font2D findFontFromPlatformMap(String lcName, int style) { final String[] files = { plainFile, boldFile, italicFile, boldItalicFile } ; - failure = AccessController.doPrivileged(new PrivilegedAction() { - public Boolean run() { - for (int i=0; i() { - public String run() { - for (int p = 0; p < pathDirs.length; p++) { - File f = new File(pathDirs[p] +File.separator+ s); - if (f.exists()) { - return f.getAbsolutePath(); - } - } - return null; - } - }); - if (path != null) { - return path; + for (int p = 0; p < pathDirs.length; p++) { + f = new File(pathDirs[p] + File.separator + s); + if (f.exists()) { + return f.getAbsolutePath(); + } } } return s; // shouldn't happen, but harmless @@ -2181,7 +2145,6 @@ private static boolean fontSupportsEncoding(Font font, String encoding) { private int createdFontCount = 0; - @SuppressWarnings("removal") public Font2D[] createFont2D(File fontFile, int fontFormat, boolean all, boolean isCopy, CreatedFontTracker tracker) throws FontFormatException { @@ -2229,15 +2192,10 @@ public Font2D[] createFont2D(File fontFile, int fontFormat, boolean all, } } catch (FontFormatException e) { if (isCopy) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - if (_tracker != null) { - _tracker.subBytes((int)fFile.length()); - } - fFile.delete(); - return null; - } - }); + if (_tracker != null) { + _tracker.subBytes((int)fFile.length()); + } + fFile.delete(); } throw(e); } @@ -2253,39 +2211,31 @@ public Void run() { if (fileCloser == null) { final Runnable fileCloserRunnable = new Runnable() { public void run() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - for (int i = 0;i < CHANNELPOOLSIZE; i++) { - if (fontFileCache[i] != null) { - try { - fontFileCache[i].close(); - } catch (Exception e) { - } - } + for (int i = 0;i < CHANNELPOOLSIZE; i++) { + if (fontFileCache[i] != null) { + try { + fontFileCache[i].close(); + } catch (Exception e) { } - if (tmpFontFiles != null) { - File[] files = new File[tmpFontFiles.size()]; - files = tmpFontFiles.toArray(files); - for (int f=0; f) () -> { - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - fileCloser = new Thread(rootTG, fileCloserRunnable, - "FileCloser", 0, false); - fileCloser.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(fileCloser); - return null; - }); + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + fileCloser = new Thread(rootTG, fileCloserRunnable, + "FileCloser", 0, false); + fileCloser.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(fileCloser); } } } @@ -2930,7 +2880,6 @@ public String getPlatformFontPath(boolean noType1Font) { return fontPath; } - @SuppressWarnings("removal") protected void loadFonts() { if (discoveredAllFonts) { return; @@ -2943,28 +2892,23 @@ protected void loadFonts() { } initialiseDeferredFonts(); - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - if (fontPath == null) { - fontPath = getPlatformFontPath(noType1Font); - registerFontDirs(fontPath); - } - if (fontPath != null) { - // this will find all fonts including those already - // registered. But we have checks in place to prevent - // double registration. - if (! gotFontsFromPlatform()) { - registerFontsOnPath(fontPath, false, - Font2D.UNKNOWN_RANK, - false, true); - loadedAllFontFiles = true; - } - } - registerOtherFontFiles(registeredFontFiles); - discoveredAllFonts = true; - return null; + if (fontPath == null) { + fontPath = getPlatformFontPath(noType1Font); + registerFontDirs(fontPath); + } + if (fontPath != null) { + // this will find all fonts including those already + // registered. But we have checks in place to prevent + // double registration. + if (! gotFontsFromPlatform()) { + registerFontsOnPath(fontPath, false, + Font2D.UNKNOWN_RANK, + false, true); + loadedAllFontFiles = true; } - }); + } + registerOtherFontFiles(registeredFontFiles); + discoveredAllFonts = true; } } @@ -3048,7 +2992,6 @@ public synchronized String getDefaultFontFaceName() { return defaultFontName; } - @SuppressWarnings("removal") public void loadFontFiles() { loadFonts(); if (loadedAllFontFiles) { @@ -3060,23 +3003,18 @@ public void loadFontFiles() { Thread.dumpStack(); FontUtilities.logInfo("loadAllFontFiles() called"); } - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - if (fontPath == null) { - fontPath = getPlatformFontPath(noType1Font); - } - if (fontPath != null) { - // this will find all fonts including those already - // registered. But we have checks in place to prevent - // double registration. - registerFontsOnPath(fontPath, false, - Font2D.UNKNOWN_RANK, - false, true); - } - loadedAllFontFiles = true; - return null; - } - }); + if (fontPath == null) { + fontPath = getPlatformFontPath(noType1Font); + } + if (fontPath != null) { + // this will find all fonts including those already + // registered. But we have checks in place to prevent + // double registration. + registerFontsOnPath(fontPath, false, + Font2D.UNKNOWN_RANK, + false, true); + } + loadedAllFontFiles = true; } } @@ -3402,16 +3340,9 @@ public String[] getInstalledFontFamilyNames(Locale requestedLocale) { // Provides an aperture to add native font family names to the map protected void addNativeFontFamilyNames(TreeMap familyNames, Locale requestedLocale) { } - @SuppressWarnings("removal") public void register1dot0Fonts() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - String type1Dir = "/usr/openwin/lib/X11/fonts/Type1"; - registerFontsInDir(type1Dir, true, Font2D.TYPE1_RANK, - false, false); - return null; - } - }); + String type1Dir = "/usr/openwin/lib/X11/fonts/Type1"; + registerFontsInDir(type1Dir, true, Font2D.TYPE1_RANK, false, false); } /* Really we need only the JRE fonts family names, but there's little @@ -3442,33 +3373,28 @@ protected void getJREFontFamilyNames(TreeMap familyNames, * on windows and uses that if set. */ private static Locale systemLocale = null; - @SuppressWarnings("removal") private static Locale getSystemStartupLocale() { if (systemLocale == null) { - systemLocale = AccessController.doPrivileged(new PrivilegedAction() { - public Locale run() { - /* On windows the system locale may be different than the - * user locale. This is an unsupported configuration, but - * in that case we want to return a dummy locale that will - * never cause a match in the usage of this API. This is - * important because Windows documents that the family - * names of fonts are enumerated using the language of - * the system locale. BY returning a dummy locale in that - * case we do not use the platform API which would not - * return us the names we want. - */ - String fileEncoding = System.getProperty("file.encoding", ""); - String sysEncoding = System.getProperty("sun.jnu.encoding"); - if (sysEncoding != null && !sysEncoding.equals(fileEncoding)) { - return Locale.ROOT; - } - - String language = System.getProperty("user.language", "en"); - String country = System.getProperty("user.country",""); - String variant = System.getProperty("user.variant",""); - return Locale.of(language, country, variant); - } - }); + /* On windows the system locale may be different than the + * user locale. This is an unsupported configuration, but + * in that case we want to return a dummy locale that will + * never cause a match in the usage of this API. This is + * important because Windows documents that the family + * names of fonts are enumerated using the language of + * the system locale. BY returning a dummy locale in that + * case we do not use the platform API which would not + * return us the names we want. + */ + String fileEncoding = System.getProperty("file.encoding", ""); + String sysEncoding = System.getProperty("sun.jnu.encoding"); + if (sysEncoding != null && !sysEncoding.equals(fileEncoding)) { + systemLocale = Locale.ROOT; + } else { + String language = System.getProperty("user.language", "en"); + String country = System.getProperty("user.country",""); + String variant = System.getProperty("user.variant",""); + systemLocale = Locale.of(language, country, variant); + } } return systemLocale; } diff --git a/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java b/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java index c291e45b558..f1d6de7d4bc 100644 --- a/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java +++ b/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java @@ -37,8 +37,6 @@ import java.awt.geom.Point2D; import java.lang.foreign.MemorySegment; import java.lang.ref.SoftReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.concurrent.ConcurrentHashMap; import java.util.WeakHashMap; @@ -167,10 +165,7 @@ private long getFacePtr(Font2D font2D) { static boolean useFFM = true; static { - @SuppressWarnings("removal") - String prop = AccessController.doPrivileged( - (PrivilegedAction) () -> - System.getProperty("sun.font.layout.ffm", "true")); + String prop = System.getProperty("sun.font.layout.ffm", "true"); useFFM = "true".equals(prop); } diff --git a/src/java.desktop/share/classes/sun/font/TrueTypeFont.java b/src/java.desktop/share/classes/sun/font/TrueTypeFont.java index 3895ec6ca82..a44a013b749 100644 --- a/src/java.desktop/share/classes/sun/font/TrueTypeFont.java +++ b/src/java.desktop/share/classes/sun/font/TrueTypeFont.java @@ -38,9 +38,6 @@ import java.nio.ShortBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; @@ -246,13 +243,7 @@ private synchronized FileChannel open(boolean usePool) FontUtilities.logInfo("open TTF: " + platName); } try { - @SuppressWarnings("removal") - RandomAccessFile raf = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public RandomAccessFile run() throws FileNotFoundException { - return new RandomAccessFile(platName, "r"); - } - }); + RandomAccessFile raf = new RandomAccessFile(platName, "r"); disposerRecord.channel = raf.getChannel(); fileSize = (int)disposerRecord.channel.size(); if (usePool) { @@ -261,13 +252,6 @@ public RandomAccessFile run() throws FileNotFoundException { ((SunFontManager) fm).addToPool(this); } } - } catch (PrivilegedActionException e) { - close(); - Throwable reason = e.getCause(); - if (reason == null) { - reason = e; - } - throw new FontFormatException(reason.toString()); } catch (ClosedChannelException e) { /* NIO I/O is interruptible, recurse to retry operation. * The call to channel.size() above can throw this exception. @@ -664,7 +648,6 @@ && getDirectoryEntry(hheaTag) == null) { }; private static String defaultCodePage = null; - @SuppressWarnings("removal") static String getCodePage() { if (defaultCodePage != null) { @@ -672,8 +655,7 @@ static String getCodePage() { } if (FontUtilities.isWindows) { - defaultCodePage = - AccessController.doPrivileged(new GetPropertyAction("file.encoding")); + defaultCodePage = System.getProperty("file.encoding"); } else { if (languages.length != codePages.length) { throw new InternalError("wrong code pages array length"); diff --git a/src/java.desktop/share/classes/sun/font/Type1Font.java b/src/java.desktop/share/classes/sun/font/Type1Font.java index cc36c193de0..67f83cce643 100644 --- a/src/java.desktop/share/classes/sun/font/Type1Font.java +++ b/src/java.desktop/share/classes/sun/font/Type1Font.java @@ -83,18 +83,10 @@ private static class T1DisposerRecord implements DisposerRecord { fileName = name; } - @SuppressWarnings("removal") public synchronized void dispose() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - - if (fileName != null) { - (new java.io.File(fileName)).delete(); - } - return null; - } - }); + if (fileName != null) { + (new java.io.File(fileName)).delete(); + } } } @@ -191,18 +183,11 @@ private synchronized ByteBuffer getBuffer() throws FontFormatException { FontUtilities.logInfo("open Type 1 font: " + platName); } try { - @SuppressWarnings("removal") - RandomAccessFile raf = (RandomAccessFile) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - try { - return new RandomAccessFile(platName, "r"); - } catch (FileNotFoundException ffne) { - } - return null; - } - }); + RandomAccessFile raf = null; + try { + raf = new RandomAccessFile(platName, "r"); + } catch (FileNotFoundException ffne) { + } FileChannel fc = raf.getChannel(); fileSize = (int)fc.size(); bbuf = ByteBuffer.allocate(fileSize); @@ -227,7 +212,6 @@ protected void close() { } /* called from native code to read file into a direct byte buffer */ - @SuppressWarnings("removal") void readFile(ByteBuffer buffer) { RandomAccessFile raf = null; FileChannel fc; @@ -235,17 +219,10 @@ void readFile(ByteBuffer buffer) { FontUtilities.logInfo("open Type 1 font: " + platName); } try { - raf = (RandomAccessFile) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - try { - return new RandomAccessFile(platName, "r"); - } catch (FileNotFoundException fnfe) { - } - return null; - } - }); + try { + raf = new RandomAccessFile(platName, "r"); + } catch (FileNotFoundException fnfe) { + } fc = raf.getChannel(); while (buffer.remaining() > 0 && fc.read(buffer) != -1) {} } catch (ClosedChannelException e) { diff --git a/src/java.desktop/share/classes/sun/java2d/Disposer.java b/src/java.desktop/share/classes/sun/java2d/Disposer.java index 5a80a616045..9929238c099 100644 --- a/src/java.desktop/share/classes/sun/java2d/Disposer.java +++ b/src/java.desktop/share/classes/sun/java2d/Disposer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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,8 +31,6 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.PhantomReference; import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Hashtable; import java.util.concurrent.ConcurrentLinkedDeque; @@ -50,7 +48,7 @@ * * @see DisposerRecord */ -@SuppressWarnings({"removal", "restricted"}) +@SuppressWarnings("restricted") public class Disposer implements Runnable { private static final ReferenceQueue queue = new ReferenceQueue<>(); private static final Hashtable, DisposerRecord> records = @@ -62,16 +60,9 @@ public class Disposer implements Runnable { public static int refType = PHANTOM; static { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); initIDs(); - String type = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.java2d.reftype")); + String type = System.getProperty("sun.java2d.reftype"); if (type != null) { if (type.equals("weak")) { refType = WEAK; @@ -82,16 +73,13 @@ public Void run() { } } disposerInstance = new Disposer(); - AccessController.doPrivileged((PrivilegedAction) () -> { - String name = "Java2D Disposer"; - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - Thread t = new Thread(rootTG, disposerInstance, name, 0, false); - t.setContextClassLoader(null); - t.setDaemon(true); - t.setPriority(Thread.MAX_PRIORITY); - t.start(); - return null; - }); + String name = "Java2D Disposer"; + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + Thread t = new Thread(rootTG, disposerInstance, name, 0, false); + t.setContextClassLoader(null); + t.setDaemon(true); + t.setPriority(Thread.MAX_PRIORITY); + t.start(); } /** @@ -241,7 +229,6 @@ public static void pollRemove() { * so will clutter the records hashmap and no one will be cleaning up * the reference queue. */ - @SuppressWarnings("unchecked") public static void addReference(Reference ref, DisposerRecord rec) { records.put(ref, rec); } diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java b/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java index 4335b1c9fbf..5cd8f11ecdb 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java @@ -40,7 +40,6 @@ import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.peer.ComponentPeer; -import java.security.AccessController; import java.util.Locale; import java.util.TreeMap; @@ -50,7 +49,6 @@ import sun.font.FontManagerFactory; import sun.font.FontManagerForSGE; import sun.java2d.pipe.Region; -import sun.security.action.GetPropertyAction; /** * This is an implementation of a GraphicsEnvironment object for the @@ -65,10 +63,8 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment /** Establish the default font to be used by SG2D. */ private final Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); - @SuppressWarnings("removal") private static final boolean uiScaleEnabled - = "true".equals(AccessController.doPrivileged( - new GetPropertyAction("sun.java2d.uiScale.enabled", "true"))); + = "true".equals(System.getProperty("sun.java2d.uiScale.enabled", "true")); private static final double debugScale = uiScaleEnabled ? getScaleFactor("sun.java2d.uiScale") : -1; @@ -293,9 +289,7 @@ public static double getDebugScale() { public static double getScaleFactor(String propertyName) { - @SuppressWarnings("removal") - String scaleFactor = AccessController.doPrivileged( - new GetPropertyAction(propertyName, "-1")); + String scaleFactor = System.getProperty(propertyName, "-1"); if (scaleFactor == null || scaleFactor.equals("-1")) { return -1; diff --git a/src/java.desktop/share/classes/sun/java2d/SurfaceDataProxy.java b/src/java.desktop/share/classes/sun/java2d/SurfaceDataProxy.java index 4c1e8256552..ba4d6caf44c 100644 --- a/src/java.desktop/share/classes/sun/java2d/SurfaceDataProxy.java +++ b/src/java.desktop/share/classes/sun/java2d/SurfaceDataProxy.java @@ -38,9 +38,6 @@ import sun.java2d.loops.BlitBg; import sun.awt.image.SurfaceManager; -import java.security.AccessController; -import sun.security.action.GetPropertyAction; - /** * The proxy class encapsulates the logic for managing alternate * SurfaceData representations of a primary SurfaceData. @@ -70,18 +67,14 @@ public abstract class SurfaceDataProxy static { cachingAllowed = true; - @SuppressWarnings("removal") - String manimg = AccessController.doPrivileged( - new GetPropertyAction("sun.java2d.managedimages")); + String manimg = System.getProperty("sun.java2d.managedimages"); if ("false".equals(manimg)) { cachingAllowed = false; System.out.println("Disabling managed images"); } defaultThreshold = 1; - @SuppressWarnings("removal") - String num = AccessController.doPrivileged( - new GetPropertyAction("sun.java2d.accthreshold")); + String num = System.getProperty("sun.java2d.accthreshold"); if (num != null) { try { int parsed = Integer.parseInt(num); diff --git a/src/java.desktop/share/classes/sun/java2d/cmm/CMSManager.java b/src/java.desktop/share/classes/sun/java2d/cmm/CMSManager.java index 99e167ba672..8aba1056616 100644 --- a/src/java.desktop/share/classes/sun/java2d/cmm/CMSManager.java +++ b/src/java.desktop/share/classes/sun/java2d/cmm/CMSManager.java @@ -27,9 +27,6 @@ import java.awt.color.CMMException; import java.awt.color.ICC_Profile; -import java.security.AccessController; - -import sun.security.action.GetPropertyAction; public final class CMSManager { @@ -45,9 +42,7 @@ private static synchronized PCMM createModule() { return cmmImpl; } - GetPropertyAction gpa = new GetPropertyAction("sun.java2d.cmm"); - @SuppressWarnings("removal") - String cmmProviderClass = AccessController.doPrivileged(gpa); + String cmmProviderClass = System.getProperty("sun.java2d.cmm"); CMMServiceProvider provider = null; if (cmmProviderClass != null) { try { @@ -67,9 +62,7 @@ private static synchronized PCMM createModule() { "No CM module found"); } - gpa = new GetPropertyAction("sun.java2d.cmm.trace"); - @SuppressWarnings("removal") - String cmmTrace = AccessController.doPrivileged(gpa); + String cmmTrace = System.getProperty("sun.java2d.cmm.trace"); if (cmmTrace != null) { cmmImpl = new CMMTracer(cmmImpl); } diff --git a/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMS.java b/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMS.java index 2fe86b3500c..3a7db37329e 100644 --- a/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMS.java +++ b/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMS.java @@ -143,23 +143,17 @@ private LCMS() {} private static LCMS theLcms = null; - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") static synchronized PCMM getModule() { if (theLcms != null) { return theLcms; } - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - /* We need to load awt here because of usage trace and - * disposer frameworks - */ - System.loadLibrary("awt"); - System.loadLibrary("lcms"); - return null; - } - }); + /* We need to load awt here because of usage trace and + * disposer frameworks + */ + System.loadLibrary("awt"); + System.loadLibrary("lcms"); theLcms = new LCMS(); diff --git a/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java b/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java index ade97ee007f..8fd97626f04 100644 --- a/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java +++ b/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java @@ -36,8 +36,6 @@ import java.io.FileOutputStream; import java.io.PrintStream; import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; @@ -46,7 +44,6 @@ import sun.awt.util.ThreadGroupUtils; import sun.java2d.SurfaceData; import sun.java2d.pipe.Region; -import sun.security.action.GetPropertyAction; /** * defines interface for primitives which can be placed into @@ -336,9 +333,7 @@ protected GraphicsPrimitive makePrimitive(SurfaceType srctype, public static final int TRACECOUNTS = 4; static { - GetPropertyAction gpa = new GetPropertyAction("sun.java2d.trace"); - @SuppressWarnings("removal") - String trace = AccessController.doPrivileged(gpa); + String trace = System.getProperty("sun.java2d.trace"); if (trace != null) { boolean verbose = false; int traceflags = 0; @@ -401,17 +396,12 @@ public static boolean tracingEnabled() { private static PrintStream getTraceOutputFile() { if (traceout == null) { if (tracefile != null) { - @SuppressWarnings("removal") - FileOutputStream o = AccessController.doPrivileged( - new PrivilegedAction() { - public FileOutputStream run() { - try { - return new FileOutputStream(tracefile); - } catch (FileNotFoundException e) { - return null; - } - } - }); + FileOutputStream o; + try { + o = new FileOutputStream(tracefile); + } catch (FileNotFoundException e) { + o = null; + } if (o != null) { traceout = new PrintStream(o); } else { @@ -425,17 +415,13 @@ public FileOutputStream run() { } public static class TraceReporter implements Runnable { - @SuppressWarnings("removal") public static void setShutdownHook() { - AccessController.doPrivileged((PrivilegedAction) () -> { - TraceReporter t = new TraceReporter(); - Thread thread = new Thread( - ThreadGroupUtils.getRootThreadGroup(), t, - "TraceReporter", 0, false); - thread.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(thread); - return null; - }); + TraceReporter t = new TraceReporter(); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), t, + "TraceReporter", 0, false); + thread.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(thread); } public void run() { diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java index a42e474e764..66eb9334e86 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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,7 +30,6 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Path2D; import java.awt.geom.PathIterator; -import java.security.AccessController; import java.util.Arrays; import sun.awt.geom.PathConsumer2D; import static sun.java2d.marlin.MarlinUtils.logInfo; @@ -40,7 +39,6 @@ import sun.java2d.pipe.AATileGenerator; import sun.java2d.pipe.Region; import sun.java2d.pipe.RenderingEngine; -import sun.security.action.GetPropertyAction; /** * Marlin RendererEngine implementation (derived from Pisces) @@ -1119,10 +1117,8 @@ public float getMinimumAAPenSize() { USE_THREAD_LOCAL = MarlinProperties.isUseThreadLocal(); // Soft reference by default: - @SuppressWarnings("removal") - final String refType = AccessController.doPrivileged( - new GetPropertyAction("sun.java2d.renderer.useRef", - "soft")); + final String refType = System.getProperty("sun.java2d.renderer.useRef", + "soft"); switch (refType) { default: case "soft": @@ -1300,7 +1296,6 @@ private static void logSettings(final String reClass) { * Get the RendererContext instance dedicated to the current thread * @return RendererContext instance */ - @SuppressWarnings({"unchecked"}) static RendererContext getRendererContext() { final RendererContext rdrCtx = RDR_CTX_PROVIDER.acquire(); if (DO_MONITORS) { diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinProperties.java b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinProperties.java index ef919eba400..65122cae2a3 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinProperties.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinProperties.java @@ -25,9 +25,7 @@ package sun.java2d.marlin; -import java.security.AccessController; import static sun.java2d.marlin.MarlinUtils.logInfo; -import sun.security.action.GetPropertyAction; public final class MarlinProperties { @@ -288,24 +286,18 @@ public static float getQuadDecD2() { } // system property utilities - @SuppressWarnings("removal") static String getString(final String key, final String def) { - return AccessController.doPrivileged( - new GetPropertyAction(key, def)); + return System.getProperty(key, def); } - @SuppressWarnings("removal") static boolean getBoolean(final String key, final String def) { - return Boolean.parseBoolean(AccessController.doPrivileged( - new GetPropertyAction(key, def))); + return Boolean.parseBoolean(System.getProperty(key, def)); } static int getInteger(final String key, final int def, final int min, final int max) { - @SuppressWarnings("removal") - final String property = AccessController.doPrivileged( - new GetPropertyAction(key)); + final String property = System.getProperty(key); int value = def; if (property != null) { @@ -334,9 +326,7 @@ public static double getDouble(final String key, final double def, final double min, final double max) { double value = def; - @SuppressWarnings("removal") - final String property = AccessController.doPrivileged( - new GetPropertyAction(key)); + final String property = System.getProperty(key); if (property != null) { try { diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/RendererStats.java b/src/java.desktop/share/classes/sun/java2d/marlin/RendererStats.java index 5517ce93f99..131f63afa65 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/RendererStats.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/RendererStats.java @@ -25,8 +25,6 @@ package sun.java2d.marlin; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentLinkedQueue; @@ -357,11 +355,8 @@ static void dumpStats() { private final ConcurrentLinkedQueue allStats = new ConcurrentLinkedQueue<>(); - @SuppressWarnings("removal") private RendererStatsHolder() { - AccessController.doPrivileged( - (PrivilegedAction) () -> { - final Thread hook = new Thread( + final Thread hook = new Thread( MarlinUtils.getRootThreadGroup(), new Runnable() { @Override @@ -371,21 +366,18 @@ public void run() { }, "MarlinStatsHook" ); - hook.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(hook); + hook.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(hook); - if (USE_DUMP_THREAD) { - final Timer statTimer = new Timer("RendererStats"); - statTimer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - dump(); - } - }, DUMP_INTERVAL, DUMP_INTERVAL); + if (USE_DUMP_THREAD) { + final Timer statTimer = new Timer("RendererStats"); + statTimer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + dump(); } - return null; - } - ); + }, DUMP_INTERVAL, DUMP_INTERVAL); + } } void add(final Object parent, final RendererStats stats) { diff --git a/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java b/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java index 4b89aca5c85..8427bcd1a4f 100644 --- a/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java +++ b/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java @@ -30,8 +30,6 @@ import sun.java2d.pipe.RenderQueue; import static sun.java2d.pipe.BufferedOpCodes.*; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * OGL-specific implementation of RenderQueue. This class provides a @@ -44,13 +42,12 @@ public class OGLRenderQueue extends RenderQueue { private static OGLRenderQueue theInstance; private final QueueFlusher flusher; - @SuppressWarnings("removal") private OGLRenderQueue() { /* * The thread must be a member of a thread group * which will not get GCed before VM exit. */ - flusher = AccessController.doPrivileged((PrivilegedAction) QueueFlusher::new); + flusher = new QueueFlusher(); } /** diff --git a/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceData.java b/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceData.java index 2f27515c204..501399c35a9 100644 --- a/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceData.java +++ b/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceData.java @@ -178,31 +178,19 @@ protected native boolean initFBObject(long pData, static { if (!GraphicsEnvironment.isHeadless()) { // fbobject currently enabled by default; use "false" to disable - @SuppressWarnings("removal") - String fbo = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "sun.java2d.opengl.fbobject")); + String fbo = System.getProperty("sun.java2d.opengl.fbobject"); isFBObjectEnabled = !"false".equals(fbo); // lcdshader currently enabled by default; use "false" to disable - @SuppressWarnings("removal") - String lcd = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "sun.java2d.opengl.lcdshader")); + String lcd = System.getProperty("sun.java2d.opengl.lcdshader"); isLCDShaderEnabled = !"false".equals(lcd); // biopshader currently enabled by default; use "false" to disable - @SuppressWarnings("removal") - String biop = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "sun.java2d.opengl.biopshader")); + String biop = System.getProperty("sun.java2d.opengl.biopshader"); isBIOpShaderEnabled = !"false".equals(biop); // gradshader currently enabled by default; use "false" to disable - @SuppressWarnings("removal") - String grad = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "sun.java2d.opengl.gradshader")); + String grad = System.getProperty("sun.java2d.opengl.gradshader"); isGradShaderEnabled = !"false".equals(grad); OGLRenderQueue rq = OGLRenderQueue.getInstance(); diff --git a/src/java.desktop/share/classes/sun/java2d/pipe/RenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/pipe/RenderingEngine.java index e33eabd06b3..e6a5be7ca3b 100644 --- a/src/java.desktop/share/classes/sun/java2d/pipe/RenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/pipe/RenderingEngine.java @@ -30,9 +30,6 @@ import java.awt.geom.PathIterator; import java.awt.geom.AffineTransform; -import java.security.AccessController; -import sun.security.action.GetPropertyAction; - import sun.awt.geom.PathConsumer2D; /** @@ -120,10 +117,7 @@ public static synchronized RenderingEngine getInstance() { /* Look first for an app-override renderer, * if not specified or present, then look for marlin. */ - GetPropertyAction gpa = - new GetPropertyAction("sun.java2d.renderer"); - @SuppressWarnings("removal") - String reClass = AccessController.doPrivileged(gpa); + String reClass = System.getProperty("sun.java2d.renderer"); if (reClass != null) { try { Class cls = Class.forName(reClass); @@ -144,16 +138,12 @@ public static synchronized RenderingEngine getInstance() { throw new InternalError("No RenderingEngine module found"); } - gpa = new GetPropertyAction("sun.java2d.renderer.verbose"); - @SuppressWarnings("removal") - String verbose = AccessController.doPrivileged(gpa); + String verbose = System.getProperty("sun.java2d.renderer.verbose"); if (verbose != null && verbose.startsWith("t")) { System.out.println("RenderingEngine = "+reImpl); } - gpa = new GetPropertyAction("sun.java2d.renderer.trace"); - @SuppressWarnings("removal") - String reTrace = AccessController.doPrivileged(gpa); + String reTrace = System.getProperty("sun.java2d.renderer.trace"); if (reTrace != null) { reImpl = new Tracer(reImpl); } diff --git a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java index e64fb2cb0d5..a0f68a713aa 100644 --- a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java @@ -338,18 +338,9 @@ public class PSPrinterJob extends RasterPrinterJob { initStatic(); } - @SuppressWarnings("removal") private static void initStatic() { - //enable privileges so initProps can access system properties, - // open the property file, etc. - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - mFontProps = initProps(); - isMac = OSInfo.getOSType() == OSInfo.OSType.MACOSX; - return null; - } - }); + mFontProps = initProps(); + isMac = OSInfo.getOSType() == OSInfo.OSType.MACOSX; } /* @@ -512,7 +503,6 @@ protected void setAttributes(PrintRequestAttributeSet attributes) * this method is called to mark the start of a * document. */ - @SuppressWarnings("removal") protected void startDoc() throws PrinterException { // A security check has been performed in the @@ -551,7 +541,7 @@ protected void startDoc() throws PrinterException { } } else { PrinterOpener po = new PrinterOpener(); - java.security.AccessController.doPrivileged(po); + po.run(); if (po.pex != null) { throw po.pex; } @@ -641,22 +631,16 @@ protected void startDoc() throws PrinterException { paperWidth + " "+ paperHeight+"]"); final PrintService pservice = getPrintService(); - Boolean isPS = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Boolean run() { - try { - Class psClass = Class.forName("sun.print.IPPPrintService"); - if (psClass.isInstance(pservice)) { - Method isPSMethod = psClass.getMethod("isPostscript", - (Class[])null); - return (Boolean)isPSMethod.invoke(pservice, (Object[])null); - } - } catch (Throwable t) { - } - return Boolean.TRUE; - } + Boolean isPS = Boolean.TRUE; + try { + Class psClass = Class.forName("sun.print.IPPPrintService"); + if (psClass.isInstance(pservice)) { + Method isPSMethod = psClass.getMethod("isPostscript", + (Class[])null); + isPS = (Boolean)isPSMethod.invoke(pservice, (Object[])null); } - ); + } catch (Throwable t) { + } if (isPS) { mPSStream.print(" /DeferredMediaSelection true"); } @@ -677,9 +661,9 @@ public Boolean run() { mPSStream.println("%%EndSetup"); } - // Inner class to run "privileged" to open the printer output stream. + // Inner class to open the printer output stream. - private class PrinterOpener implements java.security.PrivilegedAction { + private class PrinterOpener { PrinterException pex; OutputStream result; @@ -704,9 +688,9 @@ public OutputStream run() { } } - // Inner class to run "privileged" to invoke the system print command + // Inner class to invoke the system print command - private class PrinterSpooler implements java.security.PrivilegedAction { + private class PrinterSpooler { PrinterException pex; private void handleProcessFailure(final Process failedProcess, @@ -767,21 +751,13 @@ mNoJobSheet, getJobNameInt(), /** * Invoked if the application cancelled the printjob. */ - @SuppressWarnings("removal") protected void abortDoc() { if (mPSStream != null && mDestType != RasterPrinterJob.STREAM) { mPSStream.close(); } - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - - public Object run() { - if (spoolFile != null && spoolFile.exists()) { - spoolFile.delete(); - } - return null; - } - }); + if (spoolFile != null && spoolFile.exists()) { + spoolFile.delete(); + } } /** @@ -789,7 +765,6 @@ public Object run() { * this method is called after that last page * has been imaged. */ - @SuppressWarnings("removal") protected void endDoc() throws PrinterException { if (mPSStream != null) { mPSStream.println(EOF_COMMENT); @@ -814,7 +789,7 @@ protected void endDoc() throws PrinterException { } } PrinterSpooler spooler = new PrinterSpooler(); - java.security.AccessController.doPrivileged(spooler); + spooler.run(); if (spooler.pex != null) { throw spooler.pex; } @@ -859,28 +834,18 @@ protected void startPage(PageFormat pageFormat, Printable painter, paperWidth + " " + paperHeight + "]"); final PrintService pservice = getPrintService(); - @SuppressWarnings("removal") - Boolean isPS = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Boolean run() { - try { - Class psClass = - Class.forName("sun.print.IPPPrintService"); - if (psClass.isInstance(pservice)) { - Method isPSMethod = - psClass.getMethod("isPostscript", - (Class[])null); - return (Boolean) - isPSMethod.invoke(pservice, + Boolean isPS = Boolean.TRUE; + try { + Class psClass = Class.forName("sun.print.IPPPrintService"); + if (psClass.isInstance(pservice)) { + Method isPSMethod = + psClass.getMethod("isPostscript", + (Class[])null); + isPS = (Boolean) isPSMethod.invoke(pservice, (Object[])null); - } - } catch (Throwable t) { - } - return Boolean.TRUE; - } - } - ); - + } + } catch (Throwable t) { + } if (isPS) { mPSStream.print(" /DeferredMediaSelection true"); } diff --git a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 82f47824bfa..bf380873d2b 100644 --- a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -174,9 +174,7 @@ public abstract class RasterPrinterJob extends PrinterJob { * use a particular pipeline. Either the raster * pipeline or the pdl pipeline can be forced. */ - @SuppressWarnings("removal") - String forceStr = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction(FORCE_PIPE_PROP)); + String forceStr = System.getProperty(FORCE_PIPE_PROP); if (forceStr != null) { if (forceStr.equalsIgnoreCase(FORCE_PDL)) { @@ -186,9 +184,7 @@ public abstract class RasterPrinterJob extends PrinterJob { } } - @SuppressWarnings("removal") - String shapeTextStr =java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction(SHAPE_TEXT_PROP)); + String shapeTextStr = System.getProperty(SHAPE_TEXT_PROP); if (shapeTextStr != null) { shapeTextProp = true; @@ -731,20 +727,9 @@ public PageFormat pageDialog(PageFormat page) GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().getDefaultConfiguration(); - @SuppressWarnings("removal") - PrintService service = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public PrintService run() { - PrintService service = getPrintService(); - if (service == null) { - ServiceDialog.showNoPrintService(gc); - return null; - } - return service; - } - }); - + PrintService service = getPrintService(); if (service == null) { + ServiceDialog.showNoPrintService(gc); return page; } updatePageAttributes(service, page); @@ -812,20 +797,9 @@ public PageFormat pageDialog(final PrintRequestAttributeSet attributes) } final GraphicsConfiguration gc = grCfg; - @SuppressWarnings("removal") - PrintService service = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public PrintService run() { - PrintService service = getPrintService(); - if (service == null) { - ServiceDialog.showNoPrintService(gc); - return null; - } - return service; - } - }); - + PrintService service = getPrintService(); if (service == null) { + ServiceDialog.showNoPrintService(gc); return null; } @@ -953,7 +927,6 @@ protected PageFormat getPageFormatFromAttributes() { * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ - @SuppressWarnings("removal") public boolean printDialog(final PrintRequestAttributeSet attributes) throws HeadlessException { if (GraphicsEnvironment.isHeadless()) { @@ -1008,19 +981,9 @@ public boolean printDialog(final PrintRequestAttributeSet attributes) } final GraphicsConfiguration gc = grCfg; - PrintService service = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public PrintService run() { - PrintService service = getPrintService(); - if (service == null) { - ServiceDialog.showNoPrintService(gc); - return null; - } - return service; - } - }); - + PrintService service = getPrintService(); if (service == null) { + ServiceDialog.showNoPrintService(gc); return false; } @@ -1033,13 +996,7 @@ public PrintService run() { services[i] = spsFactories[i].getPrintService(null); } } else { - services = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public PrintService[] run() { - PrintService[] services = PrinterJob.lookupPrintServices(); - return services; - } - }); + services = PrinterJob.lookupPrintServices(); if ((services == null) || (services.length == 0)) { /* diff --git a/src/java.desktop/share/classes/sun/print/ServiceDialog.java b/src/java.desktop/share/classes/sun/print/ServiceDialog.java index 6f2bdecb809..ae2c787ce36 100644 --- a/src/java.desktop/share/classes/sun/print/ServiceDialog.java +++ b/src/java.desktop/share/classes/sun/print/ServiceDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -296,7 +296,6 @@ public void windowClosing(WindowEvent event) { * Performs Cancel when Esc key is pressed. */ private void handleEscKey(JButton btnCancel) { - @SuppressWarnings("serial") // anonymous class Action cancelKeyAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { dispose(CANCEL); @@ -449,21 +448,13 @@ private void updatePanels() { /** * Initialize ResourceBundle */ - @SuppressWarnings("removal") public static void initResource() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - try { - messageRB = ResourceBundle.getBundle(strBundle); - return null; - } catch (java.util.MissingResourceException e) { - throw new Error("Fatal: Resource for ServiceUI " + - "is missing"); - } - } - } - ); + try { + messageRB = ResourceBundle.getBundle(strBundle); + } catch (java.util.MissingResourceException e) { + throw new Error("Fatal: Resource for ServiceUI " + + "is missing"); + } } /** @@ -543,15 +534,7 @@ private static int getVKMnemonic(String key) { * Returns URL for image resource */ private static URL getImageResource(final String key) { - @SuppressWarnings("removal") - URL url = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public URL run() { - URL url = ServiceDialog.class.getResource( - "resources/" + key); - return url; - } - }); + URL url = ServiceDialog.class.getResource("resources/" + key); if (url == null) { throw new Error("Fatal: Resource for ServiceUI is broken; " + @@ -2944,14 +2927,7 @@ public IconRadioButton(String key, String img, boolean selected, { super(new FlowLayout(FlowLayout.LEADING)); final URL imgURL = getImageResource(img); - @SuppressWarnings("removal") - Icon icon = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Icon run() { - Icon icon = new ImageIcon(imgURL); - return icon; - } - }); + Icon icon = new ImageIcon(imgURL); lbl = new JLabel(icon); add(lbl); diff --git a/src/java.desktop/share/classes/sun/swing/FilePane.java b/src/java.desktop/share/classes/sun/swing/FilePane.java index e97dcb3b881..395cf058b7d 100644 --- a/src/java.desktop/share/classes/sun/swing/FilePane.java +++ b/src/java.desktop/share/classes/sun/swing/FilePane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -659,7 +659,6 @@ public JPanel createList() { JPanel p = new JPanel(new BorderLayout()); final JFileChooser fileChooser = getFileChooser(); - @SuppressWarnings("serial") // anonymous class final JList list = new JList() { public int getNextMatch(String prefix, int startIndex, Position.Bias bias) { ListModel model = getModel(); @@ -1262,7 +1261,6 @@ public JPanel createDetailsView() { JPanel p = new JPanel(new BorderLayout()); - @SuppressWarnings("serial") // anonymous class final JTable detailsTable = new JTable(getDetailsTableModel()) { // Handle Escape key events here protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { @@ -1575,7 +1573,6 @@ private void applyEdit() { protected Action newFolderAction; - @SuppressWarnings("serial") // anonymous class inside public Action getNewFolderAction() { if (!readOnly && newFolderAction == null) { newFolderAction = new AbstractAction(newFolderActionLabelText) { diff --git a/src/java.desktop/share/classes/sun/swing/JLightweightFrame.java b/src/java.desktop/share/classes/sun/swing/JLightweightFrame.java index cfc5ceef6c3..8e4b0ff3f7c 100644 --- a/src/java.desktop/share/classes/sun/swing/JLightweightFrame.java +++ b/src/java.desktop/share/classes/sun/swing/JLightweightFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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,7 +40,6 @@ import java.awt.image.DataBufferInt; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.security.AccessController; import javax.swing.JComponent; import javax.swing.JLayeredPane; @@ -55,7 +54,6 @@ import sun.awt.DisplayChangedListener; import sun.awt.LightweightFrame; import sun.awt.OverrideNativeWindowHandle; -import sun.security.action.GetPropertyAction; import sun.swing.SwingUtilities2.RepaintListener; /** @@ -105,24 +103,21 @@ public void updateCursor(JLightweightFrame frame) { * by the lock (managed with the {@link LightweightContent#paintLock()}, * {@link LightweightContent#paintUnlock()} methods). */ - @SuppressWarnings("removal") - private static boolean copyBufferEnabled = "true".equals(AccessController. - doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true"))); + private static boolean copyBufferEnabled = "true".equals( + System.getProperty("swing.jlf.copyBufferEnabled", "true")); private int[] copyBuffer; /** * Constructs a new, initially invisible {@code JLightweightFrame} * instance. */ - @SuppressWarnings("removal") public JLightweightFrame() { super(); AffineTransform defaultTransform = getGraphicsConfiguration().getDefaultTransform(); scaleFactorX = defaultTransform.getScaleX(); scaleFactorY = defaultTransform.getScaleY(); - copyBufferEnabled = "true".equals(AccessController. - doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true"))); + copyBufferEnabled = "true".equals(System.getProperty("swing.jlf.copyBufferEnabled", "true")); add(rootPane, BorderLayout.CENTER); setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); @@ -331,7 +326,6 @@ private void notifyImageUpdated(int x, int y, int width, int height) { content.imageUpdated(x, y, width, height); } - @SuppressWarnings({"removal","serial"}) // anonymous class inside private void initInterior() { contentPane = new JPanel() { @Override @@ -392,8 +386,7 @@ public void componentRemoved(ContainerEvent e) { contentPane.add(component); contentPane.revalidate(); contentPane.repaint(); - if ("true".equals(AccessController. - doPrivileged(new GetPropertyAction("swing.jlf.contentPaneTransparent", "false")))) + if ("true".equals(System.getProperty("swing.jlf.contentPaneTransparent", "false"))) { contentPane.setOpaque(false); } diff --git a/src/java.desktop/share/classes/sun/swing/LightweightContent.java b/src/java.desktop/share/classes/sun/swing/LightweightContent.java index eb283908e81..f67e3ad7fcf 100644 --- a/src/java.desktop/share/classes/sun/swing/LightweightContent.java +++ b/src/java.desktop/share/classes/sun/swing/LightweightContent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -161,7 +161,6 @@ default public void imageBufferReset(int[] data, * @param scaleY the y coordinate scale factor of the pixel buffer * @since 9 */ - @SuppressWarnings("deprecation") default public void imageBufferReset(int[] data, int x, int y, int width, int height, @@ -178,7 +177,6 @@ default public void imageBufferReset(int[] data, * default implementations in order to allow a client application to run * with any JDK version without breaking backward compatibility. */ - @SuppressWarnings("deprecation") default public void imageBufferReset(int[] data, int x, int y, int width, int height, diff --git a/src/java.desktop/share/classes/sun/swing/PrintingStatus.java b/src/java.desktop/share/classes/sun/swing/PrintingStatus.java index 1f7358a2881..b2fbed5222e 100644 --- a/src/java.desktop/share/classes/sun/swing/PrintingStatus.java +++ b/src/java.desktop/share/classes/sun/swing/PrintingStatus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -62,7 +62,6 @@ public class PrintingStatus { private final AtomicBoolean isAborted = new AtomicBoolean(false); // the action that will abort printing - @SuppressWarnings("serial") // anonymous class private final Action abortAction = new AbstractAction() { public void actionPerformed(ActionEvent ae) { if (!isAborted.get()) { diff --git a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java index d763a72d528..2613ca326ea 100644 --- a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java +++ b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java @@ -61,8 +61,6 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.text.BreakIterator; @@ -1706,10 +1704,8 @@ private static Object makeIcon(final Class baseClass, final String imageFile, final boolean enablePrivileges) { return (UIDefaults.LazyValue) (table) -> { - @SuppressWarnings("removal") - byte[] buffer = enablePrivileges ? AccessController.doPrivileged( - (PrivilegedAction) () - -> getIconBytes(baseClass, rootClass, imageFile)) + byte[] buffer = enablePrivileges ? + getIconBytes(baseClass, rootClass, imageFile) : getIconBytes(baseClass, rootClass, imageFile); if (buffer == null) { diff --git a/src/java.desktop/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java b/src/java.desktop/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java index 81789bcfdcf..c225ddc9ff6 100644 --- a/src/java.desktop/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java +++ b/src/java.desktop/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -188,7 +188,6 @@ protected void installDefaults(JFileChooser fc) { readOnly = UIManager.getBoolean("FileChooser.readOnly"); } - @SuppressWarnings("serial") // anonymous classes inside public void installComponents(JFileChooser fc) { super.installComponents(fc); diff --git a/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java b/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java index 28d57b02b63..f93c1673aca 100644 --- a/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java +++ b/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java @@ -332,7 +332,6 @@ public JTextComponent call() throws Exception { } } - @SuppressWarnings("serial") // anonymous class inside private JTextComponent createPrintShellOnEDT(final JTextComponent textComponent) { assert SwingUtilities.isEventDispatchThread(); diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c b/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c index 59773ec666d..36163e885ed 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c @@ -542,7 +542,7 @@ OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, } JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); - if (!((*env)->ExceptionOccurred(env))) { + if (!((*env)->ExceptionCheck(env))) { JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); } diff --git a/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c b/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c index c8d1464f8aa..29690b9c9a7 100644 --- a/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c +++ b/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c @@ -984,7 +984,7 @@ int awt_getPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP) { 0, y, w, maxLines, jdata, jdatabuffer); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->DeleteLocalRef(env, jdata); return -1; } @@ -1104,7 +1104,7 @@ int awt_setPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP) { 0, y, w, maxLines, jdata, jdatabuffer); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->DeleteLocalRef(env, jdata); return -1; } diff --git a/src/java.desktop/share/native/libawt/awt/image/gif/gifdecoder.c b/src/java.desktop/share/native/libawt/awt/image/gif/gifdecoder.c index 02b10bef76f..964c2f4a4c1 100644 --- a/src/java.desktop/share/native/libawt/awt/image/gif/gifdecoder.c +++ b/src/java.desktop/share/native/libawt/awt/image/gif/gifdecoder.c @@ -237,7 +237,7 @@ Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env, len = (*env)->CallIntMethod(env, this, readID, blockh, remain, blockLength + 1); if (len > blockLength + 1) len = blockLength + 1; - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { return 0; } GET_ARRAYS(); @@ -314,10 +314,10 @@ Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env, } if ((*env)->CallIntMethod(env, this, readID, blockh, 0, blockLength + 1) != 0 - || (*env)->ExceptionOccurred(env)) + || (*env)->ExceptionCheck(env)) { /* quietly accept truncated GIF images */ - return (!(*env)->ExceptionOccurred(env)); + return (!(*env)->ExceptionCheck(env)); } GET_ARRAYS(); blockLength = block[blockLength]; @@ -412,7 +412,7 @@ Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env, relx, rely + y, width, passht, raslineh, cmh); - if (count <= 0 || (*env)->ExceptionOccurred(env)) { + if (count <= 0 || (*env)->ExceptionCheck(env)) { /* Nobody is listening any more. */ if (verbose) { fprintf(stdout, "Orphan gif decoder quitting\n"); diff --git a/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c b/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c index 7e382eec175..b6170814223 100644 --- a/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c +++ b/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c @@ -2017,7 +2017,7 @@ cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component, g_BImgGetRGBMID, 0, y, w, numLines, jpixels, 0, w); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->DeleteLocalRef(env, jpixels); return -1; } @@ -2093,7 +2093,7 @@ cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component, (*env)->CallVoidMethod(env, imageP->jimage, g_BImgSetRGBMID, 0, y, w, numLines, jpixels, 0, w); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->DeleteLocalRef(env, jpixels); return -1; } diff --git a/src/java.desktop/share/native/libawt/java2d/SurfaceData.c b/src/java.desktop/share/native/libawt/java2d/SurfaceData.c index 4d96a2d3ff4..fbed597096b 100644 --- a/src/java.desktop/share/native/libawt/java2d/SurfaceData.c +++ b/src/java.desktop/share/native/libawt/java2d/SurfaceData.c @@ -118,7 +118,7 @@ GetSDOps(JNIEnv *env, jobject sData, jboolean callSetup) } ops = (SurfaceDataOps *)JNU_GetLongFieldAsPtr(env, sData, pDataID); if (ops == NULL) { - if (!(*env)->ExceptionOccurred(env) && + if (!(*env)->ExceptionCheck(env) && !(*env)->IsInstanceOf(env, sData, pNullSurfaceDataClass)) { if (!(*env)->GetBooleanField(env, sData, validID)) { diff --git a/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc b/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc index f2c08541d7c..caeca3e6346 100644 --- a/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc +++ b/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc @@ -50,7 +50,7 @@ hb_jdk_get_nominal_glyph (hb_font_t *font HB_UNUSED, jobject font2D = jdkFontInfo->font2D; *glyph = (hb_codepoint_t)env->CallIntMethod( font2D, sunFontIDs.f2dCharToGlyphMID, unicode); - if (env->ExceptionOccurred()) + if (env->ExceptionCheck()) { env->ExceptionClear(); } @@ -75,7 +75,7 @@ hb_jdk_get_variation_glyph (hb_font_t *font HB_UNUSED, *glyph = (hb_codepoint_t)env->CallIntMethod( font2D, sunFontIDs.f2dCharToVariationGlyphMID, unicode, variation_selector); - if (env->ExceptionOccurred()) + if (env->ExceptionCheck()) { env->ExceptionClear(); } diff --git a/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c b/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c index 4e2ba2a35c5..a764eb1ae3b 100644 --- a/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c +++ b/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c @@ -575,7 +575,7 @@ sun_jpeg_output_message (j_common_ptr cinfo) (*env)->CallVoidMethod(env, theObject, JPEGImageReader_warningWithMessageID, string); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit(cinfo); } @@ -585,7 +585,7 @@ sun_jpeg_output_message (j_common_ptr cinfo) (*env)->CallVoidMethod(env, theObject, JPEGImageWriter_warningWithMessageID, string); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, (const JOCTET **)(&dest->next_output_byte))) { cinfo->err->error_exit(cinfo); @@ -625,7 +625,7 @@ static void imageio_set_stream(JNIEnv *env, if (setjmp(jerr->setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error while aborting. */ - if (!(*env)->ExceptionOccurred(env)) { + if (!(*env)->ExceptionCheck(env)) { char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message) (cinfo, buffer); @@ -651,7 +651,7 @@ static void imageio_reset(JNIEnv *env, if (setjmp(jerr->setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error while aborting. */ - if (!(*env)->ExceptionOccurred(env)) { + if (!(*env)->ExceptionCheck(env)) { char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message) (cinfo, buffer); JNU_ThrowByName(env, "javax/imageio/IIOException", buffer); @@ -969,7 +969,7 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo) if ((ret > 0) && ((unsigned int)ret > sb->bufferLength)) { ret = (int)sb->bufferLength; } - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -992,7 +992,7 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo) (*env)->CallVoidMethod(env, reader, JPEGImageReader_warningOccurredID, READ_NO_EOI); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -1067,7 +1067,7 @@ imageio_fill_suspended_buffer(j_decompress_ptr cinfo) sb->hstreamBuffer, offset, buflen); if ((ret > 0) && ((unsigned int)ret > buflen)) ret = (int)buflen; - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -1083,7 +1083,7 @@ imageio_fill_suspended_buffer(j_decompress_ptr cinfo) (*env)->CallVoidMethod(env, reader, JPEGImageReader_warningOccurredID, READ_NO_EOI); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -1168,7 +1168,7 @@ imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes) input, JPEGImageReader_skipInputBytesID, (jlong) num_bytes); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -1187,7 +1187,7 @@ imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes) JPEGImageReader_warningOccurredID, READ_NO_EOI); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -1221,7 +1221,7 @@ imageio_term_source(j_decompress_ptr cinfo) JPEGImageReader_pushBackID, src->bytes_in_buffer); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -1660,7 +1660,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader /* If we get here, the JPEG code has signaled an error while reading the header. */ RELEASE_ARRAYS(env, data, src->next_input_byte); - if (!(*env)->ExceptionOccurred(env)) { + if (!(*env)->ExceptionCheck(env)) { char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo, buffer); @@ -1819,7 +1819,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader cinfo->out_color_space, cinfo->num_components, profileData); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -1988,7 +1988,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage /* If we get here, the JPEG code has signaled an error while reading. */ RELEASE_ARRAYS(env, data, src->next_input_byte); - if (!(*env)->ExceptionOccurred(env)) { + if (!(*env)->ExceptionCheck(env)) { char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo, buffer); @@ -2074,7 +2074,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage (*env)->CallVoidMethod(env, this, JPEGImageReader_passStartedID, cinfo->input_scan_number-1); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -2084,7 +2084,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage (*env)->CallVoidMethod(env, this, JPEGImageReader_passStartedID, 0); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -2144,7 +2144,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage targetLine++, progressive); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -2178,7 +2178,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage RELEASE_ARRAYS(env, data, src->next_input_byte); (*env)->CallVoidMethod(env, this, JPEGImageReader_passCompleteID); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, &(src->next_input_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); } @@ -2336,7 +2336,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_resetReader become more flexible. */ - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionClear(env); } } else { @@ -2415,7 +2415,7 @@ imageio_empty_output_buffer (j_compress_ptr cinfo) sb->hstreamBuffer, 0, sb->bufferLength); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, (const JOCTET **)(&dest->next_output_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); @@ -2458,7 +2458,7 @@ imageio_term_destination (j_compress_ptr cinfo) 0, datacount); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, (const JOCTET **)(&dest->next_output_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); @@ -2669,7 +2669,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeTables /* If we get here, the JPEG code has signaled an error while writing. */ RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte)); - if (!(*env)->ExceptionOccurred(env)) { + if (!(*env)->ExceptionCheck(env)) { char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message) ((j_common_ptr) cinfo, buffer); @@ -2892,7 +2892,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage /* If we get here, the JPEG code has signaled an error while writing. */ RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte)); - if (!(*env)->ExceptionOccurred(env)) { + if (!(*env)->ExceptionCheck(env)) { char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message) ((j_common_ptr) cinfo, buffer); @@ -3039,7 +3039,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage (*env)->CallVoidMethod(env, this, JPEGImageWriter_writeMetadataID); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, (const JOCTET **)(&dest->next_output_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); @@ -3059,7 +3059,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage this, JPEGImageWriter_grabPixelsID, targetLine); - if ((*env)->ExceptionOccurred(env) + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, data, (const JOCTET **)(&dest->next_output_byte))) { cinfo->err->error_exit((j_common_ptr) cinfo); diff --git a/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c b/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c index a01a6bbd58e..889c7a9c0f6 100644 --- a/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c +++ b/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c @@ -298,7 +298,7 @@ sun_jpeg_fill_input_buffer(j_decompress_ptr cinfo) ret = (*env)->CallIntMethod(env, src->hInputStream, InputStream_readID, src->hInputBuffer, 0, buflen); if (ret > buflen) ret = buflen; - if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) { + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, src)) { cinfo->err->error_exit((struct jpeg_common_struct *) cinfo); } if (ret <= 0) { @@ -334,7 +334,7 @@ sun_jpeg_fill_suspended_buffer(j_decompress_ptr cinfo) RELEASE_ARRAYS(env, src); ret = (*env)->CallIntMethod(env, src->hInputStream, InputStream_availableID); - if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) { + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, src)) { cinfo->err->error_exit((struct jpeg_common_struct *) cinfo); } if (ret < 0 || (unsigned int)ret <= src->remaining_skip) { @@ -359,7 +359,7 @@ sun_jpeg_fill_suspended_buffer(j_decompress_ptr cinfo) ret = (*env)->CallIntMethod(env, src->hInputStream, InputStream_readID, src->hInputBuffer, offset, buflen); if ((ret > 0) && ((unsigned int)ret > buflen)) ret = (int)buflen; - if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) { + if ((*env)->ExceptionCheck(env) || !GET_ARRAYS(env, src)) { cinfo->err->error_exit((struct jpeg_common_struct *) cinfo); } if (ret <= 0) { @@ -439,7 +439,7 @@ sun_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) InputStream_readID, src->hInputBuffer, 0, buflen); if (ret > buflen) ret = buflen; - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { cinfo->err->error_exit((struct jpeg_common_struct *) cinfo); } if (ret < 0) { @@ -538,7 +538,7 @@ Java_sun_awt_image_JPEGImageDecoder_readImage(JNIEnv *env, */ jpeg_destroy_decompress(&cinfo); RELEASE_ARRAYS(env, &jsrc); - if (!(*env)->ExceptionOccurred(env)) { + if (!(*env)->ExceptionCheck(env)) { char buffer[JMSG_LENGTH_MAX]; (*cinfo.err->format_message) ((struct jpeg_common_struct *) &cinfo, buffer); @@ -584,7 +584,7 @@ Java_sun_awt_image_JPEGImageDecoder_readImage(JNIEnv *env, ret = (*env)->CallBooleanMethod(env, this, sendHeaderInfoID, cinfo.image_width, cinfo.image_height, grayscale, hasalpha, buffered_mode); - if ((*env)->ExceptionOccurred(env) || !ret) { + if ((*env)->ExceptionCheck(env) || !ret) { /* No more interest in this image... */ jpeg_destroy_decompress(&cinfo); return; @@ -694,7 +694,7 @@ Java_sun_awt_image_JPEGImageDecoder_readImage(JNIEnv *env, jsrc.hOutputBuffer, cinfo.output_scanline - 1); } - if ((*env)->ExceptionOccurred(env) || !ret || + if ((*env)->ExceptionCheck(env) || !ret || !GET_ARRAYS(env, &jsrc)) { /* No more interest in this image... */ jpeg_destroy_decompress(&cinfo); diff --git a/src/java.desktop/share/native/libjsound/PortMixer.c b/src/java.desktop/share/native/libjsound/PortMixer.c index c7f35b37b69..23f08d8dca6 100644 --- a/src/java.desktop/share/native/libjsound/PortMixer.c +++ b/src/java.desktop/share/native/libjsound/PortMixer.c @@ -209,7 +209,7 @@ void* PORT_NewBooleanControl(void* creatorV, void* controlID, char* type) { if (!ctrl) { ERROR0("PORT_NewBooleanControl: ctrl is NULL\n"); } - if ((*creator->env)->ExceptionOccurred(creator->env)) { + if ((*creator->env)->ExceptionCheck(creator->env)) { ERROR0("PORT_NewBooleanControl: ExceptionOccurred!\n"); } TRACE0("PORT_NewBooleanControl succeeded\n"); @@ -264,7 +264,7 @@ void* PORT_NewCompoundControl(void* creatorV, char* type, void** controls, int c if (!ctrl) { ERROR0("PORT_NewCompoundControl: ctrl is NULL\n"); } - if ((*creator->env)->ExceptionOccurred(creator->env)) { + if ((*creator->env)->ExceptionCheck(creator->env)) { ERROR0("PORT_NewCompoundControl: ExceptionOccurred!\n"); } TRACE0("PORT_NewCompoundControl succeeded\n"); @@ -327,7 +327,7 @@ void* PORT_NewFloatControl(void* creatorV, void* controlID, char* type, if (!ctrl) { ERROR0("PORT_NewFloatControl: ctrl is NULL!\n"); } - if ((*creator->env)->ExceptionOccurred(creator->env)) { + if ((*creator->env)->ExceptionCheck(creator->env)) { ERROR0("PORT_NewFloatControl: ExceptionOccurred!\n"); } TRACE1("PORT_NewFloatControl succeeded %p\n", (void*) ctrl); @@ -339,7 +339,7 @@ int PORT_AddControl(void* creatorV, void* control) { TRACE1("PORT_AddControl %p\n", (void*) control); (*creator->env)->CallVoidMethod(creator->env, creator->vector, creator->vectorAddElement, (jobject) control); - if ((*creator->env)->ExceptionOccurred(creator->env)) { + if ((*creator->env)->ExceptionCheck(creator->env)) { ERROR0("PORT_AddControl: ExceptionOccurred!\n"); } TRACE0("PORT_AddControl succeeded\n"); diff --git a/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c b/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c index d71e261decd..259afd94acb 100644 --- a/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c +++ b/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c @@ -122,7 +122,7 @@ Java_java_awt_SplashScreen__1getBounds(JNIEnv * env, jclass thisClass, if (clazz && mid) { bounds = (*env)->NewObject(env, clazz, mid, splash->x, splash->y, splash->width, splash->height); - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { bounds = NULL; (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); diff --git a/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java b/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java index 6640042259e..9ab68a4ff44 100644 --- a/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java +++ b/src/java.desktop/unix/classes/sun/awt/PlatformGraphicsInfo.java @@ -28,8 +28,6 @@ import java.io.File; import java.awt.GraphicsEnvironment; import java.awt.Toolkit; -import java.security.AccessController; -import java.security.PrivilegedAction; public class PlatformGraphicsInfo { @@ -47,14 +45,10 @@ public static Toolkit createToolkit() { * headless mode, in the case the application did not specify * a value for the java.awt.headless system property. */ - @SuppressWarnings("removal") public static boolean getDefaultHeadlessProperty() { - boolean noDisplay = - AccessController.doPrivileged((PrivilegedAction) () -> { + final String display = System.getenv("DISPLAY"); + boolean noDisplay = (display == null || display.trim().isEmpty()); - final String display = System.getenv("DISPLAY"); - return display == null || display.trim().isEmpty(); - }); if (noDisplay) { return true; } @@ -67,18 +61,16 @@ public static boolean getDefaultHeadlessProperty() { * code is also set up as headless from the start - it is not so easy * to try headful and then unwind that and then retry as headless. */ - boolean headless = - AccessController.doPrivileged((PrivilegedAction) () -> { - String[] libDirs = System.getProperty("sun.boot.library.path", "").split(":"); - for (String libDir : libDirs) { - File headlessLib = new File(libDir, "libawt_headless.so"); - File xawtLib = new File(libDir, "libawt_xawt.so"); - if (headlessLib.exists() && !xawtLib.exists()) { - return true; - } - } - return false; - }); + boolean headless = false; + String[] libDirs = System.getProperty("sun.boot.library.path", "").split(":"); + for (String libDir : libDirs) { + File headlessLib = new File(libDir, "libawt_headless.so"); + File xawtLib = new File(libDir, "libawt_xawt.so"); + if (headlessLib.exists() && !xawtLib.exists()) { + headless = true; + break; + } + } return headless; } diff --git a/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java b/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java index d509fe802b0..8e224414427 100644 --- a/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java +++ b/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java @@ -105,9 +105,7 @@ public int getNumber() { private BufferedImage tmpImage = null; public static int getDatatransferTimeout() { - @SuppressWarnings("removal") - Integer dt = AccessController.doPrivileged( - new GetIntegerAction("sun.awt.datatransfer.timeout")); + Integer dt = Integer.getInteger("sun.awt.datatransfer.timeout"); if (dt == null || dt <= 0) { return DEFAULT_DATATRANSFER_TIMEOUT; } else { @@ -118,18 +116,12 @@ public static int getDatatransferTimeout() { @Override public String getDesktop() { String gnome = "gnome"; - @SuppressWarnings("removal") - String gsi = AccessController.doPrivileged( - (PrivilegedAction) () - -> System.getenv("GNOME_DESKTOP_SESSION_ID")); + String gsi = System.getenv("GNOME_DESKTOP_SESSION_ID"); if (gsi != null) { return gnome; } - @SuppressWarnings("removal") - String desktop = AccessController.doPrivileged( - (PrivilegedAction) () - -> System.getenv("XDG_CURRENT_DESKTOP")); + String desktop = System.getenv("XDG_CURRENT_DESKTOP"); return (desktop != null && desktop.toLowerCase().contains(gnome)) ? gnome : null; } @@ -252,11 +244,7 @@ public boolean shouldDisableSystemTray() { result = shouldDisableSystemTray; if (result == null) { if ("gnome".equals(getDesktop())) { - @SuppressWarnings("removal") - Integer gnomeShellMajorVersion = - AccessController - .doPrivileged((PrivilegedAction) - this::getGnomeShellMajorVersion); + Integer gnomeShellMajorVersion = getGnomeShellMajorVersion(); if (gnomeShellMajorVersion == null || gnomeShellMajorVersion < 45) { @@ -486,9 +474,7 @@ public boolean checkGtkVersion(int major, int minor, int micro) { } public static GtkVersions getEnabledGtkVersion() { - @SuppressWarnings("removal") - String version = AccessController.doPrivileged( - new GetPropertyAction("jdk.gtk.version")); + String version = System.getProperty("jdk.gtk.version"); if ("3".equals(version)) { return GtkVersions.GTK3; } @@ -499,32 +485,22 @@ public static GtkVersions getGtkVersion() { return GtkVersions.getVersion(get_gtk_version()); } - @SuppressWarnings("removal") public static boolean isGtkVerbose() { - return AccessController.doPrivileged((PrivilegedAction)() - -> Boolean.getBoolean("jdk.gtk.verbose")); + return Boolean.getBoolean("jdk.gtk.verbose"); } private static volatile Boolean isOnWayland = null; - @SuppressWarnings("removal") public static boolean isOnWayland() { Boolean result = isOnWayland; if (result == null) { synchronized (GTK_LOCK) { result = isOnWayland; if (result == null) { + final String display = System.getenv("WAYLAND_DISPLAY"); isOnWayland = result - = AccessController.doPrivileged( - (PrivilegedAction) () -> { - final String display = - System.getenv("WAYLAND_DISPLAY"); - - return display != null - && !display.trim().isEmpty(); - } - ); + = (display != null && !display.trim().isEmpty()); } } } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java b/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java index d86d49290a4..641e2f86c02 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java @@ -47,8 +47,6 @@ import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.text.BreakIterator; import java.util.concurrent.ArrayBlockingQueue; @@ -227,16 +225,8 @@ public void run() { textLabel.setText(tooltipString); } - @SuppressWarnings("removal") - Point pointer = AccessController.doPrivileged( - new PrivilegedAction() { - public Point run() { - if (!isPointerOverTrayIcon(liveArguments.getBounds())) { - return null; - } - return MouseInfo.getPointerInfo().getLocation(); - } - }); + Point pointer = !isPointerOverTrayIcon(liveArguments.getBounds()) + ? null : MouseInfo.getPointerInfo().getLocation(); if (pointer == null) { return; } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/Native.java b/src/java.desktop/unix/classes/sun/awt/X11/Native.java index 744e665baaa..773668ff53a 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/Native.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/Native.java @@ -27,8 +27,6 @@ import jdk.internal.misc.Unsafe; import java.util.Vector; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * This class contains the collection of utility functions to help work with @@ -43,13 +41,7 @@ class Native { static int dataModel; static { - @SuppressWarnings("removal") - String dataModelProp = AccessController.doPrivileged( - new PrivilegedAction() { - public String run() { - return System.getProperty("sun.arch.data.model"); - } - }); + String dataModelProp = System.getProperty("sun.arch.data.model"); try { dataModel = Integer.parseInt(dataModelProp); } catch (Exception e) { diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XClipboard.java b/src/java.desktop/unix/classes/sun/awt/X11/XClipboard.java index a12dddcb7df..3a36c3195a8 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XClipboard.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XClipboard.java @@ -29,14 +29,12 @@ import java.awt.datatransfer.DataFlavor; import java.util.SortedMap; import java.io.IOException; -import java.security.AccessController; import java.util.HashMap; import java.util.Map; import sun.awt.UNIXToolkit; import sun.awt.datatransfer.DataTransferer; import sun.awt.datatransfer.SunClipboard; import sun.awt.datatransfer.ClipboardTransferable; -import sun.security.action.GetIntegerAction; /** * A class which interfaces with the X11 selection service in order to support @@ -129,13 +127,11 @@ private void checkChangeHere(Transferable contents) { } } - @SuppressWarnings("removal") private static int getPollInterval() { synchronized (XClipboard.classLock) { if (pollInterval <= 0) { - pollInterval = AccessController.doPrivileged( - new GetIntegerAction("awt.datatransfer.clipboard.poll.interval", - defaultPollInterval)); + pollInterval = Integer.getInteger("awt.datatransfer.clipboard.poll.interval" + , defaultPollInterval); if (pollInterval <= 0) { pollInterval = defaultPollInterval; } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java index 4317136816c..57e06cf94de 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java @@ -35,9 +35,6 @@ import java.util.*; import static sun.awt.X11.XEmbedHelper.*; -import java.security.AccessController; -import sun.security.action.GetBooleanAction; - public class XEmbedCanvasPeer extends XCanvasPeer implements WindowFocusListener, KeyEventPostProcessor, ModalityListener, WindowIDProvider { private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed.XEmbedCanvasPeer"); @@ -439,12 +436,11 @@ void canvasFocusGained(FocusEvent e) { } } - @SuppressWarnings("removal") void canvasFocusLost(FocusEvent e) { if (isXEmbedActive() && !e.isTemporary()) { xembedLog.fine("Forwarding FOCUS_LOST"); int num = 0; - if (AccessController.doPrivileged(new GetBooleanAction("sun.awt.xembed.testing"))) { + if (Boolean.getBoolean("sun.awt.xembed.testing")) { Component opp = e.getOppositeComponent(); try { num = Integer.parseInt(opp.getName()); diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XErrorHandlerUtil.java b/src/java.desktop/unix/classes/sun/awt/X11/XErrorHandlerUtil.java index 9d43399e23c..1dfaa4b8d4d 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XErrorHandlerUtil.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XErrorHandlerUtil.java @@ -24,9 +24,7 @@ */ package sun.awt.X11; -import java.security.AccessController; import sun.awt.SunToolkit; -import sun.security.action.GetBooleanAction; import sun.util.logging.PlatformLogger; /** @@ -59,9 +57,7 @@ public final class XErrorHandlerUtil { /** * Value of sun.awt.noisyerrorhandler system property. */ - @SuppressWarnings("removal") - private static boolean noisyAwtHandler = AccessController.doPrivileged( - new GetBooleanAction("sun.awt.noisyerrorhandler")); + private static boolean noisyAwtHandler = Boolean.getBoolean("sun.awt.noisyerrorhandler"); /** * The flag indicating that {@code init} was called already. diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XFileDialogPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XFileDialogPeer.java index f11f11ba53e..596bc493f00 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XFileDialogPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XFileDialogPeer.java @@ -32,8 +32,6 @@ import java.io.*; import java.util.Locale; import java.util.Arrays; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.awt.AWTAccessor.ComponentAccessor; import sun.util.logging.PlatformLogger; @@ -139,7 +137,7 @@ void installStrings() { this.target = target; } - @SuppressWarnings({"removal","deprecation"}) + @SuppressWarnings("deprecation") private void init(FileDialog target) { fileDialog = target; //new Dialog(target, target.getTitle(), false); this.title = target.getTitle(); @@ -151,12 +149,7 @@ private void init(FileDialog target) { savedDir = target.getDirectory(); // Shouldn't save 'user.dir' to 'savedDir' // since getDirectory() will be incorrect after handleCancel - userDir = AccessController.doPrivileged( - new PrivilegedAction() { - public String run() { - return System.getProperty("user.dir"); - } - }); + userDir = System.getProperty("user.dir"); installStrings(); gbl = new GridBagLayout(); diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java index 6d155c0bcc8..010c5aeff5a 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java @@ -28,7 +28,6 @@ import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.peer.RobotPeer; -import java.security.AccessController; import sun.awt.AWTAccessor; import sun.awt.SunToolkit; @@ -36,9 +35,7 @@ import sun.awt.X11GraphicsConfig; import sun.awt.X11GraphicsDevice; import sun.awt.screencast.ScreencastHelper; -import sun.security.action.GetPropertyAction; -@SuppressWarnings("removal") final class XRobotPeer implements RobotPeer { private static final boolean tryGtk; @@ -50,10 +47,8 @@ final class XRobotPeer implements RobotPeer { loadNativeLibraries(); tryGtk = Boolean.parseBoolean( - AccessController.doPrivileged( - new GetPropertyAction("awt.robot.gtk", - "true") - )); + System.getProperty("awt.robot.gtk", "true") + ); boolean isOnWayland = false; @@ -61,13 +56,12 @@ final class XRobotPeer implements RobotPeer { isOnWayland = sunToolkit.isRunningOnWayland(); } - screenshotMethod = AccessController.doPrivileged( - new GetPropertyAction( + screenshotMethod = System.getProperty( "awt.robot.screenshotMethod", isOnWayland ? METHOD_SCREENCAST : METHOD_X11 - )); + ); } private static volatile boolean useGtk; diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java index 33bebe77de7..73668bf591c 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java @@ -31,9 +31,6 @@ import java.awt.event.ActionEvent; import sun.awt.UNIXToolkit; -import java.security.AccessController; -import java.security.PrivilegedAction; -import sun.security.action.GetPropertyAction; final class XTaskbarPeer implements TaskbarPeer { @@ -44,10 +41,7 @@ final class XTaskbarPeer implements TaskbarPeer { private static boolean isUnity; static { - @SuppressWarnings("removal") - String de = AccessController.doPrivileged( - (PrivilegedAction) () - -> System.getenv("XDG_CURRENT_DESKTOP")); + String de = System.getenv("XDG_CURRENT_DESKTOP"); isUnity = "Unity".equals(de); } @@ -55,9 +49,7 @@ private static void initWithLock() { XToolkit.awtLock(); try { if (!initExecuted) { - @SuppressWarnings("removal") - String dname = AccessController.doPrivileged( - new GetPropertyAction("java.desktop.appName", "")); + String dname = System.getProperty("java.desktop.appName", ""); nativeLibraryLoaded = init(dname, UNIXToolkit.getEnabledGtkVersion().ordinal(), UNIXToolkit.isGtkVerbose()); diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index 1b4f45b55f1..920e1235fca 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -111,8 +111,6 @@ import java.awt.peer.TrayIconPeer; import java.awt.peer.WindowPeer; import java.beans.PropertyChangeListener; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -147,8 +145,6 @@ import sun.font.FontConfigManager; import sun.java2d.SunGraphicsEnvironment; import sun.print.PrintJob2D; -import sun.security.action.GetBooleanAction; -import sun.security.action.GetPropertyAction; import sun.util.logging.PlatformLogger; import static sun.awt.X11.XlibUtil.scaleDown; @@ -246,9 +242,7 @@ static boolean isToolkitThread() { static void initSecurityWarning() { // Enable warning only for internal builds - @SuppressWarnings("removal") - String runtime = AccessController.doPrivileged( - new GetPropertyAction("java.runtime.version")); + String runtime = System.getProperty("java.runtime.version"); securityWarningEnabled = (runtime != null && runtime.contains("internal")); } @@ -326,7 +320,6 @@ public static long getDefaultRootWindow() { } } - @SuppressWarnings("removal") void init() { awtLock(); try { @@ -339,13 +332,10 @@ void init() { arrowCursor = XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(), XCursorFontConstants.XC_arrow); final String extraButtons = "sun.awt.enableExtraMouseButtons"; - AccessController.doPrivileged((PrivilegedAction) () -> { - areExtraMouseButtonsEnabled = - Boolean.parseBoolean(System.getProperty(extraButtons, "true")); - //set system property if not yet assigned - System.setProperty(extraButtons, ""+areExtraMouseButtonsEnabled); - return null; - }); + areExtraMouseButtonsEnabled = + Boolean.parseBoolean(System.getProperty(extraButtons, "true")); + //set system property if not yet assigned + System.setProperty(extraButtons, "" + areExtraMouseButtonsEnabled); // Detect display mode changes XlibWrapper.XSelectInput(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(), XConstants.StructureNotifyMask); XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(), new XEventDispatcher() { @@ -370,28 +360,24 @@ public void dispatchEvent(XEvent ev) { } finally { awtUnlock(); } - PrivilegedAction a = () -> { - Runnable r = () -> { - XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance(); - if (peer != null) { - peer.dispose(); - } - if (xs != null) { - ((XAWTXSettings)xs).dispose(); - } - freeXKB(); - if (log.isLoggable(PlatformLogger.Level.FINE)) { - dumpPeers(); - } - }; - String name = "XToolkt-Shutdown-Thread"; - Thread shutdownThread = new Thread( - ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); - shutdownThread.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(shutdownThread); - return null; + Runnable r = () -> { + XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance(); + if (peer != null) { + peer.dispose(); + } + if (xs != null) { + ((XAWTXSettings)xs).dispose(); + } + freeXKB(); + if (log.isLoggable(PlatformLogger.Level.FINE)) { + dumpPeers(); + } }; - AccessController.doPrivileged(a); + String name = "XToolkt-Shutdown-Thread"; + Thread shutdownThread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); + shutdownThread.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(shutdownThread); } static String getCorrectXIDString(String val) { @@ -409,7 +395,6 @@ static String getAWTAppClassName() { return awtAppClassName; } - @SuppressWarnings("removal") public XToolkit() { super(); if (PerformanceLogger.loggingEnabled()) { @@ -432,16 +417,13 @@ public XToolkit() { init(); XWM.init(); - toolkitThread = AccessController.doPrivileged((PrivilegedAction) () -> { - String name = "AWT-XAWT"; - Thread thread = new Thread( + String name = "AWT-XAWT"; + toolkitThread = new Thread( ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); - thread.setContextClassLoader(null); - thread.setPriority(Thread.NORM_PRIORITY + 1); - thread.setDaemon(true); - return thread; - }); + toolkitThread.setContextClassLoader(null); + toolkitThread.setPriority(Thread.NORM_PRIORITY + 1); + toolkitThread.setDaemon(true); toolkitThread.start(); } } @@ -1120,11 +1102,9 @@ public DialogPeer createDialog(Dialog target) { * Returns the value of "sun.awt.disableGtkFileDialogs" property. Default * value is {@code false}. */ - @SuppressWarnings("removal") public static synchronized boolean getSunAwtDisableGtkFileDialogs() { if (sunAwtDisableGtkFileDialogs == null) { - sunAwtDisableGtkFileDialogs = AccessController.doPrivileged( - new GetBooleanAction("sun.awt.disableGtkFileDialogs")); + sunAwtDisableGtkFileDialogs = Boolean.getBoolean("sun.awt.disableGtkFileDialogs"); } return sunAwtDisableGtkFileDialogs.booleanValue(); } @@ -2139,9 +2119,7 @@ static int getBackingStoreType() { } private static void setBackingStoreType() { - @SuppressWarnings("removal") - String prop = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.awt.backingStore")); + String prop = System.getProperty("sun.awt.backingStore"); if (prop == null) { backingStoreType = XConstants.NotUseful; @@ -2565,8 +2543,7 @@ public boolean isTranslucencyCapable(GraphicsConfiguration gc) { * Returns the value of "sun.awt.disablegrab" property. Default * value is {@code false}. */ - @SuppressWarnings("removal") public static boolean getSunAwtDisableGrab() { - return AccessController.doPrivileged(new GetBooleanAction("sun.awt.disablegrab")); + return Boolean.getBoolean("sun.awt.disablegrab"); } } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java index a53dbebdd15..c3711010b7c 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java @@ -30,8 +30,6 @@ import java.awt.peer.TrayIconPeer; import sun.awt.*; import java.awt.image.*; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.lang.reflect.InvocationTargetException; import sun.util.logging.PlatformLogger; @@ -66,7 +64,6 @@ public void dispatchEvent(XEvent ev) {} static final int TRAY_ICON_WIDTH = 24; static final int TRAY_ICON_HEIGHT = 24; - @SuppressWarnings("removal") XTrayIconPeer(TrayIcon target) throws AWTException { @@ -84,12 +81,7 @@ public void dispatchEvent(XEvent ev) {} // Fix for 6317038: as EmbeddedFrame is instance of Frame, it is blocked // by modal dialogs, but in the case of TrayIcon it shouldn't. So we // set ModalExclusion property on it. - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - eframe.setModalExclusionType(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); - return null; - } - }); + eframe.setModalExclusionType(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); if (XWM.getWMID() != XWM.METACITY_WM) { diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java index 1c0f8e27ffb..267ad9349ea 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java @@ -767,28 +767,12 @@ protected Point getNewLocation(XConfigureEvent xe, int leftInset, int topInset) // a window is resized but the client can not tell if the window was // moved or not. The client should consider the position as unknown // and use TranslateCoordinates to find the actual position. - // - // TODO this should be the default for every case. - switch (runningWM) { - case XWM.CDE_WM: - case XWM.KDE2_WM: - case XWM.MOTIF_WM: - case XWM.METACITY_WM: - case XWM.MUTTER_WM: - case XWM.SAWFISH_WM: - case XWM.UNITY_COMPIZ_WM: - { - Point xlocation = queryXLocation(); - if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("New X location: {0}", xlocation); - } - if (xlocation != null) { - newLocation = xlocation; - } - break; - } - default: - break; + Point xlocation = queryXLocation(); + if (log.isLoggable(PlatformLogger.Level.FINE)) { + log.fine("New X location: {0}", xlocation); + } + if (xlocation != null) { + newLocation = xlocation; } } return newLocation; diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java b/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java index 7a23c806374..804107d9820 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java @@ -25,10 +25,7 @@ package sun.awt.X11; -import java.security.AccessController; - import jdk.internal.misc.Unsafe; -import sun.security.action.GetPropertyAction; final class XlibWrapper { @@ -585,9 +582,7 @@ static native void SetBitmapShape(long display, long window, static final boolean isBuildInternal; static { - @SuppressWarnings("removal") - String dataModelProp = AccessController.doPrivileged( - new GetPropertyAction("sun.arch.data.model")); + String dataModelProp = System.getProperty("sun.arch.data.model"); try { dataModel = Integer.parseInt(dataModelProp); } catch (Exception e) { @@ -639,9 +634,7 @@ static String getEventToString( int type ) { } private static boolean getBuildInternal() { - @SuppressWarnings("removal") - String javaVersion = AccessController.doPrivileged( - new GetPropertyAction("java.version")); + String javaVersion = System.getProperty("java.version"); return javaVersion != null && javaVersion.contains("internal"); } diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index 03f06408765..ca43142a098 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -33,8 +33,6 @@ import java.awt.Insets; import java.awt.Rectangle; import java.awt.Window; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -447,7 +445,6 @@ public synchronized DisplayMode[] getDisplayModes() { return modes.toArray(retArray); } - @SuppressWarnings("removal") @Override public synchronized void setDisplayMode(DisplayMode dm) { if (!isDisplayChangeSupported()) { @@ -474,24 +471,20 @@ public synchronized void setDisplayMode(DisplayMode dm) { // is already in the original DisplayMode at that time, this // hook will have no effect) shutdownHookRegistered = true; - PrivilegedAction a = () -> { - Runnable r = () -> { - Window old = getFullScreenWindow(); - if (old != null) { - exitFullScreenExclusive(old); - if (isDisplayChangeSupported()) { - setDisplayMode(origDisplayMode); - } + Runnable r = () -> { + Window old = getFullScreenWindow(); + if (old != null) { + exitFullScreenExclusive(old); + if (isDisplayChangeSupported()) { + setDisplayMode(origDisplayMode); } - }; - String name = "Display-Change-Shutdown-Thread-" + screen; - Thread t = new Thread( - ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); - t.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(t); - return null; + } }; - AccessController.doPrivileged(a); + String name = "Display-Change-Shutdown-Thread-" + screen; + Thread t = new Thread( + ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); + t.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(t); } // switch to the new DisplayMode diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java index 42b20f66843..9d42e2c92da 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java @@ -59,78 +59,71 @@ public final class X11GraphicsEnvironment extends SunGraphicsEnvironment { initStatic(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void initStatic() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - System.loadLibrary("awt"); - - /* - * Note: The XToolkit object depends on the static initializer - * of X11GraphicsEnvironment to initialize the connection to - * the X11 server. - */ - if (!isHeadless()) { - // first check the OGL system property - boolean glxRequested = false; - String prop = System.getProperty("sun.java2d.opengl"); - if (prop != null) { - if (prop.equals("true") || prop.equals("t")) { - glxRequested = true; - } else if (prop.equals("True") || prop.equals("T")) { - glxRequested = true; - glxVerbose = true; - } - } + System.loadLibrary("awt"); + + /* + * Note: The XToolkit object depends on the static initializer + * of X11GraphicsEnvironment to initialize the connection to + * the X11 server. + */ + if (!isHeadless()) { + // first check the OGL system property + boolean glxRequested = false; + String prop = System.getProperty("sun.java2d.opengl"); + if (prop != null) { + if (prop.equals("true") || prop.equals("t")) { + glxRequested = true; + } else if (prop.equals("True") || prop.equals("T")) { + glxRequested = true; + glxVerbose = true; + } + } - // Now check for XRender system property - boolean xRenderRequested = true; - boolean xRenderIgnoreLinuxVersion = false; - String xProp = System.getProperty("sun.java2d.xrender"); - if (xProp != null) { - if (xProp.equals("false") || xProp.equals("f")) { - xRenderRequested = false; - } else if (xProp.equals("True") || xProp.equals("T")) { - xRenderRequested = true; - xRenderVerbose = true; - } - - if(xProp.equalsIgnoreCase("t") || xProp.equalsIgnoreCase("true")) { - xRenderIgnoreLinuxVersion = true; - } - } + // Now check for XRender system property + boolean xRenderRequested = true; + boolean xRenderIgnoreLinuxVersion = false; + String xProp = System.getProperty("sun.java2d.xrender"); + if (xProp != null) { + if (xProp.equals("false") || xProp.equals("f")) { + xRenderRequested = false; + } else if (xProp.equals("True") || xProp.equals("T")) { + xRenderRequested = true; + xRenderVerbose = true; + } - // initialize the X11 display connection - initDisplay(glxRequested); - - // only attempt to initialize GLX if it was requested - if (glxRequested) { - glxAvailable = initGLX(); - if (glxVerbose && !glxAvailable) { - System.out.println( - "Could not enable OpenGL " + - "pipeline (GLX 1.3 not available)"); - } - } + if (xProp.equalsIgnoreCase("t") || xProp.equalsIgnoreCase("true")) { + xRenderIgnoreLinuxVersion = true; + } + } - // only attempt to initialize Xrender if it was requested - if (xRenderRequested) { - xRenderAvailable = initXRender(xRenderVerbose, xRenderIgnoreLinuxVersion); - if (xRenderVerbose && !xRenderAvailable) { - System.out.println( - "Could not enable XRender pipeline"); - } - } + // initialize the X11 display connection + initDisplay(glxRequested); - if (xRenderAvailable) { - XRSurfaceData.initXRSurfaceData(); - } + // only attempt to initialize GLX if it was requested + if (glxRequested) { + glxAvailable = initGLX(); + if (glxVerbose && !glxAvailable) { + System.out.println( + "Could not enable OpenGL " + + "pipeline (GLX 1.3 not available)"); + } + } + + // only attempt to initialize Xrender if it was requested + if (xRenderRequested) { + xRenderAvailable = initXRender(xRenderVerbose, xRenderIgnoreLinuxVersion); + if (xRenderVerbose && !xRenderAvailable) { + System.out.println( + "Could not enable XRender pipeline"); } + } - return null; + if (xRenderAvailable) { + XRSurfaceData.initXRSurfaceData(); } - }); + } // Install the correct surface manager factory. SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory()); @@ -299,9 +292,7 @@ private static boolean _isDisplayLocal() { return true; } - @SuppressWarnings("removal") - String isRemote = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.java2d.remote")); + String isRemote = System.getProperty("sun.java2d.remote"); if (isRemote != null) { return isRemote.equals("false"); } @@ -322,41 +313,35 @@ private static boolean _isDisplayLocal() { return true; } - @SuppressWarnings("removal") - Boolean result = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Boolean run() { - InetAddress[] remAddr = null; - Enumeration locals = null; - Enumeration interfaces = null; - try { - interfaces = NetworkInterface.getNetworkInterfaces(); - remAddr = InetAddress.getAllByName(hostName); - if (remAddr == null) { - return Boolean.FALSE; - } - } catch (UnknownHostException e) { - System.err.println("Unknown host: " + hostName); - return Boolean.FALSE; - } catch (SocketException e1) { - System.err.println(e1.getMessage()); - return Boolean.FALSE; - } + InetAddress[] remAddr = null; + Enumeration locals = null; + Enumeration interfaces = null; + try { + interfaces = NetworkInterface.getNetworkInterfaces(); + remAddr = InetAddress.getAllByName(hostName); + if (remAddr == null) { + return false; + } + } catch (UnknownHostException e) { + System.err.println("Unknown host: " + hostName); + return false; + } catch (SocketException e1) { + System.err.println(e1.getMessage()); + return false; + } - for (; interfaces.hasMoreElements();) { - locals = interfaces.nextElement().getInetAddresses(); - for (; locals.hasMoreElements();) { - final InetAddress localAddr = locals.nextElement(); - for (int i = 0; i < remAddr.length; i++) { - if (localAddr.equals(remAddr[i])) { - return Boolean.TRUE; - } - } + for (; interfaces.hasMoreElements();) { + locals = interfaces.nextElement().getInetAddresses(); + for (; locals.hasMoreElements();) { + final InetAddress localAddr = locals.nextElement(); + for (int i = 0; i < remAddr.length; i++) { + if (localAddr.equals(remAddr[i])) { + return true; } } - return Boolean.FALSE; - }}); - return result.booleanValue(); + } + } + return false; } diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java b/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java index 78661587554..8f276954d6d 100644 --- a/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java +++ b/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java @@ -27,14 +27,12 @@ import sun.awt.UNIXToolkit; import sun.java2d.pipe.Region; -import sun.security.action.GetPropertyAction; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.geom.AffineTransform; -import java.security.AccessController; import java.util.Arrays; import java.util.List; import java.util.Set; @@ -48,7 +46,6 @@ * org.freedesktop.portal.ScreenCast API */ -@SuppressWarnings("removal") public class ScreencastHelper { static final boolean SCREENCAST_DEBUG; @@ -70,13 +67,7 @@ private ScreencastHelper() { } static { - SCREENCAST_DEBUG = Boolean.parseBoolean( - AccessController.doPrivileged( - new GetPropertyAction( - "awt.robot.screenshotDebug", - "false" - ) - )); + SCREENCAST_DEBUG = Boolean.getBoolean("awt.robot.screenshotDebug"); boolean loadFailed = false; diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java index b05ff7f8c4a..0db18c9c3b7 100644 --- a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java +++ b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java @@ -37,8 +37,6 @@ import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.nio.file.attribute.PosixFilePermission; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashSet; @@ -73,18 +71,8 @@ private TokenStorage() {} private static final Path PROPS_PATH; private static final Path PROP_FILENAME; - @SuppressWarnings("removal") - private static void doPrivilegedRunnable(Runnable runnable) { - AccessController.doPrivileged((PrivilegedAction) () -> { - runnable.run(); - return null; - }); - } - static { - @SuppressWarnings("removal") - Path propsPath = AccessController - .doPrivileged((PrivilegedAction) () -> setupPath()); + Path propsPath = setupPath(); PROPS_PATH = propsPath; @@ -226,9 +214,9 @@ public void run() { } if (kind == ENTRY_CREATE) { - doPrivilegedRunnable(() -> setFilePermission(PROPS_PATH)); + setFilePermission(PROPS_PATH); } else if (kind == ENTRY_MODIFY) { - doPrivilegedRunnable(() -> readTokens(PROPS_PATH)); + readTokens(PROPS_PATH); } else if (kind == ENTRY_DELETE) { synchronized (PROPS) { PROPS.clear(); @@ -244,25 +232,23 @@ public void run() { private static WatchService watchService; private static void setupWatch() { - doPrivilegedRunnable(() -> { - try { - watchService = - FileSystems.getDefault().newWatchService(); - - PROPS_PATH - .getParent() - .register(watchService, - ENTRY_CREATE, - ENTRY_DELETE, - ENTRY_MODIFY); - - } catch (Exception e) { - if (SCREENCAST_DEBUG) { - System.err.printf("Token storage: failed to setup " + - "file watch %s\n", e); - } + try { + watchService = + FileSystems.getDefault().newWatchService(); + + PROPS_PATH + .getParent() + .register(watchService, + ENTRY_CREATE, + ENTRY_DELETE, + ENTRY_MODIFY); + + } catch (Exception e) { + if (SCREENCAST_DEBUG) { + System.err.printf("Token storage: failed to setup " + + "file watch %s\n", e); } - }); + } if (watchService != null) { new WatcherThread(watchService).start(); @@ -317,7 +303,7 @@ private static void storeTokenFromNative(String oldToken, } if (changed) { - doPrivilegedRunnable(() -> store(PROPS_PATH, "save tokens")); + store(PROPS_PATH, "save tokens"); } } } @@ -372,7 +358,7 @@ static Set getTokens(List affectedScreenBounds) { .toList(); } - doPrivilegedRunnable(() -> removeMalformedRecords(malformed)); + removeMalformedRecords(malformed); // 1. Try to find exact matches for (TokenItem tokenItem : allTokenItems) { diff --git a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java index 8638bd3f594..0e9b612301c 100644 --- a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java +++ b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java @@ -363,11 +363,6 @@ protected void setOsNameAndVersion() { private File getFcInfoFile() { if (fcInfoFileName == null) { - // NB need security permissions to get true IP address, and - // we should have those as the whole initialisation is in a - // doPrivileged block. But in this case no exception is thrown, - // and it returns the loop back address, and so we end up with - // "localhost" String hostname; try { hostname = InetAddress.getLocalHost().getHostName(); diff --git a/src/java.desktop/unix/classes/sun/java2d/x11/X11SurfaceData.java b/src/java.desktop/unix/classes/sun/java2d/x11/X11SurfaceData.java index 0210dd929cb..88c44369abf 100644 --- a/src/java.desktop/unix/classes/sun/java2d/x11/X11SurfaceData.java +++ b/src/java.desktop/unix/classes/sun/java2d/x11/X11SurfaceData.java @@ -210,9 +210,7 @@ public Raster getRaster(int x, int y, int w, int h) { initIDs(XORComposite.class); - @SuppressWarnings("removal") - String xtextpipe = java.security.AccessController.doPrivileged - (new sun.security.action.GetPropertyAction("sun.java2d.xtextpipe")); + String xtextpipe = System.getProperty("sun.java2d.xtextpipe"); if (xtextpipe == null || "true".startsWith(xtextpipe)) { if ("true".equals(xtextpipe)) { // Only verbose if they use the full string "true" @@ -248,9 +246,7 @@ public static boolean isAccelerationEnabled() { if (GraphicsEnvironment.isHeadless()) { accelerationEnabled = Boolean.FALSE; } else { - @SuppressWarnings("removal") - String prop = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.java2d.pmoffscreen")); + String prop = System.getProperty("sun.java2d.pmoffscreen"); if (prop != null) { // true iff prop==true, false otherwise accelerationEnabled = Boolean.valueOf(prop); diff --git a/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java b/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java index c2201cb7c7c..0d10e85f607 100644 --- a/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java +++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java @@ -30,8 +30,6 @@ import java.awt.Paint; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.awt.image.PixelConverter; import sun.font.XRTextRenderer; @@ -93,13 +91,7 @@ public static synchronized XRCompositeManager getInstance( private XRCompositeManager(XRSurfaceData surface) { con = new XRBackendNative(); - @SuppressWarnings("removal") - String gradProp = - AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return System.getProperty("sun.java2d.xrgradcache"); - } - }); + String gradProp = System.getProperty("sun.java2d.xrgradcache"); enableGradCache = gradProp == null || !(gradProp.equalsIgnoreCase("false") || diff --git a/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java b/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java index 8be118c42a5..62c43316065 100644 --- a/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java +++ b/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java @@ -90,16 +90,10 @@ public class CUPSPrinter { initStatic(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void initStatic() { // load awt library to access native code - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); libFound = initIDs(); if (libFound) { cupsServer = getCupsServer(); @@ -308,18 +302,12 @@ static String[] getDefaultPrinter() { IPPPrintService.getIPPConnection(url); if (urlConnection != null) { - @SuppressWarnings("removal") - OutputStream os = java.security.AccessController. - doPrivileged(new java.security.PrivilegedAction() { - public OutputStream run() { - try { - return urlConnection.getOutputStream(); - } catch (Exception e) { - IPPPrintService.debug_println(debugPrefix+e); - } - return null; - } - }); + OutputStream os = null; + try { + os = urlConnection.getOutputStream(); + } catch (Exception e) { + IPPPrintService.debug_println(debugPrefix+e); + } if (os == null) { return null; @@ -424,17 +412,11 @@ static String[] getAllPrinters() { IPPPrintService.getIPPConnection(url); if (urlConnection != null) { - @SuppressWarnings("removal") - OutputStream os = java.security.AccessController. - doPrivileged(new java.security.PrivilegedAction() { - public OutputStream run() { - try { - return urlConnection.getOutputStream(); - } catch (Exception e) { - } - return null; - } - }); + OutputStream os = null; + try { + os = urlConnection.getOutputStream(); + } catch (Exception e) { + } if (os == null) { return null; @@ -507,12 +489,9 @@ private static String getDomainSocketPathname() { return domainSocketPathname; } - @SuppressWarnings("removal") private static boolean isSandboxedApp() { if (PrintServiceLookupProvider.isMac()) { - return java.security.AccessController - .doPrivileged((java.security.PrivilegedAction) () -> - System.getenv("APP_SANDBOX_CONTAINER_ID") != null); + return (System.getenv("APP_SANDBOX_CONTAINER_ID") != null); } return false; } diff --git a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java index 5a6437014dd..4d217ec6e3e 100644 --- a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java +++ b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java @@ -119,9 +119,7 @@ protected static void debug_println(String str) { private static final String FORCE_PIPE_PROP = "sun.print.ippdebug"; static { - @SuppressWarnings("removal") - String debugStr = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction(FORCE_PIPE_PROP)); + String debugStr = System.getProperty(FORCE_PIPE_PROP); debugPrint = "true".equalsIgnoreCase(debugStr); } @@ -1874,18 +1872,12 @@ private void opGetAttributes() { AttributeClass.TAG_URI, ""+myURI)}; - @SuppressWarnings("removal") - OutputStream os = java.security.AccessController. - doPrivileged(new java.security.PrivilegedAction() { - public OutputStream run() { - try { - return urlConnection.getOutputStream(); - } catch (Exception e) { - } - return null; - } - }); + OutputStream os = null; + try { + os = urlConnection.getOutputStream(); + } catch (Exception e) { + } if (os == null) { return; } diff --git a/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java b/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java index 5e45b00861e..15025d43d6f 100644 --- a/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java +++ b/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java @@ -28,12 +28,8 @@ import java.io.BufferedReader; import java.io.IOException; import java.net.MalformedURLException; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Vector; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import javax.print.DocFlavor; import javax.print.MultiDocPrintService; import javax.print.PrintService; @@ -95,9 +91,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup * can be used to force the printing code to poll or not poll * for PrintServices. */ - @SuppressWarnings("removal") - String pollStr = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.java2d.print.polling")); + String pollStr = System.getProperty("sun.java2d.print.polling"); if (pollStr != null) { if (pollStr.equalsIgnoreCase("true")) { @@ -111,10 +105,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup * can be used to specify minimum refresh time (in seconds) * for polling PrintServices. The default is 120. */ - @SuppressWarnings("removal") - String refreshTimeStr = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "sun.java2d.print.minRefreshTime")); + String refreshTimeStr = System.getProperty("sun.java2d.print.minRefreshTime"); if (refreshTimeStr != null) { try { @@ -132,9 +123,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup * take lots of time if thousands of printers are attached to a server. */ if (isAIX()) { - @SuppressWarnings("removal") - String aixPrinterEnumerator = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.java2d.print.aix.lpstat")); + String aixPrinterEnumerator = System.getProperty("sun.java2d.print.aix.lpstat"); if (aixPrinterEnumerator != null) { if (aixPrinterEnumerator.equalsIgnoreCase("lpstat")) { @@ -202,18 +191,15 @@ static int getBSDCommandIndex() { return BSD_LPD; } - @SuppressWarnings("removal") public PrintServiceLookupProvider() { // start the printer listener thread if (pollServices) { - AccessController.doPrivileged((PrivilegedAction) () -> { - Thread thr = new Thread(ThreadGroupUtils.getRootThreadGroup(), - new PrinterChangeListener(), - "PrinterListener", 0, false); - thr.setContextClassLoader(null); - thr.setDaemon(true); - return thr; - }).start(); + Thread thr = new Thread(ThreadGroupUtils.getRootThreadGroup(), + new PrinterChangeListener(), + "PrinterListener", 0, false); + thr.setContextClassLoader(null); + thr.setDaemon(true); + thr.start(); IPPPrintService.debug_println(debugPrefix+"polling turned on"); } } @@ -871,7 +857,6 @@ private String[] getAllPrinterNamesAIX() { return printerNames.toArray(new String[printerNames.size()]); } - @SuppressWarnings("removal") static String[] execCmd(final String command) { ArrayList results = null; try { @@ -886,51 +871,46 @@ static String[] execCmd(final String command) { cmd[2] = "LC_ALL=C " + command; } - results = AccessController.doPrivileged( - new PrivilegedExceptionAction>() { - public ArrayList run() throws IOException { + Process proc; + BufferedReader bufferedReader = null; + File f = Files.createTempFile("prn", "xc") + .toFile(); + cmd[2] = cmd[2] + ">" + f.getAbsolutePath(); - Process proc; - BufferedReader bufferedReader = null; - File f = Files.createTempFile("prn","xc").toFile(); - cmd[2] = cmd[2]+">"+f.getAbsolutePath(); - - proc = Runtime.getRuntime().exec(cmd); - try { - boolean done = false; // in case of interrupt. - while (!done) { - try { - proc.waitFor(); - done = true; - } catch (InterruptedException e) { - } - } + proc = Runtime.getRuntime().exec(cmd); + try { + boolean done = false; // in case of interrupt. + while (!done) { + try { + proc.waitFor(); + done = true; + } catch (InterruptedException ignored) { + } + } - if (proc.exitValue() == 0) { - FileReader reader = new FileReader(f); - bufferedReader = new BufferedReader(reader); - String line; - ArrayList results = new ArrayList<>(); - while ((line = bufferedReader.readLine()) - != null) { - results.add(line); - } - return results; - } - } finally { - f.delete(); - // promptly close all streams. - if (bufferedReader != null) { - bufferedReader.close(); - } - proc.getInputStream().close(); - proc.getErrorStream().close(); - proc.getOutputStream().close(); - } - return null; + if (proc.exitValue() == 0) { + FileReader reader = new FileReader(f); + bufferedReader = new BufferedReader(reader); + String line; + while ((line = bufferedReader.readLine()) + != null) { + results.add(line); } - }); - } catch (PrivilegedActionException e) { + } + } finally { + f.delete(); + // promptly close all streams. + if (bufferedReader != null) { + bufferedReader.close(); + } + proc.getInputStream() + .close(); + proc.getErrorStream() + .close(); + proc.getOutputStream() + .close(); + } + } catch (IOException ignored) { } if (results == null) { return new String[0]; diff --git a/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java b/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java index 913c69e40ee..1249d29ec72 100644 --- a/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java +++ b/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java @@ -86,7 +86,6 @@ import java.awt.print.PrinterException; - public class UnixPrintJob implements CancelablePrintJob { private static String debugPrefix = "UnixPrintJob>> "; @@ -525,8 +524,7 @@ public void print(Doc doc, PrintRequestAttributeSet attributes) // now spool the print data. PrinterOpener po = new PrinterOpener(); - @SuppressWarnings("removal") - var dummy = java.security.AccessController.doPrivileged(po); + po.run(); if (po.pex != null) { throw po.pex; } @@ -599,8 +597,7 @@ public void print(Doc doc, PrintRequestAttributeSet attributes) if (mDestType == UnixPrintJob.DESTPRINTER) { PrinterSpooler spooler = new PrinterSpooler(); - @SuppressWarnings("removal") - var dummy2 = java.security.AccessController.doPrivileged(spooler); + spooler.run(); if (spooler.pex != null) { throw spooler.pex; } @@ -911,9 +908,7 @@ private String[] printExecCmd(String printer, String options, private String mDestination, mOptions=""; private boolean mNoJobSheet = false; - // Inner class to run "privileged" to open the printer output stream. - - private class PrinterOpener implements java.security.PrivilegedAction { + private class PrinterOpener { PrintException pex; OutputStream result; @@ -941,9 +936,7 @@ public OutputStream run() { } } - // Inner class to run "privileged" to invoke the system print command - - private class PrinterSpooler implements java.security.PrivilegedAction { + private class PrinterSpooler { PrintException pex; private void handleProcessFailure(final Process failedProcess, diff --git a/src/java.desktop/unix/classes/sun/print/UnixPrintService.java b/src/java.desktop/unix/classes/sun/print/UnixPrintService.java index bbd8c6c9c78..201487e9ca4 100644 --- a/src/java.desktop/unix/classes/sun/print/UnixPrintService.java +++ b/src/java.desktop/unix/classes/sun/print/UnixPrintService.java @@ -145,9 +145,7 @@ public class UnixPrintService implements PrintService, AttributeUpdater, "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk '{print $4}'" }; - @SuppressWarnings("removal") - private static String encoding = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("file.encoding")); + private static String encoding = System.getProperty("file.encoding"); /* let's try to support a few of these */ private static final Class[] serviceAttrCats = { diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index 33d2aeb66bb..51c425c8c59 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -1287,7 +1287,7 @@ Java_sun_awt_X11GraphicsDevice_pGetBounds(JNIEnv *env, jobject this, jint screen xwa.width, xwa.height); } - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { return NULL; } } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c index f9fe7b2b126..94468d548ef 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c @@ -1328,7 +1328,7 @@ static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) x11InputMethodGRefListHead->inputMethodGRef) == NULL) { /* Clear possible exceptions */ - if ((*env)->ExceptionOccurred(env)) { + if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c index d61c59b5915..67b1ad2bc45 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c @@ -96,7 +96,7 @@ awtJNI_ThreadYield(JNIEnv *env) { } /* threadClass == NULL*/ (*env)->CallStaticVoidMethod(env, threadClass, yieldMethodID); - DASSERT(!((*env)->ExceptionOccurred(env))); + DASSERT(!((*env)->ExceptionCheck(env))); if ((*env)->ExceptionCheck(env)) { return JNI_FALSE; } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c b/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c index d778c0bf6d6..db6acc0f3d1 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c @@ -85,7 +85,7 @@ static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gp static void quit(JNIEnv * env, jobject jpeer, gboolean isSignalHandler) { jthrowable pendingException; - if (pendingException = (*env)->ExceptionOccurred(env)) { + if ((pendingException = (*env)->ExceptionOccurred(env)) != NULL) { (*env)->ExceptionClear(env); } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java index b50a5ad583e..a8fdbaf7a50 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java @@ -25,9 +25,6 @@ package com.sun.java.swing.plaf.windows; -import java.security.AccessController; -import sun.security.action.GetBooleanAction; - import java.util.*; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; @@ -67,9 +64,8 @@ */ class AnimationController implements ActionListener, PropertyChangeListener { - @SuppressWarnings("removal") private static final boolean VISTA_ANIMATION_DISABLED = - AccessController.doPrivileged(new GetBooleanAction("swing.disablevistaanimation")); + Boolean.getBoolean("swing.disablevistaanimation"); private static final Object ANIMATION_CONTROLLER_KEY = diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java index aa97b0d0741..72ad51535ff 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java @@ -58,7 +58,6 @@ import java.awt.image.ImageFilter; import java.awt.image.ImageProducer; import java.awt.image.RGBImageFilter; -import java.security.AccessController; import javax.swing.AbstractAction; import javax.swing.Action; @@ -90,7 +89,6 @@ import sun.awt.SunToolkit; import sun.awt.shell.ShellFolder; import sun.font.FontUtilities; -import sun.security.action.GetPropertyAction; import sun.swing.DefaultLayoutStyle; import sun.swing.ImageIconUIResource; import sun.swing.MnemonicHandler; @@ -184,9 +182,7 @@ public void initialize() { // performance and compatibility issues, so allow this feature // to be switched off either at runtime or programmatically // - @SuppressWarnings("removal") - String systemFonts = java.security.AccessController.doPrivileged( - new GetPropertyAction("swing.useSystemFontSettings")); + String systemFonts = System.getProperty("swing.useSystemFontSettings"); useSystemFontSettings = systemFonts == null || Boolean.parseBoolean(systemFonts); if (useSystemFontSettings) { @@ -596,8 +592,7 @@ protected void initComponentDefaults(UIDefaults table) if (!(this instanceof WindowsClassicLookAndFeel) && (OSInfo.getOSType() == OSInfo.OSType.WINDOWS && OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) >= 0)) { - @SuppressWarnings("removal") - String prop = AccessController.doPrivileged(new GetPropertyAction("swing.noxp")); + String prop = System.getProperty("swing.noxp"); if (prop == null) { // These desktop properties are not used directly, but are needed to diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java index 5723d4274af..bba5f8dc31e 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java @@ -55,7 +55,6 @@ import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.awt.image.WritableRaster; -import java.security.AccessController; import java.util.HashMap; import javax.swing.AbstractButton; @@ -79,7 +78,6 @@ import sun.awt.image.SunWritableRaster; import sun.awt.windows.ThemeReader; -import sun.security.action.GetPropertyAction; import sun.swing.CachedPainter; import static com.sun.java.swing.plaf.windows.TMSchema.Part; @@ -124,7 +122,6 @@ static synchronized void invalidateStyle() { * @return the singleton instance of this class or null if XP styles * are not active or if this is not Windows XP */ - @SuppressWarnings("removal") static synchronized XPStyle getXP() { if (themeActive == null) { Toolkit toolkit = Toolkit.getDefaultToolkit(); @@ -134,9 +131,8 @@ static synchronized XPStyle getXP() { themeActive = Boolean.FALSE; } if (themeActive.booleanValue()) { - GetPropertyAction propertyAction = - new GetPropertyAction("swing.noxp"); - if (AccessController.doPrivileged(propertyAction) == null && + String propertyAction = System.getProperty("swing.noxp"); + if (propertyAction == null && ThemeReader.isThemed() && !(UIManager.getLookAndFeel() instanceof WindowsClassicLookAndFeel)) { diff --git a/src/java.desktop/windows/classes/sun/awt/PlatformGraphicsInfo.java b/src/java.desktop/windows/classes/sun/awt/PlatformGraphicsInfo.java index 6d14a72400c..642f98b0df2 100644 --- a/src/java.desktop/windows/classes/sun/awt/PlatformGraphicsInfo.java +++ b/src/java.desktop/windows/classes/sun/awt/PlatformGraphicsInfo.java @@ -39,15 +39,9 @@ public class PlatformGraphicsInfo { hasDisplays = hasDisplays0(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void loadAWTLibrary() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); } private static native boolean hasDisplays0(); diff --git a/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java b/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java index 1d5f76f9960..52042a600f9 100644 --- a/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java +++ b/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java @@ -29,13 +29,12 @@ import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.io.File; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import java.util.NoSuchElementException; import java.util.StringTokenizer; +import java.util.function.Supplier; import sun.awt.windows.WFontConfiguration; import sun.font.FontManager; @@ -47,24 +46,21 @@ */ public final class Win32FontManager extends SunFontManager { - @SuppressWarnings("removal") private static final TrueTypeFont eudcFont = - AccessController.doPrivileged(new PrivilegedAction() { - public TrueTypeFont run() { - String eudcFile = getEUDCFontFile(); - if (eudcFile != null) { - try { - /* Must use Java rasteriser since GDI doesn't - * enumerate (allow direct use) of EUDC fonts. - */ - return new TrueTypeFont(eudcFile, null, 0, - true, false); - } catch (FontFormatException e) { - } + ((Supplier) () -> { + String eudcFile = getEUDCFontFile(); + if (eudcFile != null) { + try { + /* Must use Java rasteriser since GDI doesn't + * enumerate (allow direct use) of EUDC fonts. + */ + return new TrueTypeFont(eudcFile, null, 0, + true, false); + } catch (FontFormatException e) { } - return null; } - }); + return null; + }).get(); /* Used on Windows to obtain from the windows registry the name * of a file containing the system EUFC font. If running in one of @@ -78,20 +74,14 @@ public TrueTypeFont getEUDCFont() { return eudcFont; } - @SuppressWarnings("removal") public Win32FontManager() { super(); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - - /* Register the JRE fonts so that the native platform can - * access them. This is used only on Windows so that when - * printing the printer driver can access the fonts. - */ - registerJREFontsWithPlatform(jreFontDirName); - return null; - } - }); + + /* Register the JRE fonts so that the native platform can + * access them. This is used only on Windows so that when + * printing the printer driver can access the fonts. + */ + registerJREFontsWithPlatform(jreFontDirName); } /** @@ -213,21 +203,15 @@ protected String[] getDefaultPlatformFont() { info[1] = "c:\\windows\\fonts"; final String[] dirs = getPlatformFontDirs(true); if (dirs.length > 1) { - @SuppressWarnings("removal") - String dir = (String) - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - for (int i=0; i() { - public Object run() { - File f1 = new File(pathName); - String[] ls = f1.list(SunFontManager.getInstance(). - getTrueTypeFilter()); - if (ls == null) { - return null; - } - for (int i=0; i () { - public String run() { - return dir.getAbsolutePath(); - } - }); + String path = dir.getAbsolutePath(); return (path.startsWith("\\\\") && path.indexOf("\\", 2) < 0); //Network path } @@ -572,25 +565,17 @@ protected Invoker createInvoker() { private static class ComInvoker extends ThreadPoolExecutor implements ThreadFactory, ShellFolder.Invoker { private static Thread comThread; - @SuppressWarnings("removal") private ComInvoker() { super(1, 1, 0, TimeUnit.DAYS, new LinkedBlockingQueue<>()); allowCoreThreadTimeOut(false); setThreadFactory(this); - final Runnable shutdownHook = () -> AccessController.doPrivileged((PrivilegedAction) () -> { - shutdownNow(); - return null; - }); - AccessController.doPrivileged((PrivilegedAction) () -> { - Thread t = new Thread( - ThreadGroupUtils.getRootThreadGroup(), shutdownHook, - "ShellFolder", 0, false); - Runtime.getRuntime().addShutdownHook(t); - return null; - }); + final Runnable shutdownHook = () -> shutdownNow(); + Thread t = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownHook, + "ShellFolder", 0, false); + Runtime.getRuntime().addShutdownHook(t); } - @SuppressWarnings("removal") public synchronized Thread newThread(final Runnable task) { final Runnable comRun = new Runnable() { public void run() { @@ -602,27 +587,22 @@ public void run() { } } }; - comThread = AccessController.doPrivileged((PrivilegedAction) () -> { - String name = "Swing-Shell"; - /* The thread must be a member of a thread group - * which will not get GCed before VM exit. - * Make its parent the top-level thread group. - */ - Thread thread = new Thread( - ThreadGroupUtils.getRootThreadGroup(), comRun, name, - 0, false); - thread.setDaemon(true); - /* This is important, since this thread running at lower priority - leads to memory consumption when listDrives() function is called - repeatedly. - */ - thread.setPriority(Thread.MAX_PRIORITY); - return thread; - }); + /* The thread must be a member of a thread group + * which will not get GCed before VM exit. + * Make its parent the top-level thread group. + */ + comThread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), comRun, "Swing-Shell", + 0, false); + comThread.setDaemon(true); + /* This is important, since this thread running at lower priority + leads to memory consumption when listDrives() function is called + repeatedly. + */ + comThread.setPriority(Thread.MAX_PRIORITY); return comThread; } - @SuppressWarnings("removal") public T invoke(Callable task) throws Exception { if (Thread.currentThread() == comThread) { // if it's already called from the COM @@ -640,13 +620,8 @@ public T invoke(Callable task) throws Exception { try { return future.get(); } catch (InterruptedException e) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - future.cancel(true); + future.cancel(true); - return null; - } - }); throw e; } catch (ExecutionException e) { diff --git a/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java b/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java index 56cea268d28..b31685294ba 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java @@ -35,7 +35,6 @@ import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.awt.image.VolatileImage; -import java.security.AccessController; import sun.awt.image.BufImgSurfaceData; import sun.java2d.DestSurfaceProvider; import sun.java2d.InvalidPipeException; @@ -45,7 +44,6 @@ import sun.java2d.pipe.BufferedContext; import sun.java2d.pipe.hw.AccelGraphicsConfig; import sun.java2d.pipe.hw.AccelSurface; -import sun.security.action.GetPropertyAction; import static java.awt.image.VolatileImage.*; import static sun.java2d.pipe.hw.AccelSurface.*; @@ -66,14 +64,10 @@ abstract class TranslucentWindowPainter { protected WWindowPeer peer; // REMIND: we probably would want to remove this later - @SuppressWarnings("removal") - private static final boolean forceOpt = - Boolean.parseBoolean(AccessController.doPrivileged( - new GetPropertyAction("sun.java2d.twp.forceopt", "false"))); - @SuppressWarnings("removal") - private static final boolean forceSW = - Boolean.parseBoolean(AccessController.doPrivileged( - new GetPropertyAction("sun.java2d.twp.forcesw", "false"))); + private static final boolean forceOpt = + Boolean.getBoolean("sun.java2d.twp.forceopt"); + private static final boolean forceSW = + Boolean.getBoolean("sun.java2d.twp.forcesw"); /** * Creates an instance of the painter for particular peer. diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java b/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java index 0ffc973408a..a6294e05ba9 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java @@ -32,11 +32,8 @@ import java.awt.image.*; import sun.awt.image.ByteInterleavedRaster; -import sun.security.action.GetPropertyAction; import java.awt.peer.FramePeer; -import java.security.PrivilegedAction; -import java.security.AccessController; @SuppressWarnings("serial") // JDK-implementation class public class WEmbeddedFrame extends EmbeddedFrame { @@ -60,9 +57,7 @@ public class WEmbeddedFrame extends EmbeddedFrame { */ private boolean isEmbeddedInIE = false; - @SuppressWarnings("removal") - private static String printScale = AccessController.doPrivileged( - new GetPropertyAction("sun.java2d.print.pluginscalefactor")); + private static String printScale = System.getProperty("sun.java2d.print.pluginscalefactor"); public WEmbeddedFrame() { this((long)0); @@ -181,7 +176,6 @@ void print(long hdc) { } } - @SuppressWarnings("removal") protected static int getPrintScaleFactor() { // check if value is already cached if (pScale != 0) @@ -189,13 +183,7 @@ protected static int getPrintScaleFactor() { if (printScale == null) { // if no system property is specified, // check for environment setting - printScale = AccessController.doPrivileged( - new PrivilegedAction() { - public String run() { - return System.getenv("JAVA2D_PLUGIN_PRINT_SCALE"); - } - } - ); + printScale = System.getenv("JAVA2D_PLUGIN_PRINT_SCALE"); } int default_printDC_scale = 4; int scale = default_printDC_scale; diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java index 7502b667250..60f3726249e 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java @@ -30,8 +30,6 @@ import java.awt.peer.*; import java.io.File; import java.io.FilenameFilter; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ResourceBundle; import java.util.MissingResourceException; import java.util.Vector; @@ -197,19 +195,13 @@ public void run() { //This whole static block is a part of 4152317 fix static { - @SuppressWarnings("removal") - String filterString = AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - try { - ResourceBundle rb = ResourceBundle.getBundle("sun.awt.windows.awtLocalization"); - return rb.getString("allFiles"); - } catch (MissingResourceException e) { - return "All Files"; - } - } - }); + String filterString; + try { + ResourceBundle rb = ResourceBundle.getBundle("sun.awt.windows.awtLocalization"); + filterString = rb.getString("allFiles"); + } catch (MissingResourceException e) { + filterString = "All Files"; + } setFilterString(filterString); } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java index a5612b08dc4..9b74f7359fb 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java @@ -32,11 +32,9 @@ import java.awt.MenuBar; import java.awt.Rectangle; import java.awt.peer.FramePeer; -import java.security.AccessController; import sun.awt.AWTAccessor; import sun.awt.im.InputMethodManager; -import sun.security.action.GetPropertyAction; import static sun.java2d.SunGraphicsEnvironment.getGCDeviceBounds; import static sun.java2d.SunGraphicsEnvironment.toDeviceSpaceAbs; @@ -80,11 +78,8 @@ public void toFront() { private native void setMaximizedBounds(int x, int y, int w, int h); private native void clearMaximizedBounds(); - @SuppressWarnings("removal") private static final boolean keepOnMinimize = "true".equals( - AccessController.doPrivileged( - new GetPropertyAction( - "sun.awt.keepWorkingSetOnMinimize"))); + System.getProperty("sun.awt.keepWorkingSetOnMinimize")); @Override public final void setMaximizedBounds(Rectangle b) { diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java index 344a8e7dbc8..3a736e5c519 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java @@ -29,11 +29,8 @@ import java.awt.*; import java.awt.peer.*; import java.awt.event.ActionEvent; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.util.logging.PlatformLogger; -@SuppressWarnings("removal") class WMenuItemPeer extends WObjectPeer implements MenuItemPeer { private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.WMenuItemPeer"); @@ -146,20 +143,15 @@ public void run() { private static Font defaultMenuFont; static { - defaultMenuFont = AccessController.doPrivileged( - new PrivilegedAction () { - public Font run() { - try { - ResourceBundle rb = ResourceBundle.getBundle("sun.awt.windows.awtLocalization"); - return Font.decode(rb.getString("menuFont")); - } catch (MissingResourceException e) { - if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("WMenuItemPeer: " + e.getMessage()+". Using default MenuItem font.", e); - } - return new Font("SanSerif", Font.PLAIN, 11); - } - } - }); + try { + ResourceBundle rb = ResourceBundle.getBundle("sun.awt.windows.awtLocalization"); + defaultMenuFont = Font.decode(rb.getString("menuFont")); + } catch (MissingResourceException e) { + if (log.isLoggable(PlatformLogger.Level.FINE)) { + log.fine("WMenuItemPeer: " + e.getMessage()+". Using default MenuItem font.", e); + } + defaultMenuFont = new Font("SanSerif", Font.PLAIN, 11); + } } static Font getDefaultFont() { diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java b/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java index 84ae7e8f418..aef078b950f 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java @@ -95,11 +95,8 @@ final class WPathGraphics extends PathGraphics { private static boolean useGDITextLayout = true; private static boolean preferGDITextLayout = false; static { - @SuppressWarnings("removal") - String textLayoutStr = - java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "sun.java2d.print.enableGDITextLayout")); + String textLayoutStr = System.getProperty( + "sun.java2d.print.enableGDITextLayout"); if (textLayoutStr != null) { useGDITextLayout = Boolean.getBoolean(textLayoutStr); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java index ad643ccbd3d..f2fbfa9b77d 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java @@ -112,8 +112,6 @@ import java.awt.peer.WindowPeer; import java.beans.PropertyChangeListener; import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Hashtable; import java.util.Locale; import java.util.Map; @@ -168,17 +166,11 @@ public final class WToolkit extends SunToolkit implements Runnable { */ private static native void initIDs(); private static boolean loaded = false; - @SuppressWarnings({"removal", "restricted"}) + + @SuppressWarnings("restricted") public static void loadLibraries() { if (!loaded) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - @Override - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); loaded = true; } } @@ -208,7 +200,6 @@ public void dispose() { private static native boolean startToolkitThread(Runnable thread, ThreadGroup rootThreadGroup); - @SuppressWarnings("removal") public WToolkit() { // Startup toolkit threads if (PerformanceLogger.loggingEnabled()) { @@ -225,16 +216,12 @@ public WToolkit() { AWTAutoShutdown.notifyToolkitThreadBusy(); // Find a root TG and attach toolkit thread to it - ThreadGroup rootTG = AccessController.doPrivileged( - (PrivilegedAction) ThreadGroupUtils::getRootThreadGroup); + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); if (!startToolkitThread(this, rootTG)) { final String name = "AWT-Windows"; - AccessController.doPrivileged((PrivilegedAction) () -> { - Thread toolkitThread = new Thread(rootTG, this, name, 0, false); - toolkitThread.setDaemon(true); - toolkitThread.start(); - return null; - }); + Thread toolkitThread = new Thread(rootTG, this, name, 0, false); + toolkitThread.setDaemon(true); + toolkitThread.start(); } try { @@ -251,36 +238,25 @@ public WToolkit() { // by the native system though. setDynamicLayout(true); final String extraButtons = "sun.awt.enableExtraMouseButtons"; - AccessController.doPrivileged((PrivilegedAction) () -> { - areExtraMouseButtonsEnabled = - Boolean.parseBoolean(System.getProperty(extraButtons, "true")); - //set system property if not yet assigned - System.setProperty(extraButtons, ""+areExtraMouseButtonsEnabled); - return null; - }); + areExtraMouseButtonsEnabled = + Boolean.parseBoolean(System.getProperty(extraButtons, "true")); + //set system property if not yet assigned + System.setProperty(extraButtons, ""+areExtraMouseButtonsEnabled); setExtraMouseButtonsEnabledNative(areExtraMouseButtonsEnabled); } - @SuppressWarnings("removal") private void registerShutdownHook() { - AccessController.doPrivileged((PrivilegedAction) () -> { - Thread shutdown = new Thread( - ThreadGroupUtils.getRootThreadGroup(), this::shutdown, - "ToolkitShutdown", 0, false); - shutdown.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(shutdown); - return null; - }); - } + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this::shutdown, + "ToolkitShutdown", 0, false); + shutdown.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(shutdown); + } - @SuppressWarnings("removal") @Override public void run() { - AccessController.doPrivileged((PrivilegedAction) () -> { - Thread.currentThread().setContextClassLoader(null); - Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1); - return null; - }); + Thread.currentThread().setContextClassLoader(null); + Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1); boolean startPump = init(); diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java index 7ad09a5e750..fd9112e08f1 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java @@ -32,8 +32,6 @@ import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Window; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; @@ -91,25 +89,21 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager */ private HashMap gdiSurfaces; - @SuppressWarnings("removal") public D3DScreenUpdateManager() { done = false; - AccessController.doPrivileged((PrivilegedAction) () -> { - Runnable shutdownRunnable = () -> { - done = true; - wakeUpUpdateThread(); - }; - Thread shutdown = new Thread( - ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable, - "ScreenUpdater", 0, false); - shutdown.setContextClassLoader(null); - try { - Runtime.getRuntime().addShutdownHook(shutdown); - } catch (Exception e) { - done = true; - } - return null; - }); + Runnable shutdownRunnable = () -> { + done = true; + wakeUpUpdateThread(); + }; + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable, + "ScreenUpdater", 0, false); + shutdown.setContextClassLoader(null); + try { + Runtime.getRuntime().addShutdownHook(shutdown); + } catch (Exception e) { + done = true; + } } /** @@ -345,19 +339,15 @@ private void removeGdiSurface(final D3DWindowSurfaceData d3dw) { * If the update thread hasn't yet been created, it will be; * otherwise it is awaken */ - @SuppressWarnings("removal") private synchronized void startUpdateThread() { if (screenUpdater == null) { - screenUpdater = AccessController.doPrivileged((PrivilegedAction) () -> { - String name = "D3D Screen Updater"; - Thread t = new Thread( + String name = "D3D Screen Updater"; + screenUpdater = new Thread( ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); - // REMIND: should it be higher? - t.setPriority(Thread.NORM_PRIORITY + 2); - t.setDaemon(true); - return t; - }); + // REMIND: should it be higher? + screenUpdater.setPriority(Thread.NORM_PRIORITY + 2); + screenUpdater.setDaemon(true); screenUpdater.start(); } else { wakeUpUpdateThread(); diff --git a/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java b/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java index 3c18de432bb..da13c6b49fc 100644 --- a/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java +++ b/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java @@ -176,65 +176,57 @@ private static boolean getPropertySet(String p) { return (propString != null) ? true : false; } - @SuppressWarnings("removal") private static void initJavaFlags() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() - { - public Object run() { - magPresent = getBooleanProp( - "javax.accessibility.screen_magnifier_present", false); - boolean ddEnabled = - !getBooleanProp("sun.java2d.noddraw", magPresent); - boolean ddOffscreenEnabled = - getBooleanProp("sun.java2d.ddoffscreen", ddEnabled); - d3dEnabled = getBooleanProp("sun.java2d.d3d", - ddEnabled && ddOffscreenEnabled); - d3dOnScreenEnabled = - getBooleanProp("sun.java2d.d3d.onscreen", d3dEnabled); - oglEnabled = getBooleanProp("sun.java2d.opengl", false); - if (oglEnabled) { - oglVerbose = isBooleanPropTrueVerbose("sun.java2d.opengl"); - if (WGLGraphicsConfig.isWGLAvailable()) { - d3dEnabled = false; - } else { - if (oglVerbose) { - System.out.println( - "Could not enable OpenGL pipeline " + - "(WGL not available)"); - } - oglEnabled = false; - } - } - gdiBlitEnabled = getBooleanProp("sun.java2d.gdiBlit", true); - d3dSet = getPropertySet("sun.java2d.d3d"); - if (d3dSet) { - d3dVerbose = isBooleanPropTrueVerbose("sun.java2d.d3d"); - } - offscreenSharingEnabled = - getBooleanProp("sun.java2d.offscreenSharing", false); - String dpiOverride = System.getProperty("sun.java2d.dpiaware"); - if (dpiOverride != null) { - setHighDPIAware = dpiOverride.equalsIgnoreCase("true"); - } else { - String sunLauncherProperty = - System.getProperty("sun.java.launcher", "unknown"); - setHighDPIAware = - sunLauncherProperty.equalsIgnoreCase("SUN_STANDARD"); - } - /* - // Output info based on some non-default flags: - if (offscreenSharingEnabled) { + magPresent = getBooleanProp( + "javax.accessibility.screen_magnifier_present", false); + boolean ddEnabled = + !getBooleanProp("sun.java2d.noddraw", magPresent); + boolean ddOffscreenEnabled = + getBooleanProp("sun.java2d.ddoffscreen", ddEnabled); + d3dEnabled = getBooleanProp("sun.java2d.d3d", + ddEnabled && ddOffscreenEnabled); + d3dOnScreenEnabled = + getBooleanProp("sun.java2d.d3d.onscreen", d3dEnabled); + oglEnabled = getBooleanProp("sun.java2d.opengl", false); + if (oglEnabled) { + oglVerbose = isBooleanPropTrueVerbose("sun.java2d.opengl"); + if (WGLGraphicsConfig.isWGLAvailable()) { + d3dEnabled = false; + } else { + if (oglVerbose) { System.out.println( - "Warning: offscreenSharing has been enabled. " + - "The use of this capability will change in future " + - "releases and applications that depend on it " + - "may not work correctly"); + "Could not enable OpenGL pipeline " + + "(WGL not available)"); } - */ - return null; + oglEnabled = false; } - }); + } + gdiBlitEnabled = getBooleanProp("sun.java2d.gdiBlit", true); + d3dSet = getPropertySet("sun.java2d.d3d"); + if (d3dSet) { + d3dVerbose = isBooleanPropTrueVerbose("sun.java2d.d3d"); + } + offscreenSharingEnabled = + getBooleanProp("sun.java2d.offscreenSharing", false); + String dpiOverride = System.getProperty("sun.java2d.dpiaware"); + if (dpiOverride != null) { + setHighDPIAware = dpiOverride.equalsIgnoreCase("true"); + } else { + String sunLauncherProperty = + System.getProperty("sun.java.launcher", "unknown"); + setHighDPIAware = + sunLauncherProperty.equalsIgnoreCase("SUN_STANDARD"); + } + /* + // Output info based on some non-default flags: + if (offscreenSharingEnabled) { + System.out.println( + "Warning: offscreenSharing has been enabled. " + + "The use of this capability will change in future " + + "releases and applications that depend on it " + + "may not work correctly"); + } + */ /* System.out.println("WindowsFlags (Java):"); System.out.println(" ddEnabled: " + ddEnabled + "\n" + diff --git a/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java b/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java index 9079e7c2bfe..44173fb2abf 100644 --- a/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java +++ b/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java @@ -25,8 +25,6 @@ package sun.print; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import javax.print.DocFlavor; @@ -54,15 +52,9 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { loadAWTLibrary(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void loadAWTLibrary() { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("awt"); - return null; - } - }); + System.loadLibrary("awt"); } /* The singleton win32 print lookup service. @@ -85,31 +77,26 @@ public static PrintServiceLookupProvider getWin32PrintLUS() { return win32PrintLUS; } - @SuppressWarnings("removal") public PrintServiceLookupProvider() { if (win32PrintLUS == null) { win32PrintLUS = this; // start the local printer listener thread - AccessController.doPrivileged((PrivilegedAction) () -> { - Thread thr = new Thread(ThreadGroupUtils.getRootThreadGroup(), - new PrinterChangeListener(), - "PrinterListener", 0, false); - thr.setContextClassLoader(null); - thr.setDaemon(true); - return thr; - }).start(); + Thread thr = new Thread(ThreadGroupUtils.getRootThreadGroup(), + new PrinterChangeListener(), + "PrinterListener", 0, false); + thr.setContextClassLoader(null); + thr.setDaemon(true); + thr.start(); // start the remote printer listener thread - AccessController.doPrivileged((PrivilegedAction) () -> { - Thread thr = new Thread(ThreadGroupUtils.getRootThreadGroup(), - new RemotePrinterChangeListener(), - "RemotePrinterListener", 0, false); - thr.setContextClassLoader(null); - thr.setDaemon(true); - return thr; - }).start(); + Thread thr1 = new Thread(ThreadGroupUtils.getRootThreadGroup(), + new RemotePrinterChangeListener(), + "RemotePrinterListener", 0, false); + thr1.setContextClassLoader(null); + thr1.setDaemon(true); + thr1.start(); } /* else condition ought to never happen! */ } diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DSurfaceData.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DSurfaceData.cpp index 9732d4d046b..1e3baa1c686 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DSurfaceData.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DSurfaceData.cpp @@ -62,7 +62,7 @@ void D3DSD_SetNativeDimensions(JNIEnv *env, D3DSDOps *d3dsdo) { } JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); - if (!(env->ExceptionOccurred())) { + if (!(env->ExceptionCheck())) { JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); } diff --git a/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp b/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp index 2489ac21952..406a82a022f 100644 --- a/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp @@ -372,7 +372,7 @@ Java_sun_java2d_windows_GDIWindowSurfaceData_initOps(JNIEnv *env, jobject wsd, wsdo->invalid = JNI_FALSE; wsdo->lockType = WIN32SD_LOCK_UNLOCKED; wsdo->peer = env->NewWeakGlobalRef(peer); - if (env->ExceptionOccurred()) { + if (env->ExceptionCheck()) { return; } wsdo->depth = depth; diff --git a/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java b/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java index ee2037fac5b..7091847a599 100644 --- a/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java +++ b/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java @@ -25,8 +25,6 @@ package java.lang.instrument; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.security.ProtectionDomain; /* diff --git a/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java b/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java index 3aeddd1c90d..bd54b89aee6 100644 --- a/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java +++ b/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -36,7 +36,6 @@ import java.nio.file.Path; import java.nio.file.InvalidPathException; import java.net.URL; -import java.security.AccessController; import java.security.CodeSource; import java.security.PrivilegedAction; import java.security.ProtectionDomain; @@ -68,9 +67,7 @@ public class InstrumentationImpl implements Instrumentation { private static final String TRACE_USAGE_PROP_NAME = "jdk.instrument.traceUsage"; private static final boolean TRACE_USAGE; static { - PrivilegedAction pa = () -> System.getProperty(TRACE_USAGE_PROP_NAME); - @SuppressWarnings("removal") - String s = AccessController.doPrivileged(pa); + String s = System.getProperty(TRACE_USAGE_PROP_NAME); TRACE_USAGE = (s != null) && (s.isEmpty() || Boolean.parseBoolean(s)); } @@ -100,9 +97,7 @@ public class InstrumentationImpl implements Instrumentation { String source = jarFile(nativeAgent); try { Path path = Path.of(source); - PrivilegedAction pa = path::toAbsolutePath; - @SuppressWarnings("removal") - Path absolutePath = AccessController.doPrivileged(pa); + Path absolutePath = path.toAbsolutePath(); source = absolutePath.toString(); } catch (InvalidPathException e) { // use original path @@ -482,18 +477,6 @@ private TransformerManager findTransformerManager(ClassFileTransformer transform * Internals */ - - // Enable or disable Java programming language access checks on a - // reflected object (for example, a method) - @SuppressWarnings("removal") - private static void setAccessible(final AccessibleObject ao, final boolean accessible) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - ao.setAccessible(accessible); - return null; - }}); - } - // Attempt to load and start an agent private void loadClassAndStartAgent( String classname, @@ -553,7 +536,7 @@ public Object run() { !javaAgentClass.getModule().isNamed()) { // If the java agent class is in an unnamed module, the java agent class can be non-public. // Suppress access check upon the invocation of the premain/agentmain method. - setAccessible(m, true); + m.setAccessible(true); } // invoke the 1 or 2-arg method @@ -665,9 +648,7 @@ private void trace(String methodName) { * Returns the possibly-bnull code source of the given class. */ private static URL codeSource(Class clazz) { - PrivilegedAction pa = clazz::getProtectionDomain; - @SuppressWarnings("removal") - CodeSource cs = AccessController.doPrivileged(pa).getCodeSource(); + CodeSource cs = clazz.getProtectionDomain().getCodeSource(); return (cs != null) ? cs.getLocation() : null; } @@ -675,13 +656,6 @@ private static URL codeSource(Class clazz) { * Holder for StackWalker object. */ private static class HolderStackWalker { - static final StackWalker walker; - static { - PrivilegedAction pa = () -> - StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); - @SuppressWarnings("removal") - StackWalker w = AccessController.doPrivileged(pa); - walker = w; - } + static final StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); } } diff --git a/src/java.net.http/share/classes/java/net/http/HttpClient.java b/src/java.net.http/share/classes/java/net/http/HttpClient.java index c1269eed823..fbd2e2aba36 100644 --- a/src/java.net.http/share/classes/java/net/http/HttpClient.java +++ b/src/java.net.http/share/classes/java/net/http/HttpClient.java @@ -37,9 +37,6 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.net.ProxySelector; -import java.net.URLPermission; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.time.Duration; import java.util.Objects; import java.util.Optional; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java index 1ff1e5f4733..71e4e05d2c5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java @@ -26,25 +26,15 @@ package jdk.internal.net.http; import java.io.IOException; -import java.net.InetSocketAddress; import java.net.ProtocolException; -import java.net.ProxySelector; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLPermission; -import java.security.AccessControlContext; import java.time.Duration; -import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.net.http.HttpClient; -import java.net.http.HttpHeaders; import java.net.http.HttpResponse; import java.net.http.HttpTimeoutException; @@ -53,20 +43,11 @@ import jdk.internal.net.http.common.Utils; import jdk.internal.net.http.common.Log; -import static jdk.internal.net.http.common.Utils.permissionForProxy; - /** * One request/response exchange (handles 100/101 intermediate response also). * depth field used to track number of times a new request is being sent * for a given API request. If limit exceeded exception is thrown. * - * Security check is performed here: - * - uses AccessControlContext captured at API level - * - checks for appropriate URLPermission for request - * - if permission allowed, grants equivalent SocketPermission to call - * - in case of direct HTTP proxy, checks additionally for access to proxy - * (CONNECT proxying uses its own Exchange, so check done there) - * */ final class Exchange { @@ -83,8 +64,6 @@ final class Exchange { // used to record possible cancellation raised before the exchImpl // has been established. private volatile IOException failed; - @SuppressWarnings("removal") - final AccessControlContext acc; final MultiExchange multi; final Executor parentExecutor; volatile boolean upgrading; // to HTTP/2 @@ -103,22 +82,6 @@ final class Exchange { this.upgrading = false; this.client = multi.client(); this.multi = multi; - this.acc = multi.acc; - this.parentExecutor = multi.executor; - this.pushGroup = multi.pushGroup; - this.dbgTag = "Exchange"; - } - - /* If different AccessControlContext to be used */ - Exchange(HttpRequestImpl request, - MultiExchange multi, - @SuppressWarnings("removal") AccessControlContext acc) - { - this.request = request; - this.acc = acc; - this.upgrading = false; - this.client = multi.client(); - this.multi = multi; this.parentExecutor = multi.executor; this.pushGroup = multi.pushGroup; this.dbgTag = "Exchange"; @@ -338,7 +301,7 @@ private void checkCancelled() { } } - CompletableFuture checkCancelled(CompletableFuture cf, HttpConnection connection) { + CompletableFuture checkCancelled(CompletableFuture cf, HttpConnection connection) { return cf.handle((r,t) -> { if (t == null) { if (multi.requestCancelled()) { @@ -354,7 +317,7 @@ CompletableFuture checkCancelled(CompletableFuture cf, HttpConnection } catch (Throwable x) { if (debug.on()) debug.log("Failed to close connection", x); } - return MinimalFuture.failedFuture(t); + return MinimalFuture.failedFuture(t); } } } @@ -422,15 +385,6 @@ public CompletableFuture responseAsync() { return responseAsyncImpl(null); } - CompletableFuture responseAsyncImpl(HttpConnection connection) { - SecurityException e = checkPermissions(); - if (e != null) { - return MinimalFuture.failedFuture(e); - } else { - return responseAsyncImpl0(connection); - } - } - // check whether the headersSentCF was completed exceptionally with // ProxyAuthorizationRequired. If so the Response embedded in the // exception is returned. Otherwise we proceed. @@ -584,7 +538,7 @@ private CompletableFuture ignore1xxResponse(final Response rsp) { } } - CompletableFuture responseAsyncImpl0(HttpConnection connection) { + CompletableFuture responseAsyncImpl(HttpConnection connection) { Function, CompletableFuture> after407Check; bodyIgnored = null; if (request.expectContinue()) { @@ -735,109 +689,6 @@ HttpResponse.BodySubscriber ignoreBody(HttpResponse.ResponseInfo hdrs) { return MinimalFuture.completedFuture(resp); } - private URI getURIForSecurityCheck() { - URI u; - String method = request.method(); - InetSocketAddress authority = request.authority(); - URI uri = request.uri(); - - // CONNECT should be restricted at API level - if (method.equalsIgnoreCase("CONNECT")) { - try { - u = new URI("socket", - null, - authority.getHostString(), - authority.getPort(), - null, - null, - null); - } catch (URISyntaxException e) { - throw new InternalError(e); // shouldn't happen - } - } else { - u = uri; - } - return u; - } - - /** - * Returns the security permission required for the given details. - * If method is CONNECT, then uri must be of form "scheme://host:port" - */ - private static URLPermission permissionForServer(URI uri, - String method, - Map> headers) { - if (method.equals("CONNECT")) { - return new URLPermission(uri.toString(), "CONNECT"); - } else { - return Utils.permissionForServer(uri, method, headers.keySet().stream()); - } - } - - /** - * Performs the necessary security permission checks required to retrieve - * the response. Returns a security exception representing the denied - * permission, or null if all checks pass or there is no security manager. - */ - private SecurityException checkPermissions() { - String method = request.method(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm == null || method.equals("CONNECT")) { - // tunneling will have a null acc, which is fine. The proxy - // permission check will have already been preformed. - return null; - } - - HttpHeaders userHeaders = request.getUserHeaders(); - URI u = getURIForSecurityCheck(); - URLPermission p = permissionForServer(u, method, userHeaders.map()); - - try { - assert acc != null; - sm.checkPermission(p, acc); - } catch (SecurityException e) { - return e; - } - String hostHeader = userHeaders.firstValue("Host").orElse(null); - if (hostHeader != null && !hostHeader.equalsIgnoreCase(u.getHost())) { - // user has set a Host header different to request URI - // must check that for URLPermission also - URI u1 = replaceHostInURI(u, hostHeader); - URLPermission p1 = permissionForServer(u1, method, userHeaders.map()); - try { - assert acc != null; - sm.checkPermission(p1, acc); - } catch (SecurityException e) { - return e; - } - } - ProxySelector ps = client.proxySelector(); - if (ps != null) { - if (!method.equals("CONNECT")) { - // a non-tunneling HTTP proxy. Need to check access - URLPermission proxyPerm = permissionForProxy(request.proxy()); - if (proxyPerm != null) { - try { - sm.checkPermission(proxyPerm, acc); - } catch (SecurityException e) { - return e; - } - } - } - } - return null; - } - - private static URI replaceHostInURI(URI u, String hostPort) { - StringBuilder sb = new StringBuilder(); - sb.append(u.getScheme()) - .append("://") - .append(hostPort) - .append(u.getRawPath()); - return URI.create(sb.toString()); - } - HttpClient.Version version() { return multi.version(); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientBuilderImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientBuilderImpl.java index c4157b3c74c..65e9210f9cb 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientBuilderImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientBuilderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -46,7 +46,6 @@ public class HttpClientBuilderImpl implements HttpClient.Builder { Authenticator authenticator; HttpClient.Version version; Executor executor; - // Security parameters SSLContext sslContext; SSLParameters sslParams; int priority = -1; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java index e1f4ec16dcd..4d7518d4054 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -48,10 +48,7 @@ import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; -import java.security.AccessControlContext; -import java.security.AccessController; import java.security.NoSuchAlgorithmException; -import java.security.PrivilegedAction; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -97,7 +94,6 @@ import jdk.internal.net.http.common.OperationTrackers.Trackable; import jdk.internal.net.http.common.OperationTrackers.Tracker; import jdk.internal.net.http.websocket.BuilderImpl; -import jdk.internal.misc.InnocuousThread; /** * Client implementation. Contains all configuration information and also @@ -131,16 +127,10 @@ private static final class DefaultThreadFactory implements ThreadFactory { namePrefix = "HttpClient-" + clientID + "-Worker-"; } - @SuppressWarnings("removal") @Override public Thread newThread(Runnable r) { String name = namePrefix + nextId.getAndIncrement(); - Thread t; - if (System.getSecurityManager() == null) { - t = new Thread(null, r, name, 0, false); - } else { - t = InnocuousThread.newThread(name, r); - } + Thread t = new Thread(null, r, name, 0, false); t.setDaemon(true); return t; } @@ -188,15 +178,9 @@ public void ensureExecutedAsync(Runnable command) { } } - @SuppressWarnings("removal") private void shutdown() { if (delegate instanceof ExecutorService service) { - PrivilegedAction action = () -> { - service.shutdown(); - return null; - }; - AccessController.doPrivileged(action, null, - new RuntimePermission("modifyThread")); + service.shutdown(); } } } @@ -336,7 +320,6 @@ static void abortPendingRequests(HttpClientImpl client, Throwable reason) { private final ConnectionPool connections; private final DelegatingExecutor delegatingExecutor; private final boolean isDefaultExecutor; - // Security parameters private final SSLContext sslContext; private final SSLParameters sslParams; private final SelectorManager selmgr; @@ -445,16 +428,6 @@ private HttpClientImpl(HttpClientBuilderImpl builder, SingleFacadeFactory facadeFactory) { id = CLIENT_IDS.incrementAndGet(); dbgTag = "HttpClientImpl(" + id +")"; - @SuppressWarnings("removal") - var sm = System.getSecurityManager(); - if (sm != null && builder.localAddr != null) { - // when a specific local address is configured, it will eventually - // lead to the SocketChannel.bind(...) call with an InetSocketAddress - // whose InetAddress is the local address and the port is 0. That ultimately - // leads to a SecurityManager.checkListen permission check for that port. - // so we do that security manager check here with port 0. - sm.checkListen(0); - } localAddr = builder.localAddr; if (builder.sslContext == null) { try { @@ -484,7 +457,7 @@ private HttpClientImpl(HttpClientBuilderImpl builder, Redirect.NEVER : builder.followRedirects; this.userProxySelector = builder.proxy; this.proxySelector = Optional.ofNullable(userProxySelector) - .orElseGet(HttpClientImpl::getDefaultProxySelector); + .orElseGet(ProxySelector::getDefault); if (debug.on()) debug.log("proxySelector is %s (user-supplied=%s)", this.proxySelector, userProxySelector != null); @@ -642,12 +615,6 @@ private static SSLParameters getDefaultParams(SSLContext ctx) { return params; } - @SuppressWarnings("removal") - private static ProxySelector getDefaultProxySelector() { - PrivilegedAction action = ProxySelector::getDefault; - return AccessController.doPrivileged(action); - } - // Returns the facade that was returned to the application code. // May be null if that facade is no longer referenced. final HttpClientFacade facade() { @@ -992,7 +959,6 @@ private void debugCompleted(String tag, long startNanos, HttpRequest req) { return sendAsync(userRequest, responseHandler, pushPromiseHandler, delegatingExecutor.delegate); } - @SuppressWarnings("removal") private CompletableFuture> sendAsync(HttpRequest userRequest, BodyHandler responseHandler, @@ -1012,11 +978,7 @@ private void debugCompleted(String tag, long startNanos, HttpRequest req) { return MinimalFuture.failedFuture(selmgr.selectorClosedException()); } - AccessControlContext acc = null; - if (System.getSecurityManager() != null) - acc = AccessController.getContext(); - - // Clone the, possibly untrusted, HttpRequest + // Clone the possibly untrusted HttpRequest HttpRequestImpl requestImpl = new HttpRequestImpl(userRequest, proxySelector); if (requestImpl.method().equals("CONNECT")) throw new IllegalArgumentException("Unsupported method CONNECT"); @@ -1049,8 +1011,7 @@ private void debugCompleted(String tag, long startNanos, HttpRequest req) { requestImpl, this, responseHandler, - pushPromiseHandler, - acc); + pushPromiseHandler); CompletableFuture> mexCf = mex.responseAsync(executor); CompletableFuture> res = mexCf.whenComplete((b,t) -> requestUnreference()); if (DEBUGELAPSED) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java index 839b6a6185d..bb794031508 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java @@ -31,9 +31,6 @@ import java.net.Proxy; import java.net.ProxySelector; import java.net.URI; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.time.Duration; import java.util.List; import java.util.Locale; @@ -65,17 +62,13 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest { final boolean secure; final boolean expectContinue; private volatile boolean isWebSocket; - @SuppressWarnings("removal") - private volatile AccessControlContext acc; private final Duration timeout; // may be null private final Optional version; private volatile boolean userSetAuthorization; private volatile boolean userSetProxyAuthorization; private static String userAgent() { - PrivilegedAction pa = () -> System.getProperty("java.version"); - @SuppressWarnings("removal") - String version = AccessController.doPrivileged(pa); + String version = System.getProperty("java.version"); return "Java-http-client/" + version; } @@ -196,7 +189,6 @@ private HttpRequestImpl(URI uri, this.expectContinue = other.expectContinue; this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); this.requestPublisher = mayHaveBody ? publisher(other) : null; // may be null - this.acc = other.acc; this.timeout = other.timeout; this.version = other.version(); this.authority = null; @@ -274,7 +266,6 @@ private HttpRequestImpl(HttpRequestImpl parent, HttpHeaders headers) this.expectContinue = parent.expectContinue; this.secure = parent.secure; this.requestPublisher = parent.requestPublisher; - this.acc = parent.acc; this.timeout = parent.timeout; this.version = parent.version; this.authority = null; @@ -395,7 +386,6 @@ public void setSystemHeader(String name, String value) { systemHeadersBuilder.setHeader(name, value); } - @SuppressWarnings("removal") InetSocketAddress getAddress() { URI uri = uri(); if (uri == null) { @@ -412,8 +402,7 @@ InetSocketAddress getAddress() { final String host = uri.getHost(); final int port = p; if (proxy() == null) { - PrivilegedAction pa = () -> new InetSocketAddress(host, port); - return AccessController.doPrivileged(pa); + return new InetSocketAddress(host, port); } else { return InetSocketAddress.createUnresolved(host, port); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java index 2c15a704ef9..a7fe5f19e02 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java @@ -30,7 +30,6 @@ import java.net.ConnectException; import java.net.http.HttpConnectTimeoutException; import java.time.Duration; -import java.security.AccessControlContext; import java.util.List; import java.util.ListIterator; import java.util.Objects; @@ -79,8 +78,6 @@ class MultiExchange implements Cancelable { private final HttpRequest userRequest; // the user request private final HttpRequestImpl request; // a copy of the user request private final ConnectTimeoutTracker connectTimeout; // null if no timeout - @SuppressWarnings("removal") - final AccessControlContext acc; final HttpClientImpl client; final HttpResponse.BodyHandler responseHandler; final HttpClientImpl.DelegatingExecutor executor; @@ -155,8 +152,7 @@ Duration getRemaining() { HttpRequestImpl requestImpl, HttpClientImpl client, HttpResponse.BodyHandler responseHandler, - PushPromiseHandler pushPromiseHandler, - @SuppressWarnings("removal") AccessControlContext acc) { + PushPromiseHandler pushPromiseHandler) { this.previous = null; this.userRequest = userRequest; this.request = requestImpl; @@ -164,15 +160,11 @@ Duration getRemaining() { this.previousreq = null; this.client = client; this.filters = client.filterChain(); - this.acc = acc; this.executor = client.theExecutor(); this.responseHandler = responseHandler; if (pushPromiseHandler != null) { - Executor ensureExecutedAsync = this.executor::ensureExecutedAsync; - Executor executor = acc == null - ? ensureExecutedAsync - : new PrivilegedExecutor(ensureExecutedAsync, acc); + Executor executor = this.executor::ensureExecutedAsync; this.pushGroup = new PushGroup<>(pushPromiseHandler, request, executor); } else { pushGroup = null; @@ -470,7 +462,7 @@ private CompletableFuture responseAsyncImpl() { previousreq = currentreq; currentreq = newrequest; retriedOnce = false; - setExchange(new Exchange<>(currentreq, this, acc)); + setExchange(new Exchange<>(currentreq, this)); return responseAsyncImpl(); }).thenCompose(Function.identity()); } }) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java index 1b42801e9ba..747945701f8 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,6 @@ import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.locks.ReentrantLock; @@ -167,7 +164,6 @@ public void abort(IOException ioe) { } } - @SuppressWarnings("removal") @Override public CompletableFuture connectAsync(Exchange exchange) { CompletableFuture cf = new MinimalFuture<>(); @@ -191,14 +187,12 @@ public CompletableFuture connectAsync(Exchange exchange) { debug.log("binding to configured local address " + localAddr); } var sockAddr = new InetSocketAddress(localAddr, 0); - PrivilegedExceptionAction pa = () -> chan.bind(sockAddr); try { - AccessController.doPrivileged(pa); + chan.bind(sockAddr); if (debug.on()) { debug.log("bind completed " + localAddr); } - } catch (PrivilegedActionException e) { - var cause = e.getCause(); + } catch (IOException cause) { if (debug.on()) { debug.log("bind to " + localAddr + " failed: " + cause.getMessage()); } @@ -206,13 +200,7 @@ public CompletableFuture connectAsync(Exchange exchange) { } } - PrivilegedExceptionAction pa = - () -> chan.connect(Utils.resolveAddress(address)); - try { - finished = AccessController.doPrivileged(pa); - } catch (PrivilegedActionException e) { - throw e.getCause(); - } + finished = chan.connect(Utils.resolveAddress(address)); if (finished) { if (debug.on()) debug.log("connect finished without blocking"); if (connectionOpened()) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java index 4565514f577..80ca6ba8a3a 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -72,7 +72,7 @@ public CompletableFuture connectAsync(Exchange exchange) { assert client != null; HttpRequestImpl req = new HttpRequestImpl("CONNECT", address, proxyHeaders); MultiExchange mulEx = new MultiExchange<>(null, req, - client, discarding(), null, null); + client, discarding(), null); Exchange connectExchange = mulEx.getExchange(); return connectExchange diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PrivilegedExecutor.java b/src/java.net.http/share/classes/jdk/internal/net/http/PrivilegedExecutor.java deleted file mode 100644 index 72518f2c4e8..00000000000 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PrivilegedExecutor.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.internal.net.http; - -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Objects; -import java.util.concurrent.Executor; - -/** - * Executes tasks within a given access control context, and by a given executor. - */ -class PrivilegedExecutor implements Executor { - - /** The underlying executor. May be provided by the user. */ - final Executor executor; - /** The ACC to execute the tasks within. */ - @SuppressWarnings("removal") - final AccessControlContext acc; - - public PrivilegedExecutor(Executor executor, @SuppressWarnings("removal") AccessControlContext acc) { - Objects.requireNonNull(executor); - Objects.requireNonNull(acc); - this.executor = executor; - this.acc = acc; - } - - private static class PrivilegedRunnable implements Runnable { - private final Runnable r; - @SuppressWarnings("removal") - private final AccessControlContext acc; - PrivilegedRunnable(Runnable r, @SuppressWarnings("removal") AccessControlContext acc) { - this.r = r; - this.acc = acc; - } - @SuppressWarnings("removal") - @Override - public void run() { - PrivilegedAction pa = () -> { r.run(); return null; }; - AccessController.doPrivileged(pa, acc); - } - } - - @Override - public void execute(Runnable r) { - executor.execute(new PrivilegedRunnable(r, acc)); - } -} diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java index cfb0a20fe94..ecf88eb6566 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -27,7 +27,6 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; @@ -37,11 +36,6 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -229,11 +223,6 @@ public void subscribe(Flow.Subscriber subscriber) { /** * Publishes the content of a given file. - *

- * Privileged actions are performed within a limited doPrivileged that only - * asserts the specific, read, file permission that was checked during the - * construction of this FilePublisher. This only applies if the file system - * that created the file provides interoperability with {@code java.io.File}. */ public static class FilePublisher implements BodyPublisher { @@ -241,62 +230,27 @@ public static class FilePublisher implements BodyPublisher { private final long length; private final Function inputStreamSupplier; - private static String pathForSecurityCheck(Path path) { - return path.toFile().getPath(); - } - /** * Factory for creating FilePublisher. - * - * Permission checks are performed here before construction of the - * FilePublisher. Permission checking and construction are deliberately - * and tightly co-located. */ public static FilePublisher create(Path path) throws FileNotFoundException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - FilePermission filePermission = null; boolean defaultFS = true; try { - String fn = pathForSecurityCheck(path); - if (sm != null) { - FilePermission readPermission = new FilePermission(fn, "read"); - sm.checkPermission(readPermission); - filePermission = readPermission; - } + path.toFile().getPath(); } catch (UnsupportedOperationException uoe) { + // path not associated with the default file system provider defaultFS = false; - // Path not associated with the default file system - // Test early if an input stream can still be obtained - try { - if (sm != null) { - Files.newInputStream(path).close(); - } - } catch (IOException ioe) { - if (ioe instanceof FileNotFoundException) { - throw (FileNotFoundException) ioe; - } else { - var ex = new FileNotFoundException(ioe.getMessage()); - ex.initCause(ioe); - throw ex; - } - } } - // existence check must be after permission checks + // existence check must be after FS checks if (Files.notExists(path)) throw new FileNotFoundException(path + " not found"); - Permission perm = filePermission; - assert perm == null || perm.getActions().equals("read"); - @SuppressWarnings("removal") - AccessControlContext acc = sm != null ? - AccessController.getContext() : null; boolean finalDefaultFS = defaultFS; Function inputStreamSupplier = (p) -> - createInputStream(p, acc, perm, finalDefaultFS); + createInputStream(p, finalDefaultFS); long length; try { @@ -308,41 +262,17 @@ public static FilePublisher create(Path path) return new FilePublisher(path, length, inputStreamSupplier); } - @SuppressWarnings("removal") private static InputStream createInputStream(Path path, - AccessControlContext acc, - Permission perm, boolean defaultFS) { try { - if (acc != null) { - PrivilegedExceptionAction pa = defaultFS - ? () -> new FileInputStream(path.toFile()) - : () -> Files.newInputStream(path); - return perm != null - ? AccessController.doPrivileged(pa, acc, perm) - : AccessController.doPrivileged(pa, acc); - } else { - return defaultFS + return defaultFS ? new FileInputStream(path.toFile()) : Files.newInputStream(path); - } - } catch (PrivilegedActionException pae) { - throw toUncheckedException(pae.getCause()); } catch (IOException io) { throw new UncheckedIOException(io); } } - private static RuntimeException toUncheckedException(Throwable t) { - if (t instanceof RuntimeException) - throw (RuntimeException) t; - if (t instanceof Error) - throw (Error) t; - if (t instanceof IOException) - throw new UncheckedIOException((IOException) t); - throw new UndeclaredThrowableException(t); - } - private FilePublisher(Path name, long length, Function inputStreamSupplier) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java index 22e03238d21..79b2332ae37 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java @@ -25,8 +25,6 @@ package jdk.internal.net.http; -import java.io.File; -import java.io.FilePermission; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URI; @@ -34,10 +32,8 @@ import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.AccessControlContext; -import java.security.AccessController; import java.util.List; -import java.util.Objects; + import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; @@ -56,62 +52,31 @@ public final class ResponseBodyHandlers { private ResponseBodyHandlers() { } - private static final String pathForSecurityCheck(Path path) { - return path.toFile().getPath(); - } - /** * A Path body handler. */ public static class PathBodyHandler implements BodyHandler{ private final Path file; private final List openOptions; // immutable list - @SuppressWarnings("removal") - private final AccessControlContext acc; - private final FilePermission filePermission; /** * Factory for creating PathBodyHandler. - * - * Permission checks are performed here before construction of the - * PathBodyHandler. Permission checking and construction are - * deliberately and tightly co-located. */ public static PathBodyHandler create(Path file, List openOptions) { - FilePermission filePermission = null; - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - String fn = pathForSecurityCheck(file); - FilePermission writePermission = new FilePermission(fn, "write"); - sm.checkPermission(writePermission); - filePermission = writePermission; - } catch (UnsupportedOperationException ignored) { - // path not associated with the default file system provider - } - } - assert filePermission == null || filePermission.getActions().equals("write"); - @SuppressWarnings("removal") - var acc = sm != null ? AccessController.getContext() : null; - return new PathBodyHandler(file, openOptions, acc, filePermission); + return new PathBodyHandler(file, openOptions); } private PathBodyHandler(Path file, - List openOptions, - @SuppressWarnings("removal") AccessControlContext acc, - FilePermission filePermission) { + List openOptions) { this.file = file; this.openOptions = openOptions; - this.acc = acc; - this.filePermission = filePermission; } @Override public BodySubscriber apply(ResponseInfo responseInfo) { - return new PathSubscriber(file, openOptions, acc, filePermission); + return new PathSubscriber(file, openOptions); } } @@ -170,44 +135,20 @@ public void applyPushPromise( public static class FileDownloadBodyHandler implements BodyHandler { private final Path directory; private final List openOptions; - @SuppressWarnings("removal") - private final AccessControlContext acc; - private final FilePermission[] filePermissions; // may be null /** * Factory for creating FileDownloadBodyHandler. - * - * Permission checks are performed here before construction of the - * FileDownloadBodyHandler. Permission checking and construction are - * deliberately and tightly co-located. */ public static FileDownloadBodyHandler create(Path directory, List openOptions) { - String fn; try { - fn = pathForSecurityCheck(directory); + directory.toFile().getPath(); } catch (UnsupportedOperationException uoe) { // directory not associated with the default file system provider throw new IllegalArgumentException("invalid path: " + directory, uoe); } - FilePermission filePermissions[] = null; - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - FilePermission writePermission = new FilePermission(fn, "write"); - String writePathPerm = fn + File.separatorChar + "*"; - FilePermission writeInDirPermission = new FilePermission(writePathPerm, "write"); - sm.checkPermission(writeInDirPermission); - FilePermission readPermission = new FilePermission(fn, "read"); - sm.checkPermission(readPermission); - - // read permission is only needed before determine the below checks - // only write permission is required when downloading to the file - filePermissions = new FilePermission[] { writePermission, writeInDirPermission }; - } - - // existence, etc, checks must be after permission checks + // existence, etc, checks must be after FS checks if (Files.notExists(directory)) throw new IllegalArgumentException("non-existent directory: " + directory); if (!Files.isDirectory(directory)) @@ -215,21 +156,13 @@ public static FileDownloadBodyHandler create(Path directory, if (!Files.isWritable(directory)) throw new IllegalArgumentException("non-writable directory: " + directory); - assert filePermissions == null || (filePermissions[0].getActions().equals("write") - && filePermissions[1].getActions().equals("write")); - @SuppressWarnings("removal") - var acc = sm != null ? AccessController.getContext() : null; - return new FileDownloadBodyHandler(directory, openOptions, acc, filePermissions); + return new FileDownloadBodyHandler(directory, openOptions); } private FileDownloadBodyHandler(Path directory, - List openOptions, - @SuppressWarnings("removal") AccessControlContext acc, - FilePermission... filePermissions) { + List openOptions) { this.directory = directory; this.openOptions = openOptions; - this.acc = acc; - this.filePermissions = filePermissions; } /** The "attachment" disposition-type and separator. */ @@ -394,7 +327,7 @@ public BodySubscriber apply(ResponseInfo responseInfo) { "Resulting file, " + file.toString() + ", outside of given directory"); } - return new PathSubscriber(file, openOptions, acc, filePermissions); + return new PathSubscriber(file, openOptions); } } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java index 09ad87f9205..04d019e4c81 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java @@ -26,7 +26,6 @@ package jdk.internal.net.http; import java.io.BufferedReader; -import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -35,11 +34,6 @@ import java.nio.charset.Charset; import java.nio.file.OpenOption; import java.nio.file.Path; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -164,83 +158,31 @@ public void onComplete() { /** * A Subscriber that writes the flow of data to a given file. - * - * Privileged actions are performed within a limited doPrivileged that only - * asserts the specific, write, file permissions that were checked during - * the construction of this PathSubscriber. */ public static class PathSubscriber implements TrustedSubscriber { - - private static final FilePermission[] EMPTY_FILE_PERMISSIONS = new FilePermission[0]; - private final Path file; private final OpenOption[] options; - @SuppressWarnings("removal") - private final AccessControlContext acc; - private final FilePermission[] filePermissions; - private final boolean isDefaultFS; private final CompletableFuture result = new MinimalFuture<>(); private final AtomicBoolean subscribed = new AtomicBoolean(); private volatile Flow.Subscription subscription; private volatile FileChannel out; - private static final String pathForSecurityCheck(Path path) { - return path.toFile().getPath(); - } - /** * Factory for creating PathSubscriber. - * - * Permission checks are performed here before construction of the - * PathSubscriber. Permission checking and construction are deliberately - * and tightly co-located. */ public static PathSubscriber create(Path file, List options) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - FilePermission filePermission = null; - if (sm != null) { - try { - String fn = pathForSecurityCheck(file); - FilePermission writePermission = new FilePermission(fn, "write"); - sm.checkPermission(writePermission); - filePermission = writePermission; - } catch (UnsupportedOperationException ignored) { - // path not associated with the default file system provider - } - } - - assert filePermission == null || filePermission.getActions().equals("write"); - @SuppressWarnings("removal") - AccessControlContext acc = sm != null ? AccessController.getContext() : null; - return new PathSubscriber(file, options, acc, filePermission); + return new PathSubscriber(file, options); } // pp so handler implementations in the same package can construct /*package-private*/ PathSubscriber(Path file, - List options, - @SuppressWarnings("removal") AccessControlContext acc, - FilePermission... filePermissions) { + List options) { this.file = file; this.options = options.stream().toArray(OpenOption[]::new); - this.acc = acc; - this.filePermissions = filePermissions == null || filePermissions[0] == null - ? EMPTY_FILE_PERMISSIONS : filePermissions; - this.isDefaultFS = isDefaultFS(file); - } - - private static boolean isDefaultFS(Path file) { - try { - file.toFile(); - return true; - } catch (UnsupportedOperationException uoe) { - return false; - } } - @SuppressWarnings("removal") @Override public void onSubscribe(Flow.Subscription subscription) { Objects.requireNonNull(subscription); @@ -250,31 +192,12 @@ public void onSubscribe(Flow.Subscription subscription) { } this.subscription = subscription; - if (acc == null) { - try { - out = FileChannel.open(file, options); - } catch (IOException ioe) { - result.completeExceptionally(ioe); - subscription.cancel(); - return; - } - } else { - try { - PrivilegedExceptionAction pa = - () -> FileChannel.open(file, options); - out = isDefaultFS - ? AccessController.doPrivileged(pa, acc, filePermissions) - : AccessController.doPrivileged(pa, acc); - } catch (PrivilegedActionException pae) { - Throwable t = pae.getCause() != null ? pae.getCause() : pae; - result.completeExceptionally(t); - subscription.cancel(); - return; - } catch (Exception e) { - result.completeExceptionally(e); - subscription.cancel(); - return; - } + try { + out = FileChannel.open(file, options); + } catch (IOException ioe) { + result.completeExceptionally(ioe); + subscription.cancel(); + return; } subscription.request(1); } @@ -311,21 +234,8 @@ public CompletionStage getBody() { return result; } - @SuppressWarnings("removal") private void close() { - if (acc == null) { - Utils.close(out); - } else { - PrivilegedAction pa = () -> { - Utils.close(out); - return null; - }; - if (isDefaultFS) { - AccessController.doPrivileged(pa, acc, filePermissions); - } else { - AccessController.doPrivileged(pa, acc); - } - } + Utils.close(out); } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java index bbb63718dc6..f3eedf8fe6e 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java @@ -160,6 +160,10 @@ class Stream extends ExchangeImpl { // send lock: prevent sending DataFrames after reset occurred. private final Lock sendLock = new ReentrantLock(); private final Lock stateLock = new ReentrantLock(); + // inputQ lock: methods that take from the inputQ + // must not run concurrently. + private final Lock inputQLock = new ReentrantLock(); + /** * A reference to this Stream's connection Send Window controller. The * stream MUST acquire the appropriate amount of Send Window before @@ -183,6 +187,8 @@ HttpConnection connection() { private void schedule() { boolean onCompleteCalled = false; HttpResponse.BodySubscriber subscriber = responseSubscriber; + // prevents drainInputQueue() from running concurrently + inputQLock.lock(); try { if (subscriber == null) { // pendingResponseSubscriber will be null until response headers have been received and @@ -199,7 +205,7 @@ private void schedule() { Http2Frame frame = inputQ.peek(); if (frame instanceof ResetFrame rf) { inputQ.remove(); - if (endStreamReceived() && rf.getErrorCode() == ResetFrame.NO_ERROR) { + if (endStreamReceived() && rf.getErrorCode() == ResetFrame.NO_ERROR) { // If END_STREAM is already received, complete the requestBodyCF successfully // and stop sending any request data. requestBodyCF.complete(null); @@ -208,7 +214,7 @@ private void schedule() { } return; } - DataFrame df = (DataFrame)frame; + DataFrame df = (DataFrame) frame; boolean finished = df.getFlag(DataFrame.END_STREAM); List buffers = df.getData(); @@ -256,6 +262,7 @@ private void schedule() { } catch (Throwable throwable) { errorRef.compareAndSet(null, throwable); } finally { + inputQLock.unlock(); if (sched.isStopped()) drainInputQueue(); } @@ -274,26 +281,36 @@ private void schedule() { } catch (Throwable x) { Log.logError("Subscriber::onError threw exception: {0}", t); } finally { + // cancelImpl will eventually call drainInputQueue(); cancelImpl(t); - drainInputQueue(); } } } - // must only be called from the scheduler schedule() loop. - // ensure that all received data frames are accounted for + // Called from the scheduler schedule() loop, + // or after resetting the stream. + // Ensures that all received data frames are accounted for // in the connection window flow control if the scheduler // is stopped before all the data is consumed. + // The inputQLock is used to prevent concurrently taking + // from the queue. private void drainInputQueue() { Http2Frame frame; - while ((frame = inputQ.poll()) != null) { - if (frame instanceof DataFrame df) { - // Data frames that have been added to the inputQ - // must be released using releaseUnconsumed() to - // account for the amount of unprocessed bytes - // tracked by the connection.windowUpdater. - connection.releaseUnconsumed(df); + // will wait until schedule() has finished taking + // from the queue, if needed. + inputQLock.lock(); + try { + while ((frame = inputQ.poll()) != null) { + if (frame instanceof DataFrame df) { + // Data frames that have been added to the inputQ + // must be released using releaseUnconsumed() to + // account for the amount of unprocessed bytes + // tracked by the connection.windowUpdater. + connection.releaseUnconsumed(df); + } } + } finally { + inputQLock.unlock(); } } @@ -405,12 +422,38 @@ private void receiveDataFrame(DataFrame df) { return; } } - inputQ.add(df); + pushDataFrame(len, df); } finally { sched.runOrSchedule(); } } + // Ensures that no data frame is pushed on the inputQ + // after the stream is closed. + // Changes to the `closed` boolean are guarded by the + // stateLock. Contention should be low as only one + // thread at a time adds to the inputQ, and + // we can only contend when closing the stream. + // Note that this method can run concurrently with + // methods holding the inputQLock: that is OK. + // The inputQLock is there to ensure that methods + // taking from the queue are not running concurrently + // with each others, but concurrently adding at the + // end of the queue while peeking/polling at the head + // is OK. + private void pushDataFrame(int len, DataFrame df) { + boolean closed = false; + stateLock.lock(); + try { + if (!(closed = this.closed)) { + inputQ.add(df); + } + } finally { + stateLock.unlock(); + } + if (closed && len > 0) connection.releaseUnconsumed(df); + } + /** Handles a RESET frame. RESET is always handled inline in the queue. */ private void receiveResetFrame(ResetFrame frame) { inputQ.add(frame); @@ -1547,6 +1590,8 @@ void cancelImpl(final Throwable e, final int resetFrameErrCode) { } } catch (Throwable ex) { Log.logError(ex); + } finally { + drainInputQueue(); } } @@ -1770,7 +1815,7 @@ String dbgString() { @Override protected boolean windowSizeExceeded(long received) { onProtocolError(new ProtocolException("stream %s flow control window exceeded" - .formatted(streamid)), ResetFrame.FLOW_CONTROL_ERROR); + .formatted(streamid)), ResetFrame.FLOW_CONTROL_ERROR); return true; } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java index bb6540e44b9..2a5f125c0c4 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -27,7 +27,6 @@ import java.security.Principal; import java.util.List; -import javax.net.ssl.SSLSession; import javax.net.ssl.ExtendedSSLSession; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLPeerUnverifiedException; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index ef5af764e76..511b17d7813 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -39,8 +39,6 @@ import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.URI; -import java.net.URLPermission; -import java.net.http.HttpClient; import java.net.http.HttpHeaders; import java.net.http.HttpTimeoutException; import java.nio.ByteBuffer; @@ -51,8 +49,6 @@ import java.nio.charset.Charset; import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.text.Normalizer; import java.util.Arrays; import java.util.Collection; @@ -100,10 +96,7 @@ public final class Utils { // public static final boolean TESTING; // static { -// if (ASSERTIONSENABLED) { -// PrivilegedAction action = () -> System.getProperty("test.src"); -// TESTING = AccessController.doPrivileged(action) != null; -// } else TESTING = false; +// TESTING = ASSERTIONSENABLED ? System.getProperty("test.src") != null : false; // } public static final LoggerConfig DEBUG_CONFIG = getLoggerConfig(DebugLogger.HTTP_NAME, LoggerConfig.OFF); @@ -120,9 +113,7 @@ public final class Utils { hostnameVerificationDisabledValue(); private static LoggerConfig getLoggerConfig(String loggerName, LoggerConfig def) { - PrivilegedAction action = () -> System.getProperty(loggerName); - @SuppressWarnings("removal") - var prop = AccessController.doPrivileged(action); + var prop = System.getProperty(loggerName); if (prop == null) return def; var config = LoggerConfig.OFF; for (var s : prop.split(",")) { @@ -449,41 +440,6 @@ public static Throwable wrapWithExtraDetail(Throwable t, private Utils() { } - /** - * Returns the security permissions required to connect to the proxy, or - * {@code null} if none is required or applicable. - */ - public static URLPermission permissionForProxy(InetSocketAddress proxyAddress) { - if (proxyAddress == null) - return null; - - StringBuilder sb = new StringBuilder(); - sb.append("socket://") - .append(proxyAddress.getHostString()).append(":") - .append(proxyAddress.getPort()); - String urlString = sb.toString(); - return new URLPermission(urlString, "CONNECT"); - } - - /** - * Returns the security permission required for the given details. - */ - public static URLPermission permissionForServer(URI uri, - String method, - Stream headers) { - String urlString = new StringBuilder() - .append(uri.getScheme()).append("://") - .append(uri.getRawAuthority()) - .append(uri.getRawPath()).toString(); - - StringBuilder actionStringBuilder = new StringBuilder(method); - String collected = headers.collect(joining(",")); - if (!collected.isEmpty()) { - actionStringBuilder.append(":").append(collected); - } - return new URLPermission(urlString, actionStringBuilder.toString()); - } - private static final boolean[] LOWER_CASE_CHARS = new boolean[128]; // ABNF primitives defined in RFC 7230 @@ -587,34 +543,24 @@ public static boolean isValidValue(String token) { return true; } - @SuppressWarnings("removal") public static int getIntegerNetProperty(String name, int defaultValue) { - return AccessController.doPrivileged((PrivilegedAction) () -> - NetProperties.getInteger(name, defaultValue)); + return NetProperties.getInteger(name, defaultValue); } - @SuppressWarnings("removal") public static String getNetProperty(String name) { - return AccessController.doPrivileged((PrivilegedAction) () -> - NetProperties.get(name)); + return NetProperties.get(name); } - @SuppressWarnings("removal") public static boolean getBooleanProperty(String name, boolean def) { - return AccessController.doPrivileged((PrivilegedAction) () -> - Boolean.parseBoolean(System.getProperty(name, String.valueOf(def)))); + return Boolean.parseBoolean(System.getProperty(name, String.valueOf(def))); } - @SuppressWarnings("removal") public static String getProperty(String name) { - return AccessController.doPrivileged((PrivilegedAction) () -> - System.getProperty(name)); + return System.getProperty(name); } - @SuppressWarnings("removal") public static int getIntegerProperty(String name, int defaultValue) { - return AccessController.doPrivileged((PrivilegedAction) () -> - Integer.parseInt(System.getProperty(name, String.valueOf(defaultValue)))); + return Integer.parseInt(System.getProperty(name, String.valueOf(defaultValue))); } public static int getIntegerNetProperty(String property, int min, int max, int defaultValue, boolean log) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java index abecde71665..d49b8c391cb 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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,8 +28,6 @@ import jdk.internal.net.http.hpack.HPACK.Logger.Level; import java.nio.ByteBuffer; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Map; import java.util.ResourceBundle; import java.util.function.Supplier; @@ -52,9 +50,7 @@ public final class HPACK { static { String PROPERTY = "jdk.internal.httpclient.hpack.log.level"; - @SuppressWarnings("removal") - String value = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty(PROPERTY)); + String value = System.getProperty(PROPERTY); if (value == null) { LOGGER = new RootLogger(NONE); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java index f88ec774dc0..c1c0853504c 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -39,17 +39,13 @@ import jdk.internal.net.http.common.Utils; import java.io.IOException; -import java.net.InetSocketAddress; import java.net.Proxy; import java.net.ProxySelector; import java.net.URI; import java.net.URISyntaxException; -import java.net.URLPermission; import java.nio.charset.StandardCharsets; -import java.security.AccessController; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.PrivilegedAction; import java.security.SecureRandom; import java.time.Duration; import java.util.Base64; @@ -61,11 +57,9 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.CompletableFuture; -import java.util.stream.Stream; import static java.lang.String.format; import static jdk.internal.net.http.common.Utils.isValidName; -import static jdk.internal.net.http.common.Utils.permissionForProxy; import static jdk.internal.net.http.common.Utils.stringOf; public class OpeningHandshake { @@ -112,7 +106,6 @@ public class OpeningHandshake { public OpeningHandshake(BuilderImpl b) { checkURI(b.getUri()); Proxy proxy = proxyFor(b.getProxySelector(), b.getUri()); - checkPermissions(b, proxy); this.client = b.getClient(); URI httpURI = createRequestURI(b.getUri()); HttpRequestBuilderImpl requestBuilder = new HttpRequestBuilderImpl(httpURI); @@ -185,12 +178,9 @@ static URI createRequestURI(URI uri) { } } - @SuppressWarnings("removal") public CompletableFuture send() { - PrivilegedAction> pa = () -> - client.sendAsync(this.request, BodyHandlers.ofString()) + return client.sendAsync(this.request, BodyHandlers.ofString()) .thenCompose(this::resultFrom); - return AccessController.doPrivileged(pa); } /* @@ -376,27 +366,4 @@ private static Proxy proxyFor(Optional selector, URI uri) { return proxy; } - /** - * Performs the necessary security permissions checks to connect ( possibly - * through a proxy ) to the builders WebSocket URI. - * - * @throws SecurityException if the security manager denies access - */ - static void checkPermissions(BuilderImpl b, Proxy proxy) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - Stream headers = b.getHeaders().stream().map(p -> p.first).distinct(); - URLPermission perm1 = Utils.permissionForServer(b.getUri(), "", headers); - sm.checkPermission(perm1); - if (proxy == null) { - return; - } - URLPermission perm2 = permissionForProxy((InetSocketAddress) proxy.address()); - if (perm2 != null) { - sm.checkPermission(perm2); - } - } } diff --git a/src/java.rmi/share/classes/java/rmi/MarshalledObject.java b/src/java.rmi/share/classes/java/rmi/MarshalledObject.java index 148cc97ef94..acf402db4d9 100644 --- a/src/java.rmi/share/classes/java/rmi/MarshalledObject.java +++ b/src/java.rmi/share/classes/java/rmi/MarshalledObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -35,8 +35,6 @@ import java.io.ObjectStreamConstants; import java.io.OutputStream; import java.io.Serializable; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.rmi.server.MarshalInputStream; import sun.rmi.server.MarshalOutputStream; @@ -317,7 +315,6 @@ private static class MarshalledObjectInputStream * null, then all annotations will be * null. */ - @SuppressWarnings("removal") MarshalledObjectInputStream(InputStream objIn, InputStream locIn, ObjectInputFilter filter) throws IOException @@ -325,13 +322,10 @@ private static class MarshalledObjectInputStream super(objIn); this.locIn = (locIn == null ? null : new ObjectInputStream(locIn)); if (filter != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - MarshalledObjectInputStream.this.setObjectInputFilter(filter); - if (MarshalledObjectInputStream.this.locIn != null) { - MarshalledObjectInputStream.this.locIn.setObjectInputFilter(filter); - } - return null; - }); + MarshalledObjectInputStream.this.setObjectInputFilter(filter); + if (MarshalledObjectInputStream.this.locIn != null) { + MarshalledObjectInputStream.this.locIn.setObjectInputFilter(filter); + } } } diff --git a/src/java.rmi/share/classes/java/rmi/server/LogStream.java b/src/java.rmi/share/classes/java/rmi/server/LogStream.java index ca554569d3b..8ac26770263 100644 --- a/src/java.rmi/share/classes/java/rmi/server/LogStream.java +++ b/src/java.rmi/share/classes/java/rmi/server/LogStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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,14 +120,6 @@ public static synchronized PrintStream getDefaultStream() { */ @Deprecated public static synchronized void setDefaultStream(PrintStream newDefault) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - - if (sm != null) { - sm.checkPermission( - new java.util.logging.LoggingPermission("control", null)); - } - defaultStream = newDefault; } diff --git a/src/java.rmi/share/classes/java/rmi/server/ObjID.java b/src/java.rmi/share/classes/java/rmi/server/ObjID.java index ae3a61277ec..894ee317d28 100644 --- a/src/java.rmi/share/classes/java/rmi/server/ObjID.java +++ b/src/java.rmi/share/classes/java/rmi/server/ObjID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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,8 +30,6 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.security.SecureRandom; import java.util.concurrent.atomic.AtomicLong; @@ -242,9 +240,7 @@ public String toString() { } private static boolean useRandomIDs() { - @SuppressWarnings("removal") - String value = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("java.rmi.server.randomIDs")); + String value = System.getProperty("java.rmi.server.randomIDs"); return value == null ? true : Boolean.parseBoolean(value); } } diff --git a/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java b/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java index 6736c33f0a0..004ea27e30a 100644 --- a/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java +++ b/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java @@ -27,8 +27,6 @@ import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Iterator; import java.util.ServiceLoader; @@ -112,12 +110,7 @@ public class RMIClassLoader { newDefaultProviderInstance(); /** provider instance */ - @SuppressWarnings("removal") - private static final RMIClassLoaderSpi provider = - AccessController.doPrivileged( - new PrivilegedAction() { - public RMIClassLoaderSpi run() { return initializeProvider(); } - }); + private static final RMIClassLoaderSpi provider = initializeProvider(); /* * Disallow anyone from creating one of these. @@ -538,11 +531,6 @@ public static String getClassAnnotation(Class cl) { * @since 1.4 */ public static RMIClassLoaderSpi getDefaultProviderInstance() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("setFactory")); - } return defaultProvider; } diff --git a/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java b/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java index fedc4b22d9b..a7fc07f3d4b 100644 --- a/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java +++ b/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java @@ -131,11 +131,6 @@ public static synchronized void setSocketFactory(RMISocketFactory fac) if (factory != null) { throw new SocketException("factory already defined"); } - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkSetFactory(); - } factory = fac; } @@ -181,11 +176,6 @@ public static synchronized RMISocketFactory getDefaultSocketFactory() { */ public static synchronized void setFailureHandler(RMIFailureHandler fh) { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkSetFactory(); - } handler = fh; } diff --git a/src/java.rmi/share/classes/sun/rmi/log/ReliableLog.java b/src/java.rmi/share/classes/sun/rmi/log/ReliableLog.java index 293e2ccdec3..ce2aa84d312 100644 --- a/src/java.rmi/share/classes/sun/rmi/log/ReliableLog.java +++ b/src/java.rmi/share/classes/sun/rmi/log/ReliableLog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -27,9 +27,6 @@ import java.io.*; import java.lang.reflect.Constructor; -import java.rmi.server.RMIClassLoader; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * This class is a simple implementation of a reliable Log. The @@ -132,15 +129,13 @@ public class ReliableLog { * if an exception occurs during invocation of the handler's * snapshot method or if other IOException occurs. */ - @SuppressWarnings("removal") public ReliableLog(String dirPath, LogHandler handler, boolean pad) throws IOException { super(); - this.Debug = AccessController.doPrivileged( - (PrivilegedAction) () -> Boolean.getBoolean("sun.rmi.log.debug")); + this.Debug = Boolean.getBoolean("sun.rmi.log.debug"); dir = new File(dirPath); if (!(dir.exists() && dir.isDirectory())) { // create directory @@ -331,19 +326,10 @@ public synchronized void update(Object value, boolean forceToDisk) private static Constructor getLogClassConstructor() { - @SuppressWarnings("removal") - String logClassName = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("sun.rmi.log.class")); + String logClassName = System.getProperty("sun.rmi.log.class"); if (logClassName != null) { try { - @SuppressWarnings("removal") - ClassLoader loader = - AccessController.doPrivileged( - new PrivilegedAction() { - public ClassLoader run() { - return ClassLoader.getSystemClassLoader(); - } - }); + ClassLoader loader = ClassLoader.getSystemClassLoader(); Class cl = loader.loadClass(logClassName).asSubclass(LogFile.class); return cl.getConstructor(String.class, String.class); diff --git a/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java index 91bb92d9833..406e16b6376 100644 --- a/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java +++ b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java @@ -263,7 +263,6 @@ public String[] list() * Check that the caller has access to perform indicated operation. * The client must be on same the same host as this server. */ - @SuppressWarnings("removal") public static void checkAccess(String op) throws AccessException { try { @@ -370,7 +369,6 @@ private static URL[] pathToURLs(String path) { * {@link ObjectInputFilter.Status#REJECTED} if rejected, * otherwise {@link ObjectInputFilter.Status#UNDECIDED} */ - @SuppressWarnings("removal") private static ObjectInputFilter.Status registryFilter(ObjectInputFilter.FilterInfo filterInfo) { if (registryFilter != null) { ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo); diff --git a/src/java.rmi/share/classes/sun/rmi/runtime/Log.java b/src/java.rmi/share/classes/sun/rmi/runtime/Log.java index 849b35688d1..78154bb21c8 100644 --- a/src/java.rmi/share/classes/sun/rmi/runtime/Log.java +++ b/src/java.rmi/share/classes/sun/rmi/runtime/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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,7 +30,6 @@ import java.io.OutputStream; import java.lang.StackWalker.StackFrame; import java.rmi.server.LogStream; -import java.security.PrivilegedAction; import java.util.Set; import java.util.logging.Handler; import java.util.logging.SimpleFormatter; @@ -69,9 +68,7 @@ public abstract class Log { /* selects log implementation */ private static final LogFactory logFactory; static { - @SuppressWarnings("removal") - boolean useOld = java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> Boolean.getBoolean("sun.rmi.log.useOld")); + boolean useOld = Boolean.getBoolean("sun.rmi.log.useOld"); /* set factory to select the logging facility to use */ logFactory = (useOld ? (LogFactory) new LogStreamLogFactory() : @@ -177,17 +174,12 @@ public Log createLog(final String loggerName, String oldLogName, private static class LoggerLog extends Log { /* alternate console handler for RMI loggers */ - @SuppressWarnings("removal") - private static final Handler alternateConsole = - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Handler run() { - InternalStreamHandler alternate = - new InternalStreamHandler(System.err); - alternate.setLevel(Level.ALL); - return alternate; - } - }); + private static final Handler alternateConsole; + static { + var alternate = new InternalStreamHandler(System.err); + alternate.setLevel(Level.ALL); + alternateConsole = alternate; + } /** handler to which messages are copied */ private InternalStreamHandler copyHandler = null; @@ -199,22 +191,14 @@ public Handler run() { private LoggerPrintStream loggerSandwich; /** creates a Log which will delegate to the given logger */ - @SuppressWarnings("removal") private LoggerLog(final Logger logger, final Level level) { this.logger = logger; - if (level != null){ - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - if (!logger.isLoggable(level)) { - logger.setLevel(level); - } - logger.addHandler(alternateConsole); - return null; - } - } - ); + if (level != null) { + if (!logger.isLoggable(level)) { + logger.setLevel(level); + } + logger.addHandler(alternateConsole); } } @@ -247,8 +231,6 @@ public String toString() { /** * Set the output stream associated with the RMI server call * logger. - * - * Calling code needs LoggingPermission "control". */ public synchronized void setOutputStream(OutputStream out) { if (out != null) { diff --git a/src/java.rmi/share/classes/sun/rmi/runtime/NewThreadAction.java b/src/java.rmi/share/classes/sun/rmi/runtime/NewThreadAction.java index aebd200afe6..f9be382d0fc 100644 --- a/src/java.rmi/share/classes/sun/rmi/runtime/NewThreadAction.java +++ b/src/java.rmi/share/classes/sun/rmi/runtime/NewThreadAction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,11 @@ package sun.rmi.runtime; -import java.security.AccessController; -import java.security.PrivilegedAction; -import sun.security.util.SecurityConstants; - /** - * A PrivilegedAction for creating a new thread conveniently with an - * AccessController.doPrivileged construct. + * A utility class for creating threads. The constructors take a + * variety of parameters to configure the thread. The run() method + * creates and sets up the thread and returns it, but does not + * start it. * * All constructors allow the choice of the Runnable for the new * thread to execute, the name of the new thread (which will be @@ -48,34 +46,27 @@ * * @author Peter Jones **/ -public final class NewThreadAction implements PrivilegedAction { +public final class NewThreadAction { /** cached reference to the system (root) thread group */ - @SuppressWarnings("removal") - static final ThreadGroup systemThreadGroup = - AccessController.doPrivileged(new PrivilegedAction() { - public ThreadGroup run() { - ThreadGroup group = Thread.currentThread().getThreadGroup(); - ThreadGroup parent; - while ((parent = group.getParent()) != null) { - group = parent; - } - return group; - } - }); + static final ThreadGroup systemThreadGroup; + static { + ThreadGroup group = Thread.currentThread().getThreadGroup(); + ThreadGroup parent; + while ((parent = group.getParent()) != null) { + group = parent; + } + systemThreadGroup = group; + } + /** - * special child of the system thread group for running tasks that - * may execute user code, so that the security policy for threads in - * the system thread group will not apply + * Special child of the system thread group for running tasks that + * may execute user code. The need for a separate thread group may + * be a vestige of it having had a different security policy from + * the system thread group, so this might no longer be necessary. */ - @SuppressWarnings("removal") - static final ThreadGroup userThreadGroup = - AccessController.doPrivileged(new PrivilegedAction() { - public ThreadGroup run() { - return new ThreadGroup(systemThreadGroup, "RMI Runtime"); - } - }); + static final ThreadGroup userThreadGroup = new ThreadGroup(systemThreadGroup, "RMI Runtime"); private final ThreadGroup group; private final Runnable runnable; @@ -128,11 +119,6 @@ public NewThreadAction(Runnable runnable, String name, boolean daemon, } public Thread run() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } Thread t = new Thread(group, runnable, "RMI " + name); t.setContextClassLoader(ClassLoader.getSystemClassLoader()); t.setDaemon(daemon); diff --git a/src/java.rmi/share/classes/sun/rmi/runtime/RuntimeUtil.java b/src/java.rmi/share/classes/sun/rmi/runtime/RuntimeUtil.java index b45bbe5f3a3..4be706e57bb 100644 --- a/src/java.rmi/share/classes/sun/rmi/runtime/RuntimeUtil.java +++ b/src/java.rmi/share/classes/sun/rmi/runtime/RuntimeUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,6 @@ package sun.rmi.runtime; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedAction; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; @@ -37,10 +34,7 @@ * RMI runtime implementation utilities. * * There is a single instance of this class, which can be obtained - * with a GetInstanceAction. Getting the instance requires - * RuntimePermission("sun.rmi.runtime.RuntimeUtil.getInstance") - * because the public methods of this class expose security-sensitive - * capabilities. + * with a getInstance() call. * * @author Peter Jones **/ @@ -51,14 +45,8 @@ public final class RuntimeUtil { Log.getLog("sun.rmi.runtime", null, false); /** number of scheduler threads */ - @SuppressWarnings("removal") private static final int schedulerThreads = // default 1 - AccessController.doPrivileged((PrivilegedAction) () -> - Integer.getInteger("sun.rmi.runtime.schedulerThreads", 1)); - - /** permission required to get instance */ - private static final Permission GET_INSTANCE_PERMISSION = - new RuntimePermission("sun.rmi.runtime.RuntimeUtil.getInstance"); + Integer.getInteger("sun.rmi.runtime.schedulerThreads", 1); /** the singleton instance of this class */ private static final RuntimeUtil instance = new RuntimeUtil(); @@ -71,13 +59,11 @@ private RuntimeUtil() { schedulerThreads, new ThreadFactory() { private final AtomicInteger count = new AtomicInteger(); - @SuppressWarnings("removal") public Thread newThread(Runnable runnable) { try { - return AccessController.doPrivileged( - new NewThreadAction(runnable, - "Scheduler(" + count.getAndIncrement() + ")", - true)); + return new NewThreadAction(runnable, + "Scheduler(" + count.getAndIncrement() + ")", + true).run(); } catch (Throwable t) { runtimeLog.log(Level.WARNING, "scheduler thread factory throws", t); @@ -94,29 +80,7 @@ public Thread newThread(Runnable runnable) { // stpe.allowCoreThreadTimeOut(true); } - /** - * A PrivilegedAction for getting the RuntimeUtil instance. - **/ - public static class GetInstanceAction - implements PrivilegedAction - { - /** - * Creates an action that returns the RuntimeUtil instance. - **/ - public GetInstanceAction() { - } - - public RuntimeUtil run() { - return getInstance(); - } - } - - private static RuntimeUtil getInstance() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(GET_INSTANCE_PERMISSION); - } + public static RuntimeUtil getInstance() { return instance; } diff --git a/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java b/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java index 5574da072eb..30b6c47ed3d 100644 --- a/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java +++ b/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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,7 +34,6 @@ import java.security.AccessControlException; import java.security.Permission; import java.rmi.server.RMIClassLoader; -import java.security.PrivilegedAction; /** * MarshalInputStream is an extension of ObjectInputStream. When resolving @@ -62,12 +61,9 @@ public class MarshalInputStream extends ObjectInputStream { * The value is only false when the property is present * and is equal to "false". */ - @SuppressWarnings("removal") private static final boolean useCodebaseOnlyProperty = - ! java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty( - "java.rmi.server.useCodebaseOnly", "true")) - .equalsIgnoreCase("false"); + ! System.getProperty("java.rmi.server.useCodebaseOnly", "true") + .equalsIgnoreCase("false"); /** table to hold sun classes to which access is explicitly permitted */ protected static Map> permittedSunClasses diff --git a/src/java.rmi/share/classes/sun/rmi/server/MarshalOutputStream.java b/src/java.rmi/share/classes/sun/rmi/server/MarshalOutputStream.java index 26dae06c2d7..81bf7bf42e7 100644 --- a/src/java.rmi/share/classes/sun/rmi/server/MarshalOutputStream.java +++ b/src/java.rmi/share/classes/sun/rmi/server/MarshalOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -58,19 +58,12 @@ public MarshalOutputStream(OutputStream out) throws IOException { /** * Creates a marshal output stream with the given protocol version. */ - @SuppressWarnings("removal") public MarshalOutputStream(OutputStream out, int protocolVersion) throws IOException { super(out); this.useProtocolVersion(protocolVersion); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - enableReplaceObject(true); - return null; - } - }); + enableReplaceObject(true); } /** diff --git a/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java b/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java index 0e41b5615b5..39ff8ce8f20 100644 --- a/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java +++ b/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,6 @@ import java.rmi.server.RemoteCall; import java.rmi.server.RemoteObject; import java.rmi.server.RemoteRef; -import java.security.AccessController; -import java.security.PrivilegedAction; import jdk.internal.access.SharedSecrets; import sun.rmi.runtime.Log; @@ -64,11 +62,9 @@ public class UnicastRef implements RemoteRef { /** * Client-side call log. */ - @SuppressWarnings("removal") public static final Log clientCallLog = Log.getLog("sun.rmi.client.call", "RMI", - AccessController.doPrivileged((PrivilegedAction) () -> - Boolean.getBoolean("sun.rmi.client.logCalls"))); + Boolean.getBoolean("sun.rmi.client.logCalls")); private static final long serialVersionUID = 8258372400816541186L; @SuppressWarnings("serial") // Type of field is not Serializable diff --git a/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java b/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java index 7c5b8f911f7..6263bf6d599 100644 --- a/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java +++ b/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -48,14 +48,11 @@ import java.rmi.server.ServerRef; import java.rmi.server.Skeleton; import java.rmi.server.SkeletonNotFoundException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicInteger; import sun.rmi.runtime.Log; import sun.rmi.transport.LiveRef; import sun.rmi.transport.StreamRemoteCall; @@ -80,9 +77,7 @@ public class UnicastServerRef extends UnicastRef implements ServerRef, Dispatcher { /** value of server call log property */ - @SuppressWarnings("removal") - public static final boolean logCalls = AccessController.doPrivileged( - (PrivilegedAction) () -> Boolean.getBoolean("java.rmi.server.logCalls")); + public static final boolean logCalls = Boolean.getBoolean("java.rmi.server.logCalls"); /** server call log */ public static final Log callLog = @@ -92,10 +87,8 @@ public class UnicastServerRef extends UnicastRef private static final long serialVersionUID = -7384275867073752268L; /** flag to enable writing exceptions to System.err */ - @SuppressWarnings("removal") private static final boolean wantExceptionLog = - AccessController.doPrivileged((PrivilegedAction) () -> - Boolean.getBoolean("sun.rmi.server.exceptionTrace")); + Boolean.getBoolean("sun.rmi.server.exceptionTrace"); private boolean forceStubUse = false; @@ -103,10 +96,8 @@ public class UnicastServerRef extends UnicastRef * flag to remove server-side stack traces before marshalling * exceptions thrown by remote invocations to this VM */ - @SuppressWarnings("removal") private static final boolean suppressStackTraces = - AccessController.doPrivileged((PrivilegedAction) () -> - Boolean.getBoolean("sun.rmi.server.suppressStackTraces")); + Boolean.getBoolean("sun.rmi.server.suppressStackTraces"); /** * skeleton to dispatch remote calls through, for 1.1 stub protocol @@ -413,18 +404,10 @@ public void dispatch(Remote obj, RemoteCall call) throws IOException { * Sets a filter for invocation arguments, if a filter has been set. * Called by dispatch before the arguments are read. */ - @SuppressWarnings("removal") protected void unmarshalCustomCallData(ObjectInput in) throws IOException, ClassNotFoundException { - if (filter != null && - in instanceof ObjectInputStream) { - // Set the filter on the stream - ObjectInputStream ois = (ObjectInputStream) in; - - AccessController.doPrivileged((PrivilegedAction)() -> { - ois.setObjectInputFilter(filter); - return null; - }); + if (filter != null && in instanceof ObjectInputStream ois) { + ois.setObjectInputFilter(filter); } } @@ -576,7 +559,6 @@ private static class HashToMethod_Maps { HashToMethod_Maps() {} - @SuppressWarnings("removal") protected Map computeValue(Class remoteClass) { Map map = new HashMap<>(); for (Class cl = remoteClass; @@ -586,20 +568,13 @@ protected Map computeValue(Class remoteClass) { for (Class intf : cl.getInterfaces()) { if (Remote.class.isAssignableFrom(intf)) { for (Method method : intf.getMethods()) { - final Method m = method; /* * Set this Method object to override language * access checks so that the dispatcher can invoke * methods from non-public remote interfaces. */ - AccessController.doPrivileged( - new PrivilegedAction() { - public Void run() { - m.setAccessible(true); - return null; - } - }); - map.put(Util.computeMethodHash(m), m); + method.setAccessible(true); + map.put(Util.computeMethodHash(method), method); } } } diff --git a/src/java.rmi/share/classes/sun/rmi/server/Util.java b/src/java.rmi/share/classes/sun/rmi/server/Util.java index 2c1cfe52ffe..8b9896bf2a9 100644 --- a/src/java.rmi/share/classes/sun/rmi/server/Util.java +++ b/src/java.rmi/share/classes/sun/rmi/server/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -35,28 +35,20 @@ import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.StubNotFoundException; -import java.rmi.registry.Registry; import java.rmi.server.LogStream; -import java.rmi.server.ObjID; -import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RemoteObjectInvocationHandler; import java.rmi.server.RemoteRef; import java.rmi.server.RemoteStub; import java.rmi.server.Skeleton; import java.rmi.server.SkeletonNotFoundException; -import java.security.AccessController; import java.security.MessageDigest; import java.security.DigestOutputStream; import java.security.NoSuchAlgorithmException; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; -import sun.rmi.registry.RegistryImpl; import sun.rmi.runtime.Log; -import sun.rmi.transport.LiveRef; -import sun.rmi.transport.tcp.TCPEndpoint; /** * A utility class with static methods for creating stubs/proxies and @@ -66,20 +58,15 @@ public final class Util { /** "server" package log level */ - @SuppressWarnings("removal") - static final int logLevel = LogStream.parseLevel( - AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("sun.rmi.server.logLevel"))); + static final int logLevel = LogStream.parseLevel(System.getProperty("sun.rmi.server.logLevel")); /** server reference log */ public static final Log serverRefLog = Log.getLog("sun.rmi.server.ref", "transport", Util.logLevel); /** cached value of property java.rmi.server.ignoreStubClasses */ - @SuppressWarnings("removal") private static final boolean ignoreStubClasses = - AccessController.doPrivileged( - (PrivilegedAction) () -> Boolean.getBoolean("java.rmi.server.ignoreStubClasses")); + Boolean.getBoolean("java.rmi.server.ignoreStubClasses"); /** cache of impl classes that have no corresponding stub class */ private static final Map, Void> withoutStubs = @@ -120,7 +107,6 @@ private Util() { * @throws StubNotFoundException if problem locating/creating stub or * creating the dynamic proxy instance **/ - @SuppressWarnings("removal") public static Remote createProxy(Class implClass, RemoteRef clientRef, boolean forceStubUse) @@ -150,12 +136,7 @@ public static Remote createProxy(Class implClass, /* REMIND: private remote interfaces? */ try { - return AccessController.doPrivileged(new PrivilegedAction() { - public Remote run() { - return (Remote) Proxy.newProxyInstance(loader, - interfaces, - handler); - }}); + return (Remote) Proxy.newProxyInstance(loader, interfaces, handler); } catch (IllegalArgumentException e) { throw new StubNotFoundException("unable to create proxy", e); } diff --git a/src/java.rmi/share/classes/sun/rmi/transport/DGCAckHandler.java b/src/java.rmi/share/classes/sun/rmi/transport/DGCAckHandler.java index d02b500f2a3..4004a23fff7 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/DGCAckHandler.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/DGCAckHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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,8 +26,6 @@ package sun.rmi.transport; import java.rmi.server.UID; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -64,16 +62,12 @@ public class DGCAckHandler { /** timeout for holding references without receiving an acknowledgment */ - @SuppressWarnings("removal") private static final long dgcAckTimeout = // default 5 minutes - AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("sun.rmi.dgc.ackTimeout", 300000)); + Long.getLong("sun.rmi.dgc.ackTimeout", 300000); /** thread pool for scheduling delayed tasks */ - @SuppressWarnings("removal") private static final ScheduledExecutorService scheduler = - AccessController.doPrivileged( - new RuntimeUtil.GetInstanceAction()).getScheduler(); + RuntimeUtil.getInstance().getScheduler(); /** table mapping ack ID to handler */ private static final Map idTable = diff --git a/src/java.rmi/share/classes/sun/rmi/transport/DGCClient.java b/src/java.rmi/share/classes/sun/rmi/transport/DGCClient.java index 7185f46201f..6bf0248f529 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/DGCClient.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/DGCClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -27,17 +27,13 @@ import java.io.InvalidClassException; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; -import java.net.SocketPermission; import java.rmi.UnmarshalException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.rmi.ConnectException; import java.rmi.RemoteException; import java.rmi.dgc.DGC; import java.rmi.dgc.Lease; @@ -49,10 +45,6 @@ import sun.rmi.server.UnicastRef; import sun.rmi.server.Util; -import java.security.AccessControlContext; -import java.security.Permissions; -import java.security.ProtectionDomain; - /** * DGCClient implements the client-side of the RMI distributed garbage * collection system. @@ -91,22 +83,16 @@ final class DGCClient { private static VMID vmid = new VMID(); /** lease duration to request (usually ignored by server) */ - @SuppressWarnings("removal") private static final long leaseValue = // default 10 minutes - AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("java.rmi.dgc.leaseValue", 600000)); + Long.getLong("java.rmi.dgc.leaseValue", 600000); /** maximum interval between retries of failed clean calls */ - @SuppressWarnings("removal") private static final long cleanInterval = // default 3 minutes - AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("sun.rmi.dgc.cleanInterval", 180000)); + Long.getLong("sun.rmi.dgc.cleanInterval", 180000); /** maximum interval between complete garbage collections of local heap */ - @SuppressWarnings("removal") private static final long gcInterval = // default 1 hour - AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("sun.rmi.dgc.client.gcInterval", 3600000)); + Long.getLong("sun.rmi.dgc.client.gcInterval", 3600000); /** minimum retry count for dirty calls that fail */ private static final int dirtyFailureRetries = 5; @@ -120,21 +106,6 @@ final class DGCClient { /** ObjID for server-side DGC object */ private static final ObjID dgcID = new ObjID(ObjID.DGC_ID); - /** - * An AccessControlContext with only socket permissions, - * suitable for an RMIClientSocketFactory. - */ - @SuppressWarnings("removal") - private static final AccessControlContext SOCKET_ACC = createSocketAcc(); - - @SuppressWarnings("removal") - private static AccessControlContext createSocketAcc() { - Permissions perms = new Permissions(); - perms.add(new SocketPermission("*", "connect,resolve")); - ProtectionDomain[] pd = { new ProtectionDomain(null, perms) }; - return new AccessControlContext(pd); - } - /* * Disallow anyone from creating one of these. */ @@ -256,7 +227,6 @@ public static EndpointEntry lookup(Endpoint ep) { } } - @SuppressWarnings("removal") private EndpointEntry(final Endpoint endpoint) { this.endpoint = endpoint; try { @@ -266,9 +236,9 @@ private EndpointEntry(final Endpoint endpoint) { } catch (RemoteException e) { throw new Error("internal error creating DGC stub"); } - renewCleanThread = AccessController.doPrivileged( + renewCleanThread = new NewThreadAction(new RenewCleanThread(), - "RenewClean-" + endpoint, true)); + "RenewClean-" + endpoint, true).run(); renewCleanThread.start(); } @@ -496,20 +466,13 @@ private void makeDirtyCall(Set refEntries, long sequenceNum) { * * This method must ONLY be called while synchronized on this entry. */ - @SuppressWarnings("removal") private void setRenewTime(long newRenewTime) { assert Thread.holdsLock(this); if (newRenewTime < renewTime) { renewTime = newRenewTime; if (interruptible) { - AccessController.doPrivileged( - new PrivilegedAction() { - public Void run() { - renewCleanThread.interrupt(); - return null; - } - }); + renewCleanThread.interrupt(); } } else { renewTime = newRenewTime; @@ -522,7 +485,6 @@ public Void run() { */ private class RenewCleanThread implements Runnable { - @SuppressWarnings("removal") public void run() { do { long timeToWait; @@ -601,19 +563,13 @@ public void run() { } } - boolean needRenewal_ = needRenewal; - Set refsToDirty_ = refsToDirty; - long sequenceNum_ = sequenceNum; - AccessController.doPrivileged((PrivilegedAction)() -> { - if (needRenewal_) { - makeDirtyCall(refsToDirty_, sequenceNum_); - } + if (needRenewal) { + makeDirtyCall(refsToDirty, sequenceNum); + } - if (!pendingCleans.isEmpty()) { - makeCleanCalls(); - } - return null; - }, SOCKET_ACC); + if (!pendingCleans.isEmpty()) { + makeCleanCalls(); + } } while (!removed || !pendingCleans.isEmpty()); } } diff --git a/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl.java b/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl.java index ba73610b441..08c2eda4045 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.rmi.transport; import java.io.ObjectInputFilter; -import java.net.SocketPermission; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.dgc.DGC; @@ -36,11 +35,6 @@ import java.rmi.server.RemoteServer; import java.rmi.server.ServerNotActiveException; import java.rmi.server.UID; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permissions; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; import java.security.Security; import java.util.ArrayList; import java.util.HashSet; @@ -68,28 +62,20 @@ final class DGCImpl implements DGC { /* dgc system log */ - @SuppressWarnings("removal") static final Log dgcLog = Log.getLog("sun.rmi.dgc", "dgc", - LogStream.parseLevel(AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("sun.rmi.dgc.logLevel")))); + LogStream.parseLevel(System.getProperty("sun.rmi.dgc.logLevel"))); /** lease duration to grant to clients */ - @SuppressWarnings("removal") private static final long leaseValue = // default 10 minutes - AccessController.doPrivileged( - (PrivilegedAction) () -> Long.getLong("java.rmi.dgc.leaseValue", 600000)); + Long.getLong("java.rmi.dgc.leaseValue", 600000); /** lease check interval; default is half of lease grant duration */ - @SuppressWarnings("removal") private static final long leaseCheckInterval = - AccessController.doPrivileged( - (PrivilegedAction) () -> Long.getLong("sun.rmi.dgc.checkInterval", leaseValue / 2)); + Long.getLong("sun.rmi.dgc.checkInterval", leaseValue / 2); /** thread pool for scheduling delayed tasks */ - @SuppressWarnings("removal") private static final ScheduledExecutorService scheduler = - AccessController.doPrivileged( - new RuntimeUtil.GetInstanceAction()).getScheduler(); + RuntimeUtil.getInstance().getScheduler(); /** remote implementation of DGC interface for this VM */ private static DGCImpl dgc; @@ -124,9 +110,7 @@ static DGCImpl getDGCImpl() { * The dgcFilter created from the value of the {@code "sun.rmi.transport.dgcFilter"} * property. */ - @SuppressWarnings("removal") - private static final ObjectInputFilter dgcFilter = - AccessController.doPrivileged((PrivilegedAction)DGCImpl::initDgcFilter); + private static final ObjectInputFilter dgcFilter = initDgcFilter(); /** * Initialize the dgcFilter from the security properties or system property; if any @@ -323,59 +307,35 @@ private void checkLeases() { exportSingleton(); } - @SuppressWarnings("removal") private static void exportSingleton() { /* * "Export" the singleton DGCImpl in a context isolated from * the arbitrary current thread context. */ - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - ClassLoader savedCcl = - Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader( - ClassLoader.getSystemClassLoader()); - - /* - * Put remote collector object in table by hand to prevent - * listen on port. (UnicastServerRef.exportObject would - * cause transport to listen.) - */ - try { - dgc = new DGCImpl(); - ObjID dgcID = new ObjID(ObjID.DGC_ID); - LiveRef ref = new LiveRef(dgcID, 0); - UnicastServerRef disp = new UnicastServerRef(ref, - DGCImpl::checkInput); - Remote stub = - Util.createProxy(DGCImpl.class, - new UnicastRef(ref), true); - disp.setSkeleton(dgc); - - Permissions perms = new Permissions(); - perms.add(new SocketPermission("*", "accept,resolve")); - ProtectionDomain[] pd = { new ProtectionDomain(null, perms) }; - AccessControlContext acceptAcc = new AccessControlContext(pd); - - Target target = AccessController.doPrivileged( - new PrivilegedAction() { - public Target run() { - return new Target(dgc, disp, stub, dgcID, true); - } - }, acceptAcc); - - ObjectTable.putTarget(target); - } catch (RemoteException e) { - throw new Error( - "exception initializing server-side DGC", e); - } - } finally { - Thread.currentThread().setContextClassLoader(savedCcl); - } - return null; + ClassLoader savedCcl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); + + /* + * Put remote collector object in table by hand to prevent + * listen on port. (UnicastServerRef.exportObject would + * cause transport to listen.) + */ + try { + dgc = new DGCImpl(); + ObjID dgcID = new ObjID(ObjID.DGC_ID); + LiveRef ref = new LiveRef(dgcID, 0); + UnicastServerRef disp = new UnicastServerRef(ref, DGCImpl::checkInput); + Remote stub = Util.createProxy(DGCImpl.class, new UnicastRef(ref), true); + disp.setSkeleton(dgc); + Target target = new Target(dgc, disp, stub, dgcID, true); + ObjectTable.putTarget(target); + } catch (RemoteException e) { + throw new Error("exception initializing server-side DGC", e); } - }); + } finally { + Thread.currentThread().setContextClassLoader(savedCcl); + } } /** diff --git a/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Stub.java b/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Stub.java index 99880f3b3b0..c16ee9870b2 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Stub.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl_Stub.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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 @@ -33,8 +33,6 @@ import java.rmi.dgc.Lease; import java.rmi.dgc.VMID; import java.rmi.server.UID; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; /** diff --git a/src/java.rmi/share/classes/sun/rmi/transport/GC.java b/src/java.rmi/share/classes/sun/rmi/transport/GC.java index 4bd50511dd4..9c76a98b955 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/GC.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/GC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package sun.rmi.transport; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.SortedSet; import java.util.TreeSet; import jdk.internal.misc.InnocuousThread; @@ -39,7 +37,7 @@ * @since 1.2 */ -@SuppressWarnings({"removal", "restricted"}) +@SuppressWarnings("restricted") class GC { private GC() { } /* To prevent instantiation */ @@ -85,11 +83,7 @@ private static class LatencyLock extends Object { }; public static native long maxObjectInspectionAge(); static { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - System.loadLibrary("rmi"); - return null; - }}); + System.loadLibrary("rmi"); } private static class Daemon implements Runnable { @@ -134,18 +128,12 @@ public void run() { /* Create a new daemon thread */ public static void create() { - PrivilegedAction pa = new PrivilegedAction() { - public Void run() { - Thread t = InnocuousThread.newSystemThread("RMI GC Daemon", - new Daemon()); - assert t.getContextClassLoader() == null; - t.setDaemon(true); - t.setPriority(Thread.MIN_PRIORITY + 1); - t.start(); - GC.daemon = t; - return null; - }}; - AccessController.doPrivileged(pa); + Thread t = InnocuousThread.newSystemThread("RMI GC Daemon", new Daemon()); + assert t.getContextClassLoader() == null; + t.setDaemon(true); + t.setPriority(Thread.MIN_PRIORITY + 1); + t.start(); + GC.daemon = t; } } diff --git a/src/java.rmi/share/classes/sun/rmi/transport/ObjectTable.java b/src/java.rmi/share/classes/sun/rmi/transport/ObjectTable.java index d01256f5533..dd1fcaddeab 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/ObjectTable.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/ObjectTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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,8 +30,6 @@ import java.rmi.dgc.VMID; import java.rmi.server.ExportException; import java.rmi.server.ObjID; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; import sun.rmi.runtime.Log; @@ -48,10 +46,8 @@ public final class ObjectTable { /** maximum interval between complete garbage collections of local heap */ - @SuppressWarnings("removal") private static final long gcInterval = // default 1 hour - AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("sun.rmi.dgc.server.gcInterval", 3600000)); + Long.getLong("sun.rmi.dgc.server.gcInterval", 3600000); /** * lock guarding objTable and implTable. @@ -270,14 +266,12 @@ static void unreferenced(ObjID id, long sequenceNum, VMID vmid, * thread operates, the reaper thread also serves as the non-daemon * VM keep-alive thread; a new reaper thread is created if necessary. */ - @SuppressWarnings("removal") static void incrementKeepAliveCount() { synchronized (keepAliveLock) { keepAliveCount++; if (reaper == null) { - reaper = AccessController.doPrivileged( - new NewThreadAction(new Reaper(), "Reaper", false)); + reaper = new NewThreadAction(new Reaper(), "Reaper", false).run(); reaper.start(); } @@ -307,19 +301,13 @@ static void incrementKeepAliveCount() { * reaper thread is terminated to cease keeping the VM alive (and * because there are no more non-permanent remote objects to reap). */ - @SuppressWarnings("removal") static void decrementKeepAliveCount() { synchronized (keepAliveLock) { keepAliveCount--; if (keepAliveCount == 0) { if (!(reaper != null)) { throw new AssertionError(); } - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - reaper.interrupt(); - return null; - } - }); + reaper.interrupt(); reaper = null; /* diff --git a/src/java.rmi/share/classes/sun/rmi/transport/StreamRemoteCall.java b/src/java.rmi/share/classes/sun/rmi/transport/StreamRemoteCall.java index 8df144d086d..0cff2c33ce9 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/StreamRemoteCall.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/StreamRemoteCall.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,8 +37,6 @@ import java.rmi.UnmarshalException; import java.rmi.server.ObjID; import java.rmi.server.RemoteCall; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.rmi.runtime.Log; import sun.rmi.server.UnicastRef; @@ -139,17 +137,13 @@ public void setObjectInputFilter(ObjectInputFilter filter) { * Get the InputStream the stub/skeleton should get results/arguments * from. */ - @SuppressWarnings("removal") public ObjectInput getInputStream() throws IOException { if (in == null) { Transport.transportLog.log(Log.VERBOSE, "getting input stream"); in = new ConnectionInputStream(conn.getInputStream()); if (filter != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - in.setObjectInputFilter(filter); - return null; - }); + in.setObjectInputFilter(filter); } } return in; diff --git a/src/java.rmi/share/classes/sun/rmi/transport/Target.java b/src/java.rmi/share/classes/sun/rmi/transport/Target.java index c0d79bb38e2..3ea404698f2 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/Target.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/Target.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +29,6 @@ import java.rmi.dgc.VMID; import java.rmi.server.ObjID; import java.rmi.server.Unreferenced; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.*; import sun.rmi.runtime.Log; import sun.rmi.runtime.NewThreadAction; @@ -58,9 +55,6 @@ public final class Target { /** table that maps client endpoints to sequence numbers */ private final Hashtable sequenceTable = new Hashtable<>(5); - /** access control context in which target was created */ - @SuppressWarnings("removal") - private final AccessControlContext acc; /** context class loader in which target was created */ private final ClassLoader ccl; /** number of pending/executing calls */ @@ -86,7 +80,6 @@ public final class Target { * collection. Permanent objects do not keep a server from * exiting. */ - @SuppressWarnings("removal") public Target(Remote impl, Dispatcher disp, Remote stub, ObjID id, boolean permanent) { @@ -94,7 +87,6 @@ public Target(Remote impl, Dispatcher disp, Remote stub, ObjID id, this.disp = disp; this.stub = stub; this.id = id; - this.acc = AccessController.getContext(); /* * Fix for 4149366: so that downloaded parameter types unmarshalled @@ -177,11 +169,6 @@ Dispatcher getDispatcher() { return disp; } - @SuppressWarnings("removal") - AccessControlContext getAccessControlContext() { - return acc; - } - ClassLoader getContextClassLoader() { return ccl; } @@ -307,7 +294,6 @@ synchronized void unreferenced(long sequenceNum, VMID vmid, boolean strong) /** * Remove endpoint from the reference set. */ - @SuppressWarnings("removal") private synchronized void refSetRemove(VMID vmid) { // remove notification request DGCImpl.getDGCImpl().unregisterTarget(vmid, this); @@ -325,17 +311,12 @@ private synchronized void refSetRemove(VMID vmid) { * invoke its unreferenced callback in a separate thread. */ Remote obj = getImpl(); - if (obj instanceof Unreferenced) { - final Unreferenced unrefObj = (Unreferenced) obj; - AccessController.doPrivileged( - new NewThreadAction(() -> { - Thread.currentThread().setContextClassLoader(ccl); - AccessController.doPrivileged((PrivilegedAction) () -> { - unrefObj.unreferenced(); - return null; - }, acc); - }, "Unreferenced-" + nextThreadNum++, false, true)).start(); - // REMIND: access to nextThreadNum not synchronized; you care? + if (obj instanceof Unreferenced unrefObj) { + new NewThreadAction(() -> { + Thread.currentThread().setContextClassLoader(ccl); + unrefObj.unreferenced(); + }, "Unreferenced-" + nextThreadNum++, false, true).run().start(); + // REMIND: access to nextThreadNum not synchronized; you care? } unpinImpl(); diff --git a/src/java.rmi/share/classes/sun/rmi/transport/Transport.java b/src/java.rmi/share/classes/sun/rmi/transport/Transport.java index 4589f913dd3..b6174517180 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/Transport.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/Transport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -36,11 +36,6 @@ import java.rmi.server.RemoteCall; import java.rmi.server.RemoteServer; import java.rmi.server.ServerNotActiveException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permissions; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; import sun.rmi.runtime.Log; import sun.rmi.server.Dispatcher; import sun.rmi.server.UnicastServerRef; @@ -51,15 +46,14 @@ * * @author Ann Wollrath */ -@SuppressWarnings({"removal","deprecation"}) +@SuppressWarnings({"deprecation"}) public abstract class Transport { /** "transport" package log level */ static final int logLevel = LogStream.parseLevel(getLogLevel()); private static String getLogLevel() { - return java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("sun.rmi.transport.logLevel")); + return System.getProperty("sun.rmi.transport.logLevel"); } /* transport package log */ @@ -72,15 +66,6 @@ private static String getLogLevel() { /** ObjID for DGCImpl */ private static final ObjID dgcID = new ObjID(ObjID.DGC_ID); - /** AccessControlContext for setting context ClassLoader */ - private static final AccessControlContext SETCCL_ACC; - static { - Permissions perms = new Permissions(); - perms.add(new RuntimePermission("setContextClassLoader")); - ProtectionDomain[] pd = { new ProtectionDomain(null, perms) }; - SETCCL_ACC = new AccessControlContext(pd); - } - /** * Returns a Channel that generates connections to the * endpoint ep. A Channel is an object that creates and @@ -121,22 +106,11 @@ static Transport currentTransport() { return currentTransport.get(); } - /** - * Verify that the current access control context has permission to accept - * the connection being dispatched by the current thread. The current - * access control context is passed as a parameter to avoid the overhead of - * an additional call to AccessController.getContext. - */ - protected abstract void checkAcceptPermission(AccessControlContext acc); - /** * Sets the context class loader for the current thread. */ private static void setContextClassLoader(ClassLoader ccl) { - AccessController.doPrivileged((PrivilegedAction)() -> { - Thread.currentThread().setContextClassLoader(ccl); - return null; - }, SETCCL_ACC); + Thread.currentThread().setContextClassLoader(ccl); } /** @@ -183,27 +157,13 @@ public boolean serviceCall(final RemoteCall call) { /* call the dispatcher */ transportLog.log(Log.VERBOSE, "call dispatcher"); - final AccessControlContext acc = - target.getAccessControlContext(); ClassLoader ccl = target.getContextClassLoader(); - ClassLoader savedCcl = Thread.currentThread().getContextClassLoader(); try { if (ccl != savedCcl) setContextClassLoader(ccl); currentTransport.set(this); - try { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Void run() throws IOException { - checkAcceptPermission(acc); - disp.dispatch(impl, call); - return null; - } - }, acc); - } catch (java.security.PrivilegedActionException pae) { - throw (IOException) pae.getException(); - } + disp.dispatch(impl, call); } finally { if (ccl != savedCcl) setContextClassLoader(savedCcl); currentTransport.set(null); diff --git a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java index 013fc1606af..91ef41d3e49 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -27,18 +27,12 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; import java.net.Socket; import java.rmi.ConnectIOException; import java.rmi.RemoteException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; -import java.util.WeakHashMap; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -70,42 +64,21 @@ public class TCPChannel implements Channel { /** connection acceptor (should be in TCPTransport) */ private ConnectionAcceptor acceptor; - /** most recently authorized AccessControlContext */ - @SuppressWarnings("removal") - private AccessControlContext okContext; - - /** cache of authorized AccessControlContexts */ - @SuppressWarnings("removal") - private WeakHashMap> authcache; - - /** the SecurityManager which authorized okContext and authcache */ - @SuppressWarnings("removal") - private SecurityManager cacheSecurityManager = null; - /** client-side connection idle usage timeout */ - @SuppressWarnings("removal") private static final long idleTimeout = // default 15 seconds - AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("sun.rmi.transport.connectionTimeout", 15000)); + Long.getLong("sun.rmi.transport.connectionTimeout", 15000); /** client-side connection handshake read timeout */ - @SuppressWarnings("removal") private static final int handshakeTimeout = // default 1 minute - AccessController.doPrivileged((PrivilegedAction) () -> - Integer.getInteger("sun.rmi.transport.tcp.handshakeTimeout", 60000)); + Integer.getInteger("sun.rmi.transport.tcp.handshakeTimeout", 60000); /** client-side connection response read timeout (after handshake) */ - @SuppressWarnings("removal") private static final int responseTimeout = // default infinity - AccessController.doPrivileged((PrivilegedAction) () -> - Integer.getInteger("sun.rmi.transport.tcp.responseTimeout", 0)); + Integer.getInteger("sun.rmi.transport.tcp.responseTimeout", 0); /** thread pool for scheduling delayed tasks */ - @SuppressWarnings("removal") private static final ScheduledExecutorService scheduler = - AccessController.doPrivileged( - new RuntimeUtil.GetInstanceAction()).getScheduler(); + RuntimeUtil.getInstance().getScheduler(); /** * Create channel for endpoint. @@ -122,41 +95,6 @@ public Endpoint getEndpoint() { return ep; } - /** - * Checks if the current caller has sufficient privilege to make - * a connection to the remote endpoint. - * @exception SecurityException if caller is not allowed to use this - * Channel. - */ - @SuppressWarnings("removal") - private void checkConnectPermission() throws SecurityException { - SecurityManager security = System.getSecurityManager(); - if (security == null) - return; - - if (security != cacheSecurityManager) { - // The security manager changed: flush the cache - okContext = null; - authcache = new WeakHashMap>(); - cacheSecurityManager = security; - } - - AccessControlContext ctx = AccessController.getContext(); - - // If ctx is the same context as last time, or if it - // appears in the cache, bypass the checkConnect. - if (okContext == null || - !(okContext.equals(ctx) || authcache.containsKey(ctx))) - { - security.checkConnect(ep.getHost(), ep.getPort()); - authcache.put(ctx, new SoftReference(ctx)); - // A WeakHashMap is transformed into a SoftHashSet by making - // each value softly refer to its own key (Peter's idea). - } - okContext = ctx; - } - /** * Supplies a connection to the endpoint of the address space * for which this is a channel. The returned connection may @@ -175,10 +113,6 @@ public Connection newConnection() throws RemoteException { int elementPos = freeList.size()-1; if (elementPos >= 0) { - // If there is a security manager, make sure - // the caller is allowed to connect to the - // requested endpoint. - checkConnectPermission(); conn = freeList.get(elementPos); freeList.remove(elementPos); } @@ -467,11 +401,9 @@ public ConnectionAcceptor(TCPTransport transport) { * Start a new thread to accept connections. */ public void startNewAcceptor() { - @SuppressWarnings("removal") - Thread t = AccessController.doPrivileged( - new NewThreadAction(ConnectionAcceptor.this, - "TCPChannel Accept-" + ++ threadNum, - true)); + Thread t = new NewThreadAction(ConnectionAcceptor.this, + "TCPChannel Accept-" + ++ threadNum, + true).run(); t.start(); } diff --git a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPEndpoint.java b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPEndpoint.java index b2c0f189845..4eb1a35a95e 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPEndpoint.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,6 @@ import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.RMISocketFactory; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -79,27 +77,19 @@ public class TCPEndpoint implements Endpoint { /** true if real local host name is known yet */ private static boolean localHostKnown; - // this should be a *private* method since it is privileged - @SuppressWarnings("removal") private static int getInt(String name, int def) { - return AccessController.doPrivileged( - (PrivilegedAction) () -> Integer.getInteger(name, def)); + return Integer.getInteger(name, def); } - // this should be a *private* method since it is privileged - @SuppressWarnings("removal") private static boolean getBoolean(String name) { - return AccessController.doPrivileged( - (PrivilegedAction) () -> Boolean.getBoolean(name)); + return Boolean.getBoolean(name); } /** * Returns the value of the java.rmi.server.hostname property. */ - @SuppressWarnings("removal") private static String getHostnameProperty() { - return AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("java.rmi.server.hostname")); + return System.getProperty("java.rmi.server.hostname"); } /** @@ -762,9 +752,7 @@ static String attemptFQDN(InetAddress localAddr) private void getFQDN() { /* FQDN finder will run in RMI threadgroup. */ - @SuppressWarnings("removal") - Thread t = AccessController.doPrivileged( - new NewThreadAction(FQDN.this, "FQDN Finder", true)); + Thread t = new NewThreadAction(FQDN.this, "FQDN Finder", true).run(); t.start(); } diff --git a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java index dba0f9f8f60..9695fcac274 100644 --- a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java +++ b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.rmi.transport.tcp; import java.lang.ref.Reference; -import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.UndeclaredThrowableException; @@ -47,11 +46,6 @@ import java.rmi.server.RemoteCall; import java.rmi.server.ServerNotActiveException; import java.rmi.server.UID; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permissions; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -67,7 +61,6 @@ import java.util.concurrent.atomic.AtomicInteger; import sun.rmi.runtime.Log; import sun.rmi.runtime.NewThreadAction; -import sun.rmi.transport.Channel; import sun.rmi.transport.Connection; import sun.rmi.transport.DGCAckHandler; import sun.rmi.transport.Endpoint; @@ -87,23 +80,16 @@ public class TCPTransport extends Transport { /* tcp package log */ - @SuppressWarnings("removal") static final Log tcpLog = Log.getLog("sun.rmi.transport.tcp", "tcp", - LogStream.parseLevel(AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("sun.rmi.transport.tcp.logLevel")))); + LogStream.parseLevel(System.getProperty("sun.rmi.transport.tcp.logLevel"))); /** maximum number of connection handler threads */ - @SuppressWarnings("removal") private static final int maxConnectionThreads = // default no limit - AccessController.doPrivileged((PrivilegedAction) () -> - Integer.getInteger("sun.rmi.transport.tcp.maxConnectionThreads", - Integer.MAX_VALUE)); + Integer.getInteger("sun.rmi.transport.tcp.maxConnectionThreads", Integer.MAX_VALUE); /** keep alive time for idle connection handler threads */ - @SuppressWarnings("removal") private static final long threadKeepAliveTime = // default 1 minute - AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("sun.rmi.transport.tcp.threadKeepAliveTime", 60000)); + Long.getLong("sun.rmi.transport.tcp.threadKeepAliveTime", 60000); /** thread pool for connection handlers */ private static final ExecutorService connectionThreadPool = @@ -111,10 +97,9 @@ public class TCPTransport extends Transport { threadKeepAliveTime, TimeUnit.MILLISECONDS, new SynchronousQueue(), new ThreadFactory() { - @SuppressWarnings("removal") public Thread newThread(Runnable runnable) { - return AccessController.doPrivileged(new NewThreadAction( - runnable, "TCP Connection(idle)", true, true)); + return new NewThreadAction( + runnable, "TCP Connection(idle)", true, true).run(); } }); @@ -125,17 +110,6 @@ public Thread newThread(Runnable runnable) { private static final ThreadLocal threadConnectionHandler = new ThreadLocal<>(); - /** an AccessControlContext with no permissions */ - @SuppressWarnings("removal") - private static final AccessControlContext NOPERMS_ACC = createNopermsAcc(); - - @SuppressWarnings("removal") - private static AccessControlContext createNopermsAcc() { - Permissions perms = new Permissions(); - ProtectionDomain[] pd = { new ProtectionDomain(null, perms) }; - return new AccessControlContext(pd); - } - /** endpoints for this transport */ private final LinkedList epList; /** number of objects exported on this transport */ @@ -149,16 +123,15 @@ private static AccessControlContext createNopermsAcc() { static final RMISocketFactory defaultSocketFactory = RMISocketFactory.getDefaultSocketFactory(); - /** number of milliseconds in accepted-connection timeout. + /** + * Number of milliseconds in accepted-connection timeout. * Warning: this should be greater than 15 seconds (the client-side * timeout), and defaults to 2 hours. * The maximum representable value is slightly more than 24 days * and 20 hours. */ - @SuppressWarnings("removal") private static final int connectionReadTimeout = // default 2 hours - AccessController.doPrivileged((PrivilegedAction) () -> - Integer.getInteger("sun.rmi.transport.tcp.readTimeout", 2 * 3600 * 1000)); + Integer.getInteger("sun.rmi.transport.tcp.readTimeout", 2 * 3600 * 1000); /** * Constructs a TCPTransport. @@ -302,24 +275,6 @@ private void decrementExportCount() { } } - /** - * Verify that the current access control context has permission to - * accept the connection being dispatched by the current thread. - */ - protected void checkAcceptPermission(@SuppressWarnings("removal") AccessControlContext acc) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - ConnectionHandler h = threadConnectionHandler.get(); - if (h == null) { - throw new Error( - "checkAcceptPermission not in ConnectionHandler thread"); - } - h.checkAcceptPermission(sm, acc); - } - private TCPEndpoint getEndpoint() { synchronized (epList) { return epList.getLast(); @@ -327,7 +282,8 @@ private TCPEndpoint getEndpoint() { } /** - * Listen on transport's endpoint. + * Listen on transport's endpoint. Do nothing if a server socket + * and listening thread already exist. */ private void listen() throws RemoteException { assert Thread.holdsLock(this); @@ -347,24 +303,14 @@ private void listen() throws RemoteException { * "port in use" will cause export to hang if an * RMIFailureHandler is not installed. */ - @SuppressWarnings("removal") - Thread t = AccessController.doPrivileged( - new NewThreadAction(new AcceptLoop(server), - "TCP Accept-" + port, true)); + Thread t = new NewThreadAction(new AcceptLoop(server), + "TCP Accept-" + port, true).run(); t.start(); } catch (java.net.BindException e) { throw new ExportException("Port already in use: " + port, e); } catch (IOException e) { throw new ExportException("Listen failed on port: " + port, e); } - - } else { - // otherwise verify security access to existing server socket - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkListen(port); - } } } @@ -656,17 +602,6 @@ private class ConnectionHandler implements Runnable { * make this once-reviled tactic again socially acceptable) */ private static final int POST = 0x504f5354; - /** most recently accept-authorized AccessControlContext */ - @SuppressWarnings("removal") - private AccessControlContext okContext; - /** cache of accept-authorized AccessControlContexts */ - @SuppressWarnings("removal") - private Map> authCache; - /** security manager which authorized contexts in authCache */ - @SuppressWarnings("removal") - private SecurityManager cacheSecurityManager = null; - private Socket socket; private String remoteHost; @@ -679,37 +614,6 @@ String getClientHost() { return remoteHost; } - /** - * Verify that the given AccessControlContext has permission to - * accept this connection. - */ - @SuppressWarnings("removal") - void checkAcceptPermission(SecurityManager sm, - AccessControlContext acc) - { - /* - * Note: no need to synchronize on cache-related fields, since this - * method only gets called from the ConnectionHandler's thread. - */ - if (sm != cacheSecurityManager) { - okContext = null; - authCache = new WeakHashMap>(); - cacheSecurityManager = sm; - } - if (acc.equals(okContext) || authCache.containsKey(acc)) { - return; - } - InetAddress addr = socket.getInetAddress(); - String host = (addr != null) ? addr.getHostAddress() : "*"; - - sm.checkAccept(host, socket.getPort()); - - authCache.put(acc, new SoftReference(acc)); - okContext = acc; - } - - @SuppressWarnings("removal") public void run() { Thread t = Thread.currentThread(); String name = t.getName(); @@ -717,10 +621,7 @@ public void run() { t.setName("RMI TCP Connection(" + connectionCount.incrementAndGet() + ")-" + remoteHost); - AccessController.doPrivileged((PrivilegedAction)() -> { - run0(); - return null; - }, NOPERMS_ACC); + run0(); } finally { t.setName(name); } diff --git a/src/java.rmi/share/man/rmiregistry.1 b/src/java.rmi/share/man/rmiregistry.1 deleted file mode 100644 index c168e1482a6..00000000000 --- a/src/java.rmi/share/man/rmiregistry.1 +++ /dev/null @@ -1,100 +0,0 @@ -.\" Copyright (c) 1997, 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 -.\" 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "RMIREGISTRY" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -rmiregistry - create and start a remote object registry on the specified -port on the current host -.SH SYNOPSIS -.PP -\f[V]rmiregistry\f[R] [\f[I]options\f[R]] [\f[I]port\f[R]] -.TP -\f[I]options\f[R] -This represents the option for the \f[V]rmiregistry\f[R] command. -See \f[B]Options\f[R] -.TP -\f[I]port\f[R] -The number of a port on the current host at which to start the remote -object registry. -.SH DESCRIPTION -.PP -The \f[V]rmiregistry\f[R] command creates and starts a remote object -registry on the specified port on the current host. -If the port is omitted, then the registry is started on port 1099. -The \f[V]rmiregistry\f[R] command produces no output and is typically -run in the background, for example: -.RS -.PP -\f[V]rmiregistry &\f[R] -.RE -.PP -A remote object registry is a bootstrap naming service that\[aq]s used -by RMI servers on the same host to bind remote objects to names. -Clients on local and remote hosts can then look up remote objects and -make remote method invocations. -.PP -The registry is typically used to locate the first remote object on -which an application needs to call methods. -That object then provides application-specific support for finding other -objects. -.PP -The methods of the \f[V]java.rmi.registry.LocateRegistry\f[R] class are -used to get a registry operating on the local host or local host and -port. -.PP -The URL-based methods of the \f[V]java.rmi.Naming\f[R] class operate on -a registry and can be used to: -.IP \[bu] 2 -Bind the specified name to a remote object -.IP \[bu] 2 -Return an array of the names bound in the registry -.IP \[bu] 2 -Return a reference, a stub, for the remote object associated with the -specified name -.IP \[bu] 2 -Rebind the specified name to a new remote object -.IP \[bu] 2 -Destroy the binding for the specified name that\[aq]s associated with a -remote object -.SH OPTIONS -.TP -\f[V]-J\f[R]\f[I]option\f[R] -Used with any Java option to pass the \f[I]option\f[R] following the -\f[V]-J\f[R] (no spaces between the \f[V]-J\f[R] and the option) to the -Java interpreter. diff --git a/src/java.rmi/share/man/rmiregistry.md b/src/java.rmi/share/man/rmiregistry.md new file mode 100644 index 00000000000..48c426cfbdc --- /dev/null +++ b/src/java.rmi/share/man/rmiregistry.md @@ -0,0 +1,86 @@ +--- +# Copyright (c) 1997, 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 +# 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. +# + +title: 'RMIREGISTRY(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +rmiregistry - create and start a remote object registry on the specified port +on the current host + +## Synopsis + +`rmiregistry` \[*options*\] \[*port*\] + +*options* +: This represents the option for the `rmiregistry` command. See + [Options] + +*port* +: The number of a port on the current host at which to start the remote + object registry. + +## Description + +The `rmiregistry` command creates and starts a remote object registry on the +specified port on the current host. If the port is omitted, then the registry +is started on port 1099. The `rmiregistry` command produces no output and is +typically run in the background, for example: + +> `rmiregistry &` + +A remote object registry is a bootstrap naming service that's used by RMI +servers on the same host to bind remote objects to names. Clients on local and +remote hosts can then look up remote objects and make remote method +invocations. + +The registry is typically used to locate the first remote object on which an +application needs to call methods. That object then provides +application-specific support for finding other objects. + +The methods of the `java.rmi.registry.LocateRegistry` class are used to get a +registry operating on the local host or local host and port. + +The URL-based methods of the `java.rmi.Naming` class operate on a registry and +can be used to: + +- Bind the specified name to a remote object + +- Return an array of the names bound in the registry + +- Return a reference, a stub, for the remote object associated with the + specified name + +- Rebind the specified name to a new remote object + +- Destroy the binding for the specified name that's associated with a remote + object + +## Options + +`-J`*option* +: Used with any Java option to pass the *option* following the `-J` (no + spaces between the `-J` and the option) to the Java interpreter. diff --git a/src/java.scripting/share/classes/javax/script/ScriptEngineManager.java b/src/java.scripting/share/classes/javax/script/ScriptEngineManager.java index 88f70fc5131..da4d761a853 100644 --- a/src/java.scripting/share/classes/javax/script/ScriptEngineManager.java +++ b/src/java.scripting/share/classes/javax/script/ScriptEngineManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package javax.script; import java.util.*; -import java.security.*; import java.util.ServiceLoader; import java.util.ServiceConfigurationError; import java.util.function.Function; @@ -87,10 +86,7 @@ private ServiceLoader getServiceLoader(final ClassLoader lo private void initEngines(final ClassLoader loader) { Iterator itr; try { - @SuppressWarnings("removal") - var sl = AccessController.doPrivileged( - (PrivilegedAction>)() -> getServiceLoader(loader)); - itr = sl.iterator(); + itr = getServiceLoader(loader).iterator(); } catch (ServiceConfigurationError err) { reportException("Can't find ScriptEngineFactory providers: ", err); // do not throw any exception here. user may want to diff --git a/src/java.scripting/share/man/jrunscript.1 b/src/java.scripting/share/man/jrunscript.1 deleted file mode 100644 index 491c3cb3be3..00000000000 --- a/src/java.scripting/share/man/jrunscript.1 +++ /dev/null @@ -1,166 +0,0 @@ -.\" Copyright (c) 2006, 2024, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JRUNSCRIPT" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jrunscript - run a command-line script shell that supports interactive -and batch modes -.SH SYNOPSIS -.PP -\f[B]Note:\f[R] -.PP -This tool is \f[B]experimental\f[R] and unsupported. -It is deprecated and will be removed in a future release. -.PP -\f[V]jrunscript\f[R] [\f[I]options\f[R]] [\f[I]arguments\f[R]] -.TP -\f[I]options\f[R] -This represents the \f[V]jrunscript\f[R] command-line options that can -be used. -See \f[B]Options for the jrunscript Command\f[R]. -.TP -\f[I]arguments\f[R] -Arguments, when used, follow immediately after options or the command -name. -See \f[B]Arguments\f[R]. -.SH DESCRIPTION -.PP -The \f[V]jrunscript\f[R] command is a language-independent command-line -script shell. -The \f[V]jrunscript\f[R] command supports both an interactive -(read-eval-print) mode and a batch (\f[V]-f\f[R] option) mode of script -execution. -By default, JavaScript is the language used, but the \f[V]-l\f[R] option -can be used to specify a different language. -By using Java to scripting language communication, the -\f[V]jrunscript\f[R] command supports an exploratory programming style. -.PP -If JavaScript is used, then before it evaluates a user defined script, -the \f[V]jrunscript\f[R] command initializes certain built-in functions -and objects, which are documented in the API Specification for -\f[V]jrunscript\f[R] JavaScript built-in functions. -.SH OPTIONS FOR THE JRUNSCRIPT COMMAND -.TP -\f[V]-cp\f[R] \f[I]path\f[R] or \f[V]-classpath\f[R] \f[I]path\f[R] -Indicates where any class files are that the script needs to access. -.TP -\f[V]-D\f[R]\f[I]name\f[R]\f[V]=\f[R]\f[I]value\f[R] -Sets a Java system property. -.TP -\f[V]-J\f[R]\f[I]flag\f[R] -Passes \f[I]flag\f[R] directly to the Java Virtual Machine where the -\f[V]jrunscript\f[R] command is running. -.TP -\f[V]-l\f[R] \f[I]language\f[R] -Uses the specified scripting language. -By default, JavaScript is used. -To use other scripting languages, you must specify the corresponding -script engine\[aq]s JAR file with the \f[V]-cp\f[R] or -\f[V]-classpath\f[R] option. -.TP -\f[V]-e\f[R] \f[I]script\f[R] -Evaluates the specified script. -This option can be used to run one-line scripts that are specified -completely on the command line. -.TP -\f[V]-encoding\f[R] \f[I]encoding\f[R] -Specifies the character encoding used to read script files. -.TP -\f[V]-f\f[R] \f[I]script-file\f[R] -Evaluates the specified script file (batch mode). -.TP -\f[V]-f -\f[R] -Enters interactive mode to read and evaluate a script from standard -input. -.TP -\f[V]-help\f[R] or \f[V]-?\f[R] -Displays a help message and exits. -.TP -\f[V]-q\f[R] -Lists all script engines available and exits. -.SH ARGUMENTS -.PP -If arguments are present and if no \f[V]-e\f[R] or \f[V]-f\f[R] option -is used, then the first argument is the script file and the rest of the -arguments, if any, are passed as script arguments. -If arguments and the \f[V]-e\f[R] or the \f[V]-f\f[R] option are used, -then all arguments are passed as script arguments. -If arguments \f[V]-e\f[R] and \f[V]-f\f[R] are missing, then the -interactive mode is used. -.SH EXAMPLE OF EXECUTING INLINE SCRIPTS -.RS -.PP -\f[V]jrunscript -e \[dq]print(\[aq]hello world\[aq])\[dq]\f[R] -.RE -.RS -.PP -\f[V]jrunscript -e \[dq]cat(\[aq]http://www.example.com\[aq])\[dq]\f[R] -.RE -.SH EXAMPLE OF USING SPECIFIED LANGUAGE AND EVALUATE THE SCRIPT FILE -.RS -.PP -\f[V]jrunscript -l js -f test.js\f[R] -.RE -.SH EXAMPLE OF INTERACTIVE MODE -.IP -.nf -\f[CB] -jrunscript -js> print(\[aq]Hello World\[rs]n\[aq]); -Hello World -js> 34 + 55 -89.0 -js> t = new java.lang.Thread(function() { print(\[aq]Hello World\[rs]n\[aq]); }) -Thread[Thread-0,5,main] -js> t.start() -js> Hello World - -js> -\f[R] -.fi -.SH RUN SCRIPT FILE WITH SCRIPT ARGUMENTS -.PP -In this example, the \f[V]test.js\f[R] file is the script file. -The \f[V]arg1\f[R], \f[V]arg2\f[R], and \f[V]arg3\f[R] arguments are -passed to the script. -The script can access these arguments with an arguments array. -.RS -.PP -\f[V]jrunscript test.js arg1 arg2 arg3\f[R] -.RE diff --git a/src/java.scripting/share/man/jrunscript.md b/src/java.scripting/share/man/jrunscript.md new file mode 100644 index 00000000000..85ace0c32ee --- /dev/null +++ b/src/java.scripting/share/man/jrunscript.md @@ -0,0 +1,141 @@ +--- +# Copyright (c) 2006, 2024, 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. +# + +title: 'JRUNSCRIPT(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jrunscript - run a command-line script shell that supports interactive and +batch modes + +## Synopsis + +**Note:** + +This tool is **experimental** and unsupported. It is deprecated and will be +removed in a future release. + +`jrunscript` \[*options*\] \[*arguments*\] + +*options* +: This represents the `jrunscript` command-line options that can be used. See + [Options for the jrunscript Command]. + +*arguments* +: Arguments, when used, follow immediately after options or the command name. + See [Arguments]. + +## Description + +The `jrunscript` command is a language-independent command-line script shell. +The `jrunscript` command supports both an interactive (read-eval-print) mode +and a batch (`-f` option) mode of script execution. By default, JavaScript is +the language used, but the `-l` option can be used to specify a different +language. By using Java to scripting language communication, the `jrunscript` +command supports an exploratory programming style. + +If JavaScript is used, then before it evaluates a user defined script, the +`jrunscript` command initializes certain built-in functions and objects, which +are documented in the API Specification for `jrunscript` JavaScript built-in +functions. + +## Options for the jrunscript Command + +`-cp` *path* or `-classpath` *path* +: Indicates where any class files are that the script needs to access. + +`-D`*name*`=`*value* +: Sets a Java system property. + +`-J`*flag* +: Passes *flag* directly to the Java Virtual Machine where the `jrunscript` + command is running. + +`-l` *language* +: Uses the specified scripting language. By default, JavaScript is used. To + use other scripting languages, you must specify the corresponding script + engine's JAR file with the `-cp` or `-classpath` option. + +`-e` *script* +: Evaluates the specified script. This option can be used to run one-line + scripts that are specified completely on the command line. + +`-encoding` *encoding* +: Specifies the character encoding used to read script files. + +`-f` *script-file* +: Evaluates the specified script file (batch mode). + +`-f -` +: Enters interactive mode to read and evaluate a script from standard input. + +`-help` or `-?` +: Displays a help message and exits. + +`-q` +: Lists all script engines available and exits. + +## Arguments + +If arguments are present and if no `-e` or `-f` option is used, then the first +argument is the script file and the rest of the arguments, if any, are passed +as script arguments. If arguments and the `-e` or the `-f` option are used, +then all arguments are passed as script arguments. If arguments `-e` and `-f` +are missing, then the interactive mode is used. + +## Example of Executing Inline Scripts + +> `jrunscript -e "print('hello world')"` + +> `jrunscript -e "cat('http://www.example.com')"` + +## Example of Using Specified Language and Evaluate the Script File + +> `jrunscript -l js -f test.js` + +## Example of Interactive Mode + +``` +jrunscript +js> print('Hello World\n'); +Hello World +js> 34 + 55 +89.0 +js> t = new java.lang.Thread(function() { print('Hello World\n'); }) +Thread[Thread-0,5,main] +js> t.start() +js> Hello World + +js> +``` + +## Run Script File with Script Arguments + +In this example, the `test.js` file is the script file. The `arg1`, `arg2`, and +`arg3` arguments are passed to the script. The script can access these +arguments with an arguments array. + +> `jrunscript test.js arg1 arg2 arg3` diff --git a/src/java.se/share/classes/module-info.java b/src/java.se/share/classes/module-info.java index 81b1bd3cb8a..9a2704660b7 100644 --- a/src/java.se/share/classes/module-info.java +++ b/src/java.se/share/classes/module-info.java @@ -23,6 +23,8 @@ * questions. */ +import jdk.internal.javac.ParticipatesInPreview; + /** * Defines the API of the Java SE Platform. * @@ -38,7 +40,9 @@ * @moduleGraph * @since 9 */ +@ParticipatesInPreview module java.se { + requires transitive java.base; requires transitive java.compiler; requires transitive java.datatransfer; requires transitive java.desktop; diff --git a/src/java.security.jgss/windows/man/kinit.md b/src/java.security.jgss/windows/man/kinit.md new file mode 100644 index 00000000000..03605667ae9 --- /dev/null +++ b/src/java.security.jgss/windows/man/kinit.md @@ -0,0 +1,154 @@ +--- +# Copyright (c) 2005, 2019, 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. +# + +title: 'KINIT(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +kinit - obtain and cache Kerberos ticket-granting tickets + +## Synopsis + +Initial ticket request: + +`kinit` \[`-A`\] \[`-f`\] \[`-p`\] \[`-c` *cache\_name*\] \[`-l` *lifetime*\] +\[`-r` *renewable\_time*\] \[\[`-k` \[`-t` *keytab\_file\_name*\]\] +\[*principal*\] \[*password*\] + +Renew a ticket: + +`kinit` `-R` \[`-c` *cache\_name*\] \[*principal*\] + +## Description + +This tool is similar in functionality to the `kinit` tool that is commonly +found in other Kerberos implementations, such as SEAM and MIT Reference +implementations. The user must be registered as a principal with the Key +Distribution Center (KDC) prior to running `kinit`. + +By default, on Windows, a cache file named *USER\_HOME*`\krb5cc_`*USER\_NAME* +is generated. + +The identifier *USER\_HOME* is obtained from the `java.lang.System` property +`user.home`. *USER\_NAME* is obtained from the `java.lang.System` property +`user.name`. If *USER\_HOME* is null, the cache file is stored in the current +directory from which the program is running. *USER\_NAME* is the operating +system's login user name. This user name could be different than the user's +principal name. For example, on Windows, the cache file could be +`C:\Windows\Users\duke\krb5cc_duke`, in which `duke` is the *USER\_NAME* and +`C:\Windows\Users\duke` is the *USER\_HOME*. + +By default, the keytab name is retrieved from the Kerberos configuration file. +If the keytab name isn't specified in the Kerberos configuration file, the +kinit tool assumes that the name is *USER\_HOME*`\krb5.keytab` + +If you don't specify the password using the *password* option on the command +line, the `kinit` tool prompts you for the password. + +**Note:** + +The `password` option is provided only for testing purposes. Don't specify your +password in a script or provide your password on the command line. Doing so +will compromise your password. + +## Commands + +You can specify one of the following commands. After the command, specify the +options for it. + +`-A` +: Doesn't include addresses. + +`-f` +: Issues a forwardable ticket. + +`-p` +: Issues a proxiable ticket. + +`-c` *cache\_name* +: The cache name (for example, `FILE:D:\temp\mykrb5cc`). + +`-l` *lifetime* +: Sets the lifetime of a ticket. The value can be one of "h:m[:s]", + "NdNhNmNs", and "N". See the [MIT krb5 Time Duration definition]( + http://web.mit.edu/kerberos/krb5-1.17/doc/basic/date_format.html#duration) + for more information. + +`-r` *renewable\_time* +: Sets the total lifetime that a ticket can be renewed. + +`-R` +: Renews a ticket. + +`-k` +: Uses keytab + +`-t` *keytab\_filename* +: The keytab name (for example, `D:\winnt\profiles\duke\krb5.keytab`). + +*principal* +: The principal name (for example, `duke@example.com`). + +*password* +: The *principal*'s Kerberos password. **Don't specify this on the command + line or in a script.** + +Run `kinit -help` to display the instructions above. + +## Examples + +Requests credentials valid for authentication from the current client host, for +the default services, storing the credentials cache in the default location +(`C:\Windows\Users\duke\krb5cc_duke`): + +> `kinit duke@example.com` + +Requests proxiable credentials for a different principal and store these +credentials in a specified file cache: + +> `kinit -l 1h -r 10h duke@example.com` + +Requests a TGT for the specified principal that will expire in 1 hour but +is renewable for up to 10 hours. Users must renew a ticket before it has +expired. The renewed ticket can be renewed repeatedly within 10 hours +from its initial request. + +> `kinit -R duke@example.com` + +Renews an existing renewable TGT for the specified principal. + +> `kinit -p -c FILE:C:\Windows\Users\duke\credentials\krb5cc_cafebeef + cafebeef@example.com` + +Requests proxiable and forwardable credentials for a different principal and +stores these credentials in a specified file cache: + +> `kinit -f -p -c FILE:C:\Windows\Users\duke\credentials\krb5cc_cafebeef + cafebeef@example.com` + +Displays the help menu for the `kinit` tool: + +> `kinit -help` diff --git a/src/java.security.jgss/windows/man/klist.md b/src/java.security.jgss/windows/man/klist.md new file mode 100644 index 00000000000..be9e26abe0f --- /dev/null +++ b/src/java.security.jgss/windows/man/klist.md @@ -0,0 +1,98 @@ +--- +# Copyright (c) 2005, 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 +# 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. +# + +title: 'KLIST(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +klist - display the entries in the local credentials cache and key table + +## Synopsis + +`klist` \[`-c` \[`-f`\] \[`-e`\] \[`-a` \[`-n`\]\]\] \[`-k` \[`-t`\] \[`-K`\]\] +\[*name*\] \[`-help`\] + +## Description + +The `klist` tool displays the entries in the local credentials cache and key +table. After you modify the credentials cache with the `kinit` tool or modify +the keytab with the `ktab` tool, the only way to verify the changes is to view +the contents of the credentials cache or keytab using the `klist` tool. The +`klist` tool doesn't change the Kerberos database. + +## Commands + +`-c` +: Specifies that the credential cache is to be listed. + + The following are the options for credential cache entries: + + `-f` + : Show credential flags. + + `-e` + : Show the encryption type. + + `-a` + : Show addresses. + + `-n` + : If the `-a` option is specified, don't reverse resolve addresses. + +`-k` +: Specifies that key tab is to be listed. + + List the keytab entries. The following are the options for keytab entries: + + `-t` + : Show keytab entry timestamps. + + `-K` + : Show keytab entry DES keys. + + `-e` + : Shows keytab entry key type. + +*name* +: Specifies the credential cache name or the keytab name. File-based cache or + keytab's prefix is `FILE:`. If the name isn't specified, the `klist` tool + uses default values for the cache name and keytab. The `kinit` + documentation lists these default values. + +`-help` +: Displays instructions. + +## Examples + +List entries in the keytable specified including keytab entry timestamps and +DES keys: + +> `klist -k -t -K FILE:\temp\mykrb5cc` + +List entries in the credentials cache specified including credentials flag and +address list: + +> `klist -c -f FILE:\temp\mykrb5cc` diff --git a/src/java.security.jgss/windows/man/ktab.md b/src/java.security.jgss/windows/man/ktab.md new file mode 100644 index 00000000000..ac8a6d4a0ec --- /dev/null +++ b/src/java.security.jgss/windows/man/ktab.md @@ -0,0 +1,134 @@ +--- +# Copyright (c) 2005, 2022, 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. +# + +title: 'KTAB(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +ktab - manage the principal names and service keys stored in a local key +table + +## Synopsis + +`ktab` \[*commands*\] \[*options*\] + +\[*commands*\] \[*options*\] +: Lists the keytab name and entries, adds new key entries to the keytab, + deletes existing key entries, and displays instructions. See [Commands and + Options]. + +## Description + +The `ktab` enables the user to manage the principal names and service keys +stored in a local key table. Principal and key pairs listed in the keytab +enable services running on a host to authenticate themselves to the Key +Distribution Center (KDC). + +Before configuring a server to use Kerberos, you must set up a keytab on the +host running the server. Note that any updates made to the keytab using the +`ktab` tool don't affect the Kerberos database. + +A *keytab* is a host's copy of its own keylist, which is analogous to a user's +password. An application server that needs to authenticate itself to the Key +Distribution Center (KDC) must have a keytab which contains its own principal +and key. If you change the keys in the keytab, you must also make the +corresponding changes to the Kerberos database. The `ktab` tool enables you to +list, add, update or delete principal names and key pairs in the key table. +None of these operations affect the Kerberos database. + +## Security Alert + +Don't specify your password on the command line. Doing so can be a security +risk. For example, an attacker could discover your password while running the +UNIX `ps` command. + +Just as it is important for users to protect their passwords, it is equally +important for hosts to protect their keytabs. You should always store keytab +files on the local disk and make them readable only by root. You should never +send a keytab file over a network in the clear. + +## Commands and Options + +`-l` \[`-e`\] \[`-t`\] +: Lists the keytab name and entries. When `-e` is specified, the encryption + type for each entry is displayed. When `-t` is specified, the timestamp for + each entry is displayed. + +`-a` *principal\_name* \[*password*\] \[`-n` *kvno*\] \[`-s` *salt* \| `-f`\] \[`-append`\] +: Adds new key entries to the keytab for the given principal name with an + optional *password*. If a *kvno* is specified, new keys' Key Version + Numbers equal to the value, otherwise, automatically incrementing the Key + Version Numbers. If *salt* is specified, it will be used instead of the + default salt. If `-f` is specified, the KDC will be contacted to + fetch the salt. If `-append` is specified, new keys are appended to the + keytab, otherwise, old keys for the same principal are removed. + + No changes are made to the Kerberos database. **Don't specify the password + on the command line or in a script.** This tool will prompt for a password + if it isn't specified. + +`-d` *principal\_name* \[`-f`\] \[`-e` *etype*\] \[*kvno* \| `all`\| `old`\] +: Deletes key entries from the keytab for the specified principal. No changes + are made to the Kerberos database. + + - If *kvno* is specified, the tool deletes keys whose Key Version Numbers + match kvno. If `all` is specified, delete all keys. + + - If `old` is specified, the tool deletes all keys except those with the + highest *kvno*. The default action is `all`. + + - If *etype* is specified, the tool only deletes keys of this encryption + type. *etype* should be specified as the numeric value *etype* defined + in RFC 3961, section 8. A prompt to confirm the deletion is displayed + unless `-f` is specified. + + When *etype* is provided, only the entry matching this encryption type is + deleted. Otherwise, all entries are deleted. + +`-help` +: Displays instructions. + +## Common Options + +This option can be used with the `-l`, `-a` or `-d` commands. + +`-k` *keytab name* +: Specifies the keytab name and path with the `FILE:` prefix. + +## Examples + +- Lists all the entries in the default keytable + + > `ktab -l` + +- Adds a new principal to the key table (note that you will be prompted for + your password) + + > `ktab -a duke@example.com` + +- Deletes a principal from the key table + + > `ktab -d duke@example.com` diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java index b61c962bf51..c3d4cdcc54b 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,6 @@ */ package com.sun.security.sasl; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.security.NoSuchAlgorithmException; import java.security.InvalidParameterException; import java.security.ProviderException; @@ -98,34 +96,28 @@ public Object newInstance(Object ctrParamObj) } } - @SuppressWarnings("removal") public Provider() { super("SunSASL", PROVIDER_VER, info); final Provider p = this; - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - // Client mechanisms - putService(new ProviderService(p, "SaslClientFactory", - "DIGEST-MD5", "com.sun.security.sasl.digest.FactoryImpl")); - putService(new ProviderService(p, "SaslClientFactory", - "NTLM", "com.sun.security.sasl.ntlm.FactoryImpl")); - putService(new ProviderService(p, "SaslClientFactory", - "EXTERNAL", "com.sun.security.sasl.ClientFactoryImpl")); - putService(new ProviderService(p, "SaslClientFactory", - "PLAIN", "com.sun.security.sasl.ClientFactoryImpl")); - putService(new ProviderService(p, "SaslClientFactory", - "CRAM-MD5", "com.sun.security.sasl.ClientFactoryImpl")); + // Client mechanisms + putService(new ProviderService(p, "SaslClientFactory", + "DIGEST-MD5", "com.sun.security.sasl.digest.FactoryImpl")); + putService(new ProviderService(p, "SaslClientFactory", + "NTLM", "com.sun.security.sasl.ntlm.FactoryImpl")); + putService(new ProviderService(p, "SaslClientFactory", + "EXTERNAL", "com.sun.security.sasl.ClientFactoryImpl")); + putService(new ProviderService(p, "SaslClientFactory", + "PLAIN", "com.sun.security.sasl.ClientFactoryImpl")); + putService(new ProviderService(p, "SaslClientFactory", + "CRAM-MD5", "com.sun.security.sasl.ClientFactoryImpl")); - // Server mechanisms - putService(new ProviderService(p, "SaslServerFactory", - "CRAM-MD5", "com.sun.security.sasl.ServerFactoryImpl")); - putService(new ProviderService(p, "SaslServerFactory", - "DIGEST-MD5", "com.sun.security.sasl.digest.FactoryImpl")); - putService(new ProviderService(p, "SaslServerFactory", - "NTLM", "com.sun.security.sasl.ntlm.FactoryImpl")); - return null; - } - }); + // Server mechanisms + putService(new ProviderService(p, "SaslServerFactory", + "CRAM-MD5", "com.sun.security.sasl.ServerFactoryImpl")); + putService(new ProviderService(p, "SaslServerFactory", + "DIGEST-MD5", "com.sun.security.sasl.digest.FactoryImpl")); + putService(new ProviderService(p, "SaslServerFactory", + "NTLM", "com.sun.security.sasl.ntlm.FactoryImpl")); } } diff --git a/src/java.security.sasl/share/classes/javax/security/sasl/Sasl.java b/src/java.security.sasl/share/classes/javax/security/sasl/Sasl.java index aa6bec486ce..79f592fc54a 100644 --- a/src/java.security.sasl/share/classes/javax/security/sasl/Sasl.java +++ b/src/java.security.sasl/share/classes/javax/security/sasl/Sasl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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,8 +26,6 @@ package javax.security.sasl; import javax.security.auth.callback.CallbackHandler; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; @@ -74,10 +72,7 @@ public class Sasl { private static List disabledMechanisms = new ArrayList<>(); static { - @SuppressWarnings("removal") - String prop = AccessController.doPrivileged( - (PrivilegedAction) - () -> Security.getProperty("jdk.sasl.disabledMechanisms")); + String prop = Security.getProperty("jdk.sasl.disabledMechanisms"); if (prop != null) { for (String s : prop.split("\\s*,\\s*")) { @@ -452,9 +447,7 @@ private static Object loadFactory(Service service) * that was used to load the provider. * In order to get the class loader of a class, the * caller's class loader must be the same as or an ancestor of - * the class loader being returned. Otherwise, the caller must - * have "getClassLoader" permission, or a SecurityException - * will be thrown. + * the class loader being returned. */ return service.newInstance(null); } catch (InvalidParameterException | NoSuchAlgorithmException e) { diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java b/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java index 736431df313..f5bf8df6a4a 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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,16 +31,12 @@ import java.math.*; import java.util.*; import java.text.*; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import javax.sql.rowset.*; import javax.sql.rowset.spi.*; import javax.sql.rowset.serial.*; import com.sun.rowset.internal.*; import com.sun.rowset.providers.*; -import sun.reflect.misc.ReflectUtil; import static java.nio.charset.StandardCharsets.US_ASCII; @@ -357,7 +353,6 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern *

* @throws SQLException if an error occurs */ - @SuppressWarnings("removal") public CachedRowSetImpl() throws SQLException { try { @@ -367,16 +362,7 @@ public CachedRowSetImpl() throws SQLException { } // set the Reader, this maybe overridden latter - try { - provider = AccessController.doPrivileged(new PrivilegedExceptionAction<>() { - @Override - public SyncProvider run() throws SyncFactoryException { - return SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER); - } - }, null, new RuntimePermission("accessClassInPackage.com.sun.rowset.providers")); - } catch (PrivilegedActionException pae) { - throw (SyncFactoryException) pae.getException(); - } + provider = SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER); if (!(provider instanceof RIOptimisticProvider)) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString()); @@ -2976,7 +2962,6 @@ public Object getObject(int columnIndex) throws SQLException { // create new instance of the class SQLData obj = null; try { - ReflectUtil.checkPackageAccess(c); @SuppressWarnings("deprecation") Object tmp = c.newInstance(); obj = (SQLData) tmp; @@ -5726,7 +5711,6 @@ public Object getObject(int columnIndex, // create new instance of the class SQLData obj = null; try { - ReflectUtil.checkPackageAccess(c); @SuppressWarnings("deprecation") Object tmp = c.newInstance(); obj = (SQLData) tmp; diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java b/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java index 6e4d3671651..56f0d30c6df 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import javax.sql.*; import java.util.*; import java.io.*; -import sun.reflect.misc.ReflectUtil; import com.sun.rowset.*; import java.text.MessageFormat; @@ -575,7 +574,6 @@ private boolean updateOriginalRow(CachedRowSet crs) // create new instance of the class SQLData obj = null; try { - ReflectUtil.checkPackageAccess(c); @SuppressWarnings("deprecation") Object tmp = c.newInstance(); obj = (SQLData)tmp; diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java index f69ece6e469..37558222d9c 100644 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,9 @@ package javax.sql.rowset; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.sql.SQLException; -import java.util.PropertyPermission; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; -import sun.reflect.misc.ReflectUtil; /** * A factory API that enables applications to obtain a @@ -68,7 +64,7 @@ public class RowSetProvider { static { // Check to see if the debug property is set - String val = getSystemProperty(ROWSET_DEBUG_PROPERTY); + String val = System.getProperty(ROWSET_DEBUG_PROPERTY); // Allow simply setting the prop to turn on debug debug = val != null && !"false".equals(val); } @@ -128,7 +124,8 @@ public static RowSetFactory newFactory() String factoryClassName = null; try { trace("Checking for Rowset System Property..."); - factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME); + + factoryClassName = System.getProperty(ROWSET_FACTORY_NAME); if (factoryClassName != null) { trace("Found system property, value=" + factoryClassName); if (factoryClassName.equals(ROWSET_FACTORY_IMPL)) { @@ -193,11 +190,6 @@ public static RowSetFactory newFactory(String factoryClassName, ClassLoader cl) if(factoryClassName == null) { throw new SQLException("Error: factoryClassName cannot be null"); } - try { - ReflectUtil.checkPackageAccess(factoryClassName); - } catch (@SuppressWarnings("removal") java.security.AccessControlException e) { - throw new SQLException("Access Exception",e); - } try { // getFactoryClass takes care of adding the read edge if @@ -225,22 +217,14 @@ public static RowSetFactory newFactory(String factoryClassName, ClassLoader cl) * @return The ClassLoader to use. * */ - @SuppressWarnings("removal") - private static ClassLoader getContextClassLoader() throws SecurityException { - return AccessController.doPrivileged(new PrivilegedAction() { - - public ClassLoader run() { - ClassLoader cl = null; - - cl = Thread.currentThread().getContextClassLoader(); + private static ClassLoader getContextClassLoader() { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if (cl == null) { - cl = ClassLoader.getSystemClassLoader(); - } + if (cl == null) { + cl = ClassLoader.getSystemClassLoader(); + } - return cl; - } - }); + return cl; } /** @@ -276,7 +260,6 @@ private static Class getFactoryClass(String factoryClassName, ClassLoader cl, } } - ReflectUtil.checkPackageAccess(factoryClass); return factoryClass; } @@ -302,32 +285,6 @@ private static RowSetFactory loadViaServiceLoader() throws SQLException { } - /** - * Returns the requested System Property. If a {@code SecurityException} - * occurs, just return NULL - * @param propName - System property to retrieve - * @return The System property value or NULL if the property does not exist - * or a {@code SecurityException} occurs. - */ - @SuppressWarnings("removal") - private static String getSystemProperty(final String propName) { - String property = null; - try { - property = AccessController.doPrivileged(new PrivilegedAction() { - - public String run() { - return System.getProperty(propName); - } - }, null, new PropertyPermission(propName, "read")); - } catch (SecurityException se) { - trace("error getting " + propName + ": "+ se); - if (debug) { - se.printStackTrace(); - } - } - return property; - } - /** * Debug routine which will output tracing if the System Property * -Djavax.sql.rowset.RowSetFactory.debug is set diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java index 421d4943763..d2daa565baa 100644 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -27,7 +27,6 @@ import java.sql.*; import java.util.Arrays; import java.util.Map; -import sun.reflect.misc.ReflectUtil; /** * An input stream used for custom mapping user-defined types (UDTs). @@ -477,7 +476,6 @@ public Object readObject() throws SQLException { // create new instance of the class SQLData obj = null; try { - ReflectUtil.checkPackageAccess(c); @SuppressWarnings("deprecation") Object tmp = c.newInstance(); obj = (SQLData)tmp; diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialJavaObject.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialJavaObject.java index 00284c5ce51..154c95bc1c4 100644 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialJavaObject.java +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialJavaObject.java @@ -30,9 +30,6 @@ import java.util.Arrays; import java.util.Vector; import javax.sql.rowset.RowSetWarning; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; -import sun.reflect.misc.ReflectUtil; /** * A serializable mapping in the Java programming language of an SQL @@ -125,23 +122,9 @@ public Object getObject() throws SerialException { * the serialized object * @see Class#getFields */ - @CallerSensitive public Field[] getFields() throws SerialException { if (fields != null) { Class c = this.obj.getClass(); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - /* - * Check if the caller is allowed to access the specified class's package. - * If access is denied, throw a SecurityException. - */ - Class caller = Reflection.getCallerClass(); - if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), - c.getClassLoader())) { - ReflectUtil.checkPackageAccess(c); - } - } return c.getFields(); } else { throw new SerialException("SerialJavaObject does not contain" + diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java index 90dea7760fb..9cc7a5b2da8 100644 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java @@ -35,13 +35,8 @@ import java.io.InputStream; import java.io.IOException; import java.io.FileNotFoundException; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import javax.naming.*; -import sun.reflect.misc.ReflectUtil; /** * The Service Provider Interface (SPI) mechanism that generates SyncProvider @@ -236,11 +231,6 @@ private SyncFactory() { */ private static String ROWSET_PROPERTIES = "rowset.properties"; - /** - * Permission required to invoke setJNDIContext and setLogger - */ - private static final SQLPermission SET_SYNCFACTORY_PERMISSION = - new SQLPermission("setSyncFactory"); /** * The initial JNDI context where SyncProvider implementations can * be stored and from which they can be invoked. @@ -355,17 +345,7 @@ private static synchronized void initMapIfNecessary() throws SyncFactoryExceptio /* * Dependent on application */ - String strRowsetProperties; - try { - strRowsetProperties = AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return System.getProperty("rowset.properties"); - } - }, null, new PropertyPermission("rowset.properties", "read")); - } catch (Exception ex) { - System.out.println("errorget rowset.properties: " + ex); - strRowsetProperties = null; - }; + String strRowsetProperties = System.getProperty("rowset.properties"); if (strRowsetProperties != null) { // Load user's implementation of SyncProvider @@ -385,25 +365,17 @@ public String run() { "rowset.properties"; try { - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - InputStream in = SyncFactory.class.getModule().getResourceAsStream(ROWSET_PROPERTIES); - if (in == null) { - throw new SyncFactoryException("Resource " + ROWSET_PROPERTIES + " not found"); - } - try (in) { - properties.load(in); - } - return null; - }); - } catch (PrivilegedActionException ex) { - Throwable e = ex.getException(); - if (e instanceof SyncFactoryException) { - throw (SyncFactoryException) e; - } else { - SyncFactoryException sfe = new SyncFactoryException(); - sfe.initCause(ex.getException()); - throw sfe; + InputStream in = SyncFactory.class.getModule().getResourceAsStream(ROWSET_PROPERTIES); + if (in == null) { + throw new SyncFactoryException("Resource " + ROWSET_PROPERTIES + " not found"); } + try (in) { + properties.load(in); + } + } catch (IOException e) { + SyncFactoryException sfe = new SyncFactoryException(); + sfe.initCause(e); + throw sfe; } parseProperties(properties); @@ -421,17 +393,7 @@ public String run() { * load additional properties from -D command line */ properties.clear(); - String providerImpls; - try { - providerImpls = AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return System.getProperty(ROWSET_SYNC_PROVIDER); - } - }, null, new PropertyPermission(ROWSET_SYNC_PROVIDER, "read")); - } catch (Exception ex) { - providerImpls = null; - } - + String providerImpls = System.getProperty(ROWSET_SYNC_PROVIDER); if (providerImpls != null) { int i = 0; if (providerImpls.indexOf(colon) > 0) { @@ -563,14 +525,6 @@ public static SyncProvider getInstance(String providerID) return new com.sun.rowset.providers.RIOptimisticProvider(); } - try { - ReflectUtil.checkPackageAccess(providerID); - } catch (@SuppressWarnings("removal") java.security.AccessControlException e) { - SyncFactoryException sfe = new SyncFactoryException(); - sfe.initCause(e); - throw sfe; - } - // Attempt to invoke classname from registered SyncProvider list Class c = null; try { @@ -626,12 +580,6 @@ public static Enumeration getRegisteredProviders() */ public static void setLogger(Logger logger) { - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - if (sec != null) { - sec.checkPermission(SET_SYNCFACTORY_PERMISSION); - } - if(logger == null){ throw new NullPointerException("You must provide a Logger"); } @@ -652,12 +600,6 @@ public static void setLogger(Logger logger) { */ public static void setLogger(Logger logger, Level level) { // singleton - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - if (sec != null) { - sec.checkPermission(SET_SYNCFACTORY_PERMISSION); - } - if(logger == null){ throw new NullPointerException("You must provide a Logger"); } @@ -692,11 +634,7 @@ public static Logger getLogger() throws SyncFactoryException { */ public static synchronized void setJNDIContext(javax.naming.Context ctx) throws SyncFactoryException { - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - if (sec != null) { - sec.checkPermission(SET_SYNCFACTORY_PERMISSION); - } + if (ctx == null) { throw new SyncFactoryException("Invalid JNDI context supplied"); } diff --git a/src/java.sql/share/classes/java/sql/DriverManager.java b/src/java.sql/share/classes/java/sql/DriverManager.java index 918d0692a1a..7620a11e6fd 100644 --- a/src/java.sql/share/classes/java/sql/DriverManager.java +++ b/src/java.sql/share/classes/java/sql/DriverManager.java @@ -31,8 +31,6 @@ import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Stream; @@ -98,22 +96,6 @@ public class DriverManager { /* Prevent the DriverManager class from being instantiated. */ private DriverManager(){} - /** - * The {@code SQLPermission} constant that allows the - * setting of the logging stream. - * @since 1.3 - */ - static final SQLPermission SET_LOG_PERMISSION = - new SQLPermission("setLog"); - - /** - * The {@code SQLPermission} constant that allows the - * un-register a registered JDBC driver. - * @since 1.8 - */ - static final SQLPermission DEREGISTER_DRIVER_PERMISSION = - new SQLPermission("deregisterDriver"); - //--------------------------JDBC 2.0----------------------------- /** @@ -140,14 +122,8 @@ public static java.io.PrintWriter getLogWriter() { * @since 1.2 */ public static void setLogWriter(java.io.PrintWriter out) { - - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - if (sec != null) { - sec.checkPermission(SET_LOG_PERMISSION); - } - logStream = null; - logWriter = out; + logStream = null; + logWriter = out; } @@ -367,12 +343,6 @@ public static void deregisterDriver(Driver driver) throws SQLException { return; } - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - if (sec != null) { - sec.checkPermission(DEREGISTER_DRIVER_PERMISSION); - } - println("DriverManager.deregisterDriver: " + driver); DriverInfo aDriver = new DriverInfo(driver, null); @@ -477,13 +447,6 @@ public static int getLoginTimeout() { */ @Deprecated(since="1.2") public static void setLogStream(java.io.PrintStream out) { - - @SuppressWarnings("removal") - SecurityManager sec = System.getSecurityManager(); - if (sec != null) { - sec.checkPermission(SET_LOG_PERMISSION); - } - logStream = out; if ( out != null ) logWriter = new java.io.PrintWriter(out); @@ -549,7 +512,6 @@ private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { * Load the initial JDBC drivers by checking the System property * jdbc.drivers and then use the {@code ServiceLoader} mechanism */ - @SuppressWarnings("removal") private static void ensureDriversInitialized() { if (driversInitialized) { return; @@ -561,11 +523,7 @@ private static void ensureDriversInitialized() { } String drivers; try { - drivers = AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return System.getProperty(JDBC_DRIVERS_PROPERTY); - } - }); + drivers = System.getProperty(JDBC_DRIVERS_PROPERTY); } catch (Exception ex) { drivers = null; } @@ -574,34 +532,29 @@ public String run() { // exposed as a java.sql.Driver.class service. // ServiceLoader.load() replaces the sun.misc.Providers() - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - - ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class); - Iterator driversIterator = loadedDrivers.iterator(); - - /* Load these drivers, so that they can be instantiated. - * It may be the case that the driver class may not be there - * i.e. there may be a packaged driver with the service class - * as implementation of java.sql.Driver but the actual class - * may be missing. In that case a java.util.ServiceConfigurationError - * will be thrown at runtime by the VM trying to locate - * and load the service. - * - * Adding a try catch block to catch those runtime errors - * if driver not available in classpath but it's - * packaged as service and that service is there in classpath. - */ - try { - while (driversIterator.hasNext()) { - driversIterator.next(); - } - } catch (Throwable t) { - // Do nothing - } - return null; + + ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class); + Iterator driversIterator = loadedDrivers.iterator(); + + /* Load these drivers, so that they can be instantiated. + * It may be the case that the driver class may not be there + * i.e. there may be a packaged driver with the service class + * as implementation of java.sql.Driver but the actual class + * may be missing. In that case a java.util.ServiceConfigurationError + * will be thrown at runtime by the VM trying to locate + * and load the service. + * + * Adding a try catch block to catch those runtime errors + * if driver not available in classpath but it's + * packaged as service and that service is there in classpath. + */ + try { + while (driversIterator.hasNext()) { + driversIterator.next(); } - }); + } catch (Throwable t) { + // Do nothing + } println("DriverManager.initialize: jdbc.drivers = " + drivers); diff --git a/src/jdk.accessibility/windows/man/jabswitch.md b/src/jdk.accessibility/windows/man/jabswitch.md new file mode 100644 index 00000000000..8dfdd6f2737 --- /dev/null +++ b/src/jdk.accessibility/windows/man/jabswitch.md @@ -0,0 +1,75 @@ +--- +# Copyright (c) 2019, 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. +# + +title: 'JABSWITCH(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jabswitch - enable or disable the Java Access Bridge + +## Synopsis + +`jabswitch` \[ -enable|/enable | -disable|/disable | -version|/version | -?|/? \] + +## Options + +`-enable` +or +`/enable` +: Enables the Java Access Bridge + +`-disable` +or +`/disable` +: Disables the Java Access Bridge + +`-version` +or +`/version` +: Displays version information for the `jabswitch` command. + +`-?` +or +`/?` +: Displays usage information for the `jabswitch` command. + +## Description + +The `jabswitch` command is a utility program that enables the +Java Access Bridge to be loaded by the JDK on Windows platforms. +The Java Access Bridge is used by Assistive Technologies +to interact with Java Accessibility APIs of the Java SE platform. +To have any effect, the assistive technology must support the Java Access Bridge. + +This command creates or updates a file named `.accessibility.properties`, +in the user's home directory. When selecting the `-enable` option, the file +is populated with the information needed to load the Java Access Bridge. +This file is then read and used in accordance with the specification of the +Java SE +[`java.awt.Toolkit.getDefaultToolkit()`](../../api/java.desktop/java/awt/Toolkit.html#getDefaultToolkit()) +API, on initialization. + +Note: This command is only provided with JDK for Windows. diff --git a/src/jdk.accessibility/windows/man/jaccessinspector.md b/src/jdk.accessibility/windows/man/jaccessinspector.md new file mode 100644 index 00000000000..17f44cef358 --- /dev/null +++ b/src/jdk.accessibility/windows/man/jaccessinspector.md @@ -0,0 +1,249 @@ +--- +# Copyright (c) 2017, 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 +# 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. +# + +title: 'JACCESSINSPECTOR(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jaccessinspector - examine accessible information about the objects in the +Java Virtual Machine using the Java Accessibility Utilities API + +## Description + +The `jaccessinspector` tool lets you select different methods for examining the +object accessibility information: + +- When events occur such as a change of focus, mouse movement, property + change, menu selection, and the display of a popup menu + +- When you press the F1 key when the mouse is over an object, or F2 when the + mouse is over a window + +After an object has been selected for examination, the `jaccessinspector` tool +displays the results of calling Java Accessibility API methods on that object. + +## Running the jaccessinspector Tool + +To use the `jaccessinspector` tool, launch the `jaccessinspector` tool after +launching a Java application. To launch `jaccessinspector`, run the following +command: + +**Note:** + +`JAVA_HOME` is an environment variable and should be set to the path of the JDK +or JRE, such as `c:\Program Files\Java\jdk-10`. + +> `%JAVA_HOME%\bin\jaccessinspector.exe` + +You now have two windows open: The Java application window and the +`jaccessinspector` window. The `jaccessinspector` window contains five menus: + +- [File Menu] + +- [UpdateSettings Menu] + +- [JavaEvents Menu] + +- [AccessibilityEvents Menu] + +- [Options Menu] + +The items in **UpdateSettings**, **JavaEvents**, and **AccessibilityEvents** +menus let you query Java applications in a variety of ways. + +## File Menu + +This section describes the **File** menu items. + +AccessBridge DLL Loaded +: Enables and disables AccessBridge DLL Loaded. + +Exit +: Exits from the tool. + +## UpdateSettings Menu + +This section describes the **UpdateSettings** menu items. + +Update from Mouse +: Determines the x- and y-coordinates of the mouse (assuming the + `jaccessinspector` tool window is topmost) when the mouse has stopped + moving, and then queries the Java application for the accessible object + underneath the mouse, dumping the output into the `jaccessinspector` + window. + +Update with F2 (Mouse HWND) +: Determines the x- and y-coordinates of the mouse (assuming the + `jaccessinspector` tool window is topmost), and then queries the Java + application for the accessible object of the HWND underneath the mouse, + dumping the output into the `jaccessinspector` window. + +Update with F1 (Mouse Point) +: Determines the x- and y-coordinates of the mouse (assuming the + `jaccessinspector` tool window is topmost), and then queries the Java + application for the accessible object underneath the cursor, dumping the + output into the `jaccessinspector` window. + +## JavaEvents Menu + +This section describes the **JavaEvents** menu items. + +Track Mouse Events +: Registers with the Java application all Java Mouse Entered events, and upon + receiving one, queries the object that was entered by the cursor and dumps + the output into the `jaccessinspector` window. + + **Note:** If the mouse is moved quickly, then there may be some delay + before the displayed information is updated. + +Track Focus Events +: Registers with the Java application all Java Focus Gained events, and upon + receiving an event, queries the object that received the focus and dumps + the output into the `jaccessinspector` window. + +Track Caret Events +: Register with the Java application all Java Caret Update events, and upon + receiving an event, queries the object in which the caret was updated, and + dumps the output into the `jaccessinspector` window. + + **Note:** Because objects that contain carets are almost by definition + objects that are rich text objects, this won't seem as responsive as the + other event tracking options. In real use, one would make fewer + accessibility calls in Caret Update situations (for example, just get the + new letter, word, sentence at the caret location), which would be + significantly faster. + +Track Menu Selected \| Deselected \| Cancelled Events +: Registers with the Java application all Menu events, and upon receiving an + event, queries the object in which the caret was updated, and dumps the + output into the `jaccessinspector` window. + +Track Popup Visible \| Invisible \| Cancelled Events +: Registers with the Java application all Popup Menu events, and upon + receiving an event, queries the object in which the caret was updated, and + dumps the output into the `jaccessinspector` window. + +Track Shutdown Events +: Registers with the Java application to receive a Property Changed event + when a Java application terminates. + +## AccessibilityEvents Menu + +This section describes the **AccessibilityEvents** menu items. + +**Note:** The items listed in the **AccessibilityEvents** menu are the most +important for testing applications, especially for assistive technology +applications. + +Track Name Property Events +: Registers with the Java application all Java Property Changed events + specifically on accessible objects in which the Name property has changed, + and upon receiving an event, dumps the output into the scrolling window, + along with information about the property that changed. + +Track Description Property Events +: Register with the Java application for all Java Property Changed events + specifically on accessible objects in which the Description property has + changed, and upon receiving an event, dumps the output into the + `jaccessinspector` window, along with information about the property that + changed. + +Track State Property Events +: Register with the Java application all Java Property Changed events + specifically on accessible objects in which the State property has changed, + and upon receiving an event, dumps the output into the `jaccessinspector` + window, along with information about the property that changed. + +Track Value Property Events +: Register with the Java application all Java Property Changed events + specifically on accessible objects in which the Value property has changed, + and upon receiving an event, dumps the output into the scrolling window, + along with information about the property that changed. + +Track Selection Property Events +: Register with the Java application all Java Property Changed events + specifically on accessible objects in which the Selection property has + changed, and upon receiving an event, dumps the output into the + `jaccessinspector` window, along with information about the property that + changed. + +Track Text Property Events +: Register with the Java application all Java Property Changed events + specifically on accessible objects in which the Text property has changed, + and upon receiving one event, dump the output into the `jaccessinspector` + window, along with information about the property that changed. + +Track Caret Property Events +: Register with the Java application all Java Property Changed events + specifically on accessible objects in which the Caret property has changed, + and upon receiving an event, dumps the output into the `jaccessinspector` + window, along with information about the property that changed. + +Track VisibleData Property Events +: Register with the Java application all Java Property Changed events + specifically on accessible objects in which the VisibleData property has + changed, and upon receiving an event, dumps the output into the + `jaccessinspector` window, along with information about the property that + changed. + +Track Child Property Events +: Register with the Java application all Java Property Changed events + specifically on accessible objects in which the Child property has changed, + and upon receiving an event, dumps the output into the `jaccessinspector` + window, along with information about the property that changed. + +Track Active Descendent Property Events +: Register with the Java application all Java Property Changed events + specifically on accessible objects in which the Active Descendent property + has changed, and upon receiving an event, dumps the output into the + `jaccessinspector` window, along with information about the property that + changed. + +Track Table Model Change Property Events +: Register with the Java application all Property Changed events specifically + on accessible objects in which the Table Model Change property has changed, + and upon receiving an event, dumps the output into the `jaccessinspector` + window, along with information about the property that changed. + +## Options Menu + +This section describes the **Options** menu items. + +Monitor the same events as JAWS +: Enables monitoring of only the events also monitored by JAWS. + +Monitor All Events +: Enables monitoring of all events in the `jaccessinspector` window. + +Reset All Events +: Resets the selected Options to the default settings. + +Go To Message +: Opens the **Go To Message** dialog that lets you display a logged message + by entering its message number. + +Clear Message History +: Clears the history of logged messages from the `jaccessinspector` window. diff --git a/src/jdk.accessibility/windows/man/jaccesswalker.md b/src/jdk.accessibility/windows/man/jaccesswalker.md new file mode 100644 index 00000000000..f688ae57aee --- /dev/null +++ b/src/jdk.accessibility/windows/man/jaccesswalker.md @@ -0,0 +1,71 @@ +--- +# Copyright (c) 2017, 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 +# 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. +# + +title: 'JACCESSWALKER(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jaccesswalker - navigate through the component trees in a particular Java +Virtual Machine and present the hierarchy in a tree view + +## Description + +You select a node in the tree, and from the **Panels** menu, you select +**Accessibility API Panel**. The `jaccesswalker` tool shows you the +accessibility information for the object in the window. + +## Running the jaccesswalker Tool + +To use `jaccesswalker`, launch the `jaccesswalker` tool after launching a Java +application. For example, to launch `jaccesswalker`, enter the following +command: + +**Note:** + +`JAVA_HOME` is an environment variable and should be set to the path of the JDK +or JRE, such as, `c:\Program Files\Java\jdk-10`. + +> `%JAVA_HOME%\bin\jaccesswalker.exe` + +You now have two windows open: The Java application window, and the window for +the `jaccesswalker` tool. There are two tasks that you can do with +`jaccesswalker` . You can build a tree view of the Java applications' GUI +hierarchy, and you can query the Java Accessibility API information of a +particular element in the GUI hierarchy. + +## Building the GUI Hierarchy + +From the **File** menu, select **Refresh Tree** menu. The `jaccesswalker` tool +builds a list of the top-level windows belonging to Java applications. The tool +then recursively queries the elements in those windows, and builds a tree of +all of the GUI components in all of the Java applications in all of the JVMs +running in the system. + +## Examining a GUI Component + +After a GUI tree is built, you can view detailed accessibility information +about an individual GUI component by selecting it in the tree, then selecting +**Panels**, and then **Display Accessibility Information**. diff --git a/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeJavaEntryPoints.cpp b/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeJavaEntryPoints.cpp index 6f4231b70b9..8610617f7eb 100644 --- a/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeJavaEntryPoints.cpp +++ b/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeJavaEntryPoints.cpp @@ -74,36 +74,36 @@ AccessBridgeJavaEntryPoints::~AccessBridgeJavaEntryPoints() { return FALSE; \ } -#define EXCEPTION_CHECK(situationDescription, returnVal) \ - if (exception = jniEnv->ExceptionOccurred()) { \ - PrintDebugString("[ERROR]: *** Exception occured while doing: %s; returning %d", situationDescription, returnVal); \ - jniEnv->ExceptionDescribe(); \ - jniEnv->ExceptionClear(); \ - return (returnVal); \ - } - -#define EXCEPTION_CHECK_WITH_RELEASE(situationDescription, returnVal, js, stringBytes) \ - if (exception = jniEnv->ExceptionOccurred()) { \ - PrintDebugString("[ERROR]: *** Exception occured while doing: %s - call to GetStringLength; returning %d", situationDescription, returnVal); \ - jniEnv->ExceptionDescribe(); \ - jniEnv->ExceptionClear(); \ - jniEnv->ReleaseStringChars(js, stringBytes); \ - return (returnVal); \ - } \ - jniEnv->ReleaseStringChars(js, stringBytes); \ - if (exception = jniEnv->ExceptionOccurred()) { \ - PrintDebugString("[ERROR]: *** Exception occured while doing: %s - call to ReleaseStringChars; returning %d", situationDescription, returnVal); \ - jniEnv->ExceptionDescribe(); \ - jniEnv->ExceptionClear(); \ - return (returnVal); \ - } - -#define EXCEPTION_CHECK_VOID(situationDescription) \ - if (exception = jniEnv->ExceptionOccurred()) { \ +#define EXCEPTION_CHECK(situationDescription, returnVal) \ + if (jniEnv->ExceptionCheck()) { \ + PrintDebugString("[ERROR]: *** Exception occured while doing: %s; returning %d", situationDescription, returnVal); \ + jniEnv->ExceptionDescribe(); \ + jniEnv->ExceptionClear(); \ + return (returnVal); \ + } + +#define EXCEPTION_CHECK_WITH_RELEASE(situationDescription, returnVal, js, stringBytes) \ + if (jniEnv->ExceptionCheck()) { \ + PrintDebugString("[ERROR]: *** Exception occured while doing: %s - call to GetStringLength; returning %d", situationDescription, returnVal); \ + jniEnv->ExceptionDescribe(); \ + jniEnv->ExceptionClear(); \ + jniEnv->ReleaseStringChars(js, stringBytes); \ + return (returnVal); \ + } \ + jniEnv->ReleaseStringChars(js, stringBytes); \ + if (jniEnv->ExceptionCheck()) { \ + PrintDebugString("[ERROR]: *** Exception occured while doing: %s - call to ReleaseStringChars; returning %d", situationDescription, returnVal); \ + jniEnv->ExceptionDescribe(); \ + jniEnv->ExceptionClear(); \ + return (returnVal); \ + } + +#define EXCEPTION_CHECK_VOID(situationDescription) \ + if (jniEnv->ExceptionCheck()) { \ PrintDebugString("[ERROR]: *** Exception occured while doing: %s", situationDescription); \ - jniEnv->ExceptionDescribe(); \ - jniEnv->ExceptionClear(); \ - return; \ + jniEnv->ExceptionDescribe(); \ + jniEnv->ExceptionClear(); \ + return; \ } /** @@ -890,7 +890,6 @@ AccessBridgeJavaEntryPoints::BuildJavaEntryPoints() { */ BOOL AccessBridgeJavaEntryPoints::isJavaWindow(jint window) { - jthrowable exception; BOOL returnVal; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::isJavaWindow(%X):", window); @@ -913,7 +912,6 @@ AccessBridgeJavaEntryPoints::isJavaWindow(jint window) { */ BOOL AccessBridgeJavaEntryPoints::isSameObject(jobject obj1, jobject obj2) { - jthrowable exception; BOOL returnVal; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::isSameObject(%p %p):", obj1, obj2); @@ -935,7 +933,6 @@ jobject AccessBridgeJavaEntryPoints::getAccessibleContextFromHWND(jint window) { jobject returnedAccessibleContext; jobject globalRef; - jthrowable exception; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::getAccessibleContextFromHWND(%X):", window); @@ -961,7 +958,6 @@ AccessBridgeJavaEntryPoints::getAccessibleContextFromHWND(jint window) { */ HWND AccessBridgeJavaEntryPoints::getHWNDFromAccessibleContext(jobject accessibleContext) { - jthrowable exception; HWND rHWND; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::getHWNDFromAccessibleContext(%X):", @@ -987,7 +983,6 @@ AccessBridgeJavaEntryPoints::getHWNDFromAccessibleContext(jobject accessibleCont */ BOOL AccessBridgeJavaEntryPoints::setTextContents(const jobject accessibleContext, const wchar_t *text) { - jthrowable exception; BOOL result = FALSE; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::setTextContents(%p, %ls):", @@ -1024,7 +1019,6 @@ AccessBridgeJavaEntryPoints::setTextContents(const jobject accessibleContext, co */ jobject AccessBridgeJavaEntryPoints::getParentWithRole(const jobject accessibleContext, const wchar_t *role) { - jthrowable exception; jobject rAccessibleContext; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::getParentWithRole(%p):", @@ -1062,7 +1056,6 @@ AccessBridgeJavaEntryPoints::getParentWithRole(const jobject accessibleContext, */ jobject AccessBridgeJavaEntryPoints::getTopLevelObject(const jobject accessibleContext) { - jthrowable exception; jobject rAccessibleContext; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::getTopLevelObject(%p):", @@ -1093,7 +1086,6 @@ AccessBridgeJavaEntryPoints::getTopLevelObject(const jobject accessibleContext) */ jobject AccessBridgeJavaEntryPoints::getParentWithRoleElseRoot(const jobject accessibleContext, const wchar_t *role) { - jthrowable exception; jobject rAccessibleContext; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::getParentWithRoleElseRoot(%p):", @@ -1131,7 +1123,6 @@ AccessBridgeJavaEntryPoints::getParentWithRoleElseRoot(const jobject accessibleC */ jint AccessBridgeJavaEntryPoints::getObjectDepth(const jobject accessibleContext) { - jthrowable exception; jint rResult; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::getObjectDepth(%p):", @@ -1158,7 +1149,6 @@ AccessBridgeJavaEntryPoints::getObjectDepth(const jobject accessibleContext) { */ jobject AccessBridgeJavaEntryPoints::getActiveDescendent(const jobject accessibleContext) { - jthrowable exception; jobject rAccessibleContext; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::getActiveDescendent(%p):", @@ -1215,7 +1205,6 @@ AccessBridgeJavaEntryPoints::getVirtualAccessibleName ( jstring js = NULL; const wchar_t * stringBytes = NULL; - jthrowable exception = NULL; jsize length = 0; PrintDebugString("[INFO]: getVirtualAccessibleName called."); if (getVirtualAccessibleNameFromContextMethod != (jmethodID) 0) @@ -1266,7 +1255,6 @@ AccessBridgeJavaEntryPoints::getVirtualAccessibleName ( BOOL AccessBridgeJavaEntryPoints::requestFocus(const jobject accessibleContext) { - jthrowable exception; BOOL result = FALSE; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::requestFocus(%p):", @@ -1294,7 +1282,6 @@ AccessBridgeJavaEntryPoints::requestFocus(const jobject accessibleContext) { BOOL AccessBridgeJavaEntryPoints::selectTextRange(const jobject accessibleContext, int startIndex, int endIndex) { - jthrowable exception; BOOL result = FALSE; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::selectTextRange(%p start = %d end = %d):", @@ -1362,7 +1349,6 @@ AccessBridgeJavaEntryPoints::getTextAttributesInRange(const jobject accessibleCo jstring js; const wchar_t *stringBytes; - jthrowable exception; jsize length; BOOL result = FALSE; @@ -1429,7 +1415,6 @@ AccessBridgeJavaEntryPoints::getTextAttributesInRange(const jobject accessibleCo int AccessBridgeJavaEntryPoints::getVisibleChildrenCount(const jobject accessibleContext) { - jthrowable exception; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getVisibleChildrenCount(%p)", accessibleContext); @@ -1455,8 +1440,6 @@ BOOL AccessBridgeJavaEntryPoints::getVisibleChildren(const jobject accessibleCon const int nStartIndex, /* OUT */ VisibleChildrenInfo *visibleChildrenInfo) { - jthrowable exception; - PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getVisibleChildren(%p, startIndex = %d)", accessibleContext, nStartIndex); @@ -1500,7 +1483,6 @@ BOOL AccessBridgeJavaEntryPoints::getVisibleChildren(const jobject accessibleCon BOOL AccessBridgeJavaEntryPoints::setCaretPosition(const jobject accessibleContext, int position) { - jthrowable exception; BOOL result = FALSE; PrintDebugString("[INFO]: In AccessBridgeJavaEntryPoints::setCaretPostion(%p position = %d):", @@ -1531,7 +1513,6 @@ BOOL AccessBridgeJavaEntryPoints::getVersionInfo(AccessBridgeVersionInfo *info) { jstring js; const wchar_t *stringBytes; - jthrowable exception; jsize length; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getVersionInfo():"); @@ -1601,7 +1582,6 @@ AccessBridgeJavaEntryPoints::getVersionInfo(AccessBridgeVersionInfo *info) { BOOL AccessBridgeJavaEntryPoints::verifyAccessibleText(jobject obj) { JavaVM *vm; BOOL retval; - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::verifyAccessibleText"); @@ -1653,7 +1633,6 @@ jobject AccessBridgeJavaEntryPoints::getAccessibleContextAt(jint x, jint y, jobject accessibleContext) { jobject returnedAccessibleContext; jobject globalRef; - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleContextAt(%d, %d, %p):", x, y, accessibleContext); @@ -1688,7 +1667,6 @@ jobject AccessBridgeJavaEntryPoints::getAccessibleContextWithFocus() { jobject returnedAccessibleContext; jobject globalRef; - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleContextWithFocus()"); @@ -1724,7 +1702,6 @@ AccessBridgeJavaEntryPoints::getAccessibleContextInfo(jobject accessibleContext, jstring js; const wchar_t *stringBytes; jobject returnedJobject; - jthrowable exception; jsize length; PrintDebugString("[INFO]: ##### Calling AccessBridgeJavaEntryPoints::getAccessibleContextInfo(%p):", accessibleContext); @@ -2156,7 +2133,6 @@ jobject AccessBridgeJavaEntryPoints::getAccessibleChildFromContext(jobject accessibleContext, jint childIndex) { jobject returnedAccessibleContext; jobject globalRef; - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleChildContext(%p, %d):", accessibleContext, childIndex); @@ -2188,7 +2164,6 @@ AccessBridgeJavaEntryPoints::getAccessibleParentFromContext(jobject accessibleCo { jobject returnedAccessibleContext; jobject globalRef; - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleParentFromContext(%p):", accessibleContext); @@ -2217,8 +2192,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleTableInfo(jobject accessibleContext, AccessibleTableInfo *tableInfo) { - jthrowable exception; - PrintDebugString("[INFO]: ##### Calling AccessBridgeJavaEntryPoints::getAccessibleTableInfo(%p):", accessibleContext); @@ -2292,8 +2265,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleTableCellInfo(jobject accessibleTable, jint row, jint column, AccessibleTableCellInfo *tableCellInfo) { - jthrowable exception; - PrintDebugString("[INFO]: ##### Calling AccessBridgeJavaEntryPoints::getAccessibleTableCellInfo(%p): row=%d, column=%d", accessibleTable, row, column); @@ -2373,8 +2344,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableCellInfo(jobject accessibleTable, BOOL AccessBridgeJavaEntryPoints::getAccessibleTableRowHeader(jobject acParent, AccessibleTableInfo *tableInfo) { - jthrowable exception; - PrintDebugString("[INFO]: ##### Calling AccessBridgeJavaEntryPoints::getAccessibleTableRowHeader(%p):", acParent); @@ -2428,7 +2397,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableRowHeader(jobject acParent, Acces BOOL AccessBridgeJavaEntryPoints::getAccessibleTableColumnHeader(jobject acParent, AccessibleTableInfo *tableInfo) { - jthrowable exception; PrintDebugString("[INFO]: ##### Calling AccessBridgeJavaEntryPoints::getAccessibleTableColumnHeader(%p):", acParent); @@ -2485,7 +2453,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableRowDescription(jobject acParent, jobject returnedAccessibleContext; jobject globalRef; - jthrowable exception; PrintDebugString("[INFO]: ##### Calling AccessBridgeJavaEntryPoints::getAccessibleTableRowDescription(%p):", acParent); @@ -2513,7 +2480,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableColumnDescription(jobject acParen jobject returnedAccessibleContext; jobject globalRef; - jthrowable exception; PrintDebugString("[INFO]: ##### Calling AccessBridgeJavaEntryPoints::getAccessibleTableColumnDescription(%p):", acParent); @@ -2540,7 +2506,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableColumnDescription(jobject acParen jint AccessBridgeJavaEntryPoints::getAccessibleTableRowSelectionCount(jobject accessibleTable) { - jthrowable exception; jint count; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleTableRowSelectionCount(%p)", @@ -2565,7 +2530,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableRowSelectionCount(jobject accessi BOOL AccessBridgeJavaEntryPoints::isAccessibleTableRowSelected(jobject accessibleTable, jint row) { - jthrowable exception; BOOL result; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::isAccessibleTableRowSelected(%p, %d)", @@ -2591,7 +2555,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleTableRowSelections(jobject accessibleTable, jint count, jint *selections) { - jthrowable exception; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleTableRowSelections(%p, %d %p)", accessibleTable, count, selections); @@ -2618,7 +2581,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableRowSelections(jobject accessibleT jint AccessBridgeJavaEntryPoints::getAccessibleTableColumnSelectionCount(jobject accessibleTable) { - jthrowable exception; jint count; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleTableColumnSelectionCount(%p)", @@ -2643,7 +2605,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableColumnSelectionCount(jobject acce BOOL AccessBridgeJavaEntryPoints::isAccessibleTableColumnSelected(jobject accessibleTable, jint column) { - jthrowable exception; BOOL result; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::isAccessibleTableColumnSelected(%p, %d)", @@ -2668,7 +2629,6 @@ AccessBridgeJavaEntryPoints::isAccessibleTableColumnSelected(jobject accessibleT BOOL AccessBridgeJavaEntryPoints::getAccessibleTableColumnSelections(jobject accessibleTable, jint count, jint *selections) { - jthrowable exception; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleTableColumnSelections(%p, %d, %p)", accessibleTable, count, selections); @@ -2694,7 +2654,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableColumnSelections(jobject accessib jint AccessBridgeJavaEntryPoints::getAccessibleTableRow(jobject accessibleTable, jint index) { - jthrowable exception; jint result; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleTableRow(%p, index=%d)", @@ -2718,7 +2677,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableRow(jobject accessibleTable, jint jint AccessBridgeJavaEntryPoints::getAccessibleTableColumn(jobject accessibleTable, jint index) { - jthrowable exception; jint result; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleTableColumn(%p, index=%d)", @@ -2742,7 +2700,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTableColumn(jobject accessibleTable, j jint AccessBridgeJavaEntryPoints::getAccessibleTableIndex(jobject accessibleTable, jint row, jint column) { - jthrowable exception; jint result; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleTableIndex(%p, row=%d, col=%d)", @@ -2773,7 +2730,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleRelationSet(jobject accessibleContext, AccessibleRelationSetInfo *relationSet) { - jthrowable exception; const wchar_t *stringBytes; jsize length; @@ -2853,7 +2809,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleHypertext(jobject accessibleContext, AccessibleHypertextInfo *hypertext) { - jthrowable exception; const wchar_t *stringBytes; jsize length; @@ -2953,7 +2908,6 @@ BOOL AccessBridgeJavaEntryPoints::activateAccessibleHyperlink(jobject accessibleContext, jobject accessibleHyperlink) { - jthrowable exception; BOOL returnVal; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::activateAccessibleHyperlink(%p, %p):", @@ -2983,7 +2937,6 @@ AccessBridgeJavaEntryPoints::getAccessibleHypertextExt(const jobject accessibleC const jint nStartIndex, /* OUT */ AccessibleHypertextInfo *hypertext) { - jthrowable exception; const wchar_t *stringBytes; jsize length; PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleHypertextExt(%p, %p, startIndex = %d)", @@ -3084,8 +3037,6 @@ AccessBridgeJavaEntryPoints::getAccessibleHypertextExt(const jobject accessibleC jint AccessBridgeJavaEntryPoints::getAccessibleHyperlinkCount(const jobject accessibleContext) { - jthrowable exception; - PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleHyperlinkCount(%X)", accessibleContext); @@ -3106,8 +3057,6 @@ jint AccessBridgeJavaEntryPoints::getAccessibleHyperlinkCount(const jobject acce jint AccessBridgeJavaEntryPoints::getAccessibleHypertextLinkIndex(const jobject hypertext, const jint nIndex) { - jthrowable exception; - PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleHypertextLinkIndex(%p, index = %d)", hypertext, nIndex); @@ -3129,7 +3078,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleHyperlink(jobject hypertext, const jint index, /* OUT */ AccessibleHyperlinkInfo *info) { - jthrowable exception; const wchar_t *stringBytes; jsize length; @@ -3202,8 +3150,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleHyperlink(jobject hypertext, BOOL AccessBridgeJavaEntryPoints::getAccessibleKeyBindings(jobject accessibleContext, AccessibleKeyBindings *keyBindings) { - jthrowable exception; - PrintDebugString("[INFO]: ##### AccessBridgeJavaEntryPoints::getAccessibleKeyBindings(%p, %p)", accessibleContext, keyBindings); @@ -3249,7 +3195,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleKeyBindings(jobject accessibleCon BOOL AccessBridgeJavaEntryPoints::getAccessibleIcons(jobject accessibleContext, AccessibleIcons *icons) { - jthrowable exception; const wchar_t *stringBytes; jsize length; @@ -3328,7 +3273,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleIcons(jobject accessibleContext, BOOL AccessBridgeJavaEntryPoints::getAccessibleActions(jobject accessibleContext, AccessibleActions *actions) { - jthrowable exception; const wchar_t *stringBytes; jsize length; @@ -3388,7 +3332,6 @@ BOOL AccessBridgeJavaEntryPoints::doAccessibleActions(jobject accessibleContext, AccessibleActionsToDo *actionsToDo, jint *failure) { - jthrowable exception; BOOL returnVal; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::doAccessibleActions(%p, #actions %d %s):", @@ -3436,7 +3379,6 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleTextInfo(jobject accessibleContext, AccessibleTextInfo *textInfo, jint x, jint y) { - jthrowable exception; // Verify the Java VM still exists and AccessibleContext is // an instance of AccessibleText @@ -3495,7 +3437,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTextItems(jobject accessibleContext, AccessibleTextItemsInfo *textItems, jint index) { jstring js; const wchar_t *stringBytes; - jthrowable exception; jsize length; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleTextItems(%p):", accessibleContext); @@ -3607,7 +3548,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTextSelectionInfo(jobject accessibleCo AccessibleTextSelectionInfo *selectionInfo) { jstring js; const wchar_t *stringBytes; - jthrowable exception; jsize length; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleTextSelectionInfo(%p):", @@ -3680,7 +3620,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTextAttributes(jobject accessibleConte jstring js; const wchar_t *stringBytes; jobject AttributeSet; - jthrowable exception; jsize length; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleTextAttributes(%p):", accessibleContext); @@ -4174,8 +4113,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTextAttributes(jobject accessibleConte BOOL AccessBridgeJavaEntryPoints::getAccessibleTextRect(jobject accessibleContext, AccessibleTextRectInfo *rectInfo, jint index) { - jthrowable exception; - PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleTextRect(%p), index = %d", accessibleContext, index); @@ -4244,8 +4181,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTextRect(jobject accessibleContext, Ac BOOL AccessBridgeJavaEntryPoints::getCaretLocation(jobject accessibleContext, AccessibleTextRectInfo *rectInfo, jint index) { - jthrowable exception; - PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getCaretLocation(%p), index = %d", accessibleContext, index); @@ -4311,8 +4246,6 @@ AccessBridgeJavaEntryPoints::getCaretLocation(jobject accessibleContext, Accessi BOOL AccessBridgeJavaEntryPoints::getAccessibleTextLineBounds(jobject accessibleContext, jint index, jint *startIndex, jint *endIndex) { - jthrowable exception; - PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleTextLineBounds(%p):", accessibleContext); // Verify the Java VM still exists and AccessibleContext is @@ -4353,7 +4286,6 @@ AccessBridgeJavaEntryPoints::getAccessibleTextRange(jobject accessibleContext, jint start, jint end, wchar_t *text, short len) { jstring js; const wchar_t *stringBytes; - jthrowable exception; jsize length; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleTextRange(%p, %d, %d, *text, %d):", accessibleContext, start, end, len); @@ -4412,7 +4344,6 @@ BOOL AccessBridgeJavaEntryPoints::getCurrentAccessibleValueFromContext(jobject accessibleContext, wchar_t *value, short len) { jstring js; const wchar_t *stringBytes; - jthrowable exception; jsize length; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getCurrentAccessibleValueFromContext(%p):", accessibleContext); @@ -4453,7 +4384,6 @@ BOOL AccessBridgeJavaEntryPoints::getMaximumAccessibleValueFromContext(jobject accessibleContext, wchar_t *value, short len) { jstring js; const wchar_t *stringBytes; - jthrowable exception; jsize length; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getMaximumAccessibleValueFromContext(%p):", accessibleContext); @@ -4494,7 +4424,6 @@ BOOL AccessBridgeJavaEntryPoints::getMinimumAccessibleValueFromContext(jobject accessibleContext, wchar_t *value, short len) { jstring js; const wchar_t *stringBytes; - jthrowable exception; jsize length; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getMinimumAccessibleValueFromContext(%p):", accessibleContext); @@ -4536,7 +4465,6 @@ AccessBridgeJavaEntryPoints::getMinimumAccessibleValueFromContext(jobject access void AccessBridgeJavaEntryPoints::addAccessibleSelectionFromContext(jobject accessibleContext, int i) { - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::addAccessibleSelectionFromContext(%p):", accessibleContext); @@ -4554,7 +4482,6 @@ AccessBridgeJavaEntryPoints::addAccessibleSelectionFromContext(jobject accessibl void AccessBridgeJavaEntryPoints::clearAccessibleSelectionFromContext(jobject accessibleContext) { - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::clearAccessibleSelectionFromContext(%p):", accessibleContext); @@ -4574,7 +4501,6 @@ jobject AccessBridgeJavaEntryPoints::getAccessibleSelectionFromContext(jobject accessibleContext, int i) { jobject returnedAccessibleContext; jobject globalRef; - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleSelectionFromContext(%p):", accessibleContext); @@ -4600,7 +4526,6 @@ AccessBridgeJavaEntryPoints::getAccessibleSelectionFromContext(jobject accessibl int AccessBridgeJavaEntryPoints::getAccessibleSelectionCountFromContext(jobject accessibleContext) { int count; - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::getAccessibleSelectionCountFromContext(%p):", accessibleContext); @@ -4621,7 +4546,6 @@ AccessBridgeJavaEntryPoints::getAccessibleSelectionCountFromContext(jobject acce BOOL AccessBridgeJavaEntryPoints::isAccessibleChildSelectedFromContext(jobject accessibleContext, int i) { jboolean result; - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::isAccessibleChildSelectedFromContext(%p):", accessibleContext); @@ -4644,7 +4568,6 @@ AccessBridgeJavaEntryPoints::isAccessibleChildSelectedFromContext(jobject access void AccessBridgeJavaEntryPoints::removeAccessibleSelectionFromContext(jobject accessibleContext, int i) { - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::removeAccessibleSelectionFromContext(%p):", accessibleContext); @@ -4662,7 +4585,6 @@ AccessBridgeJavaEntryPoints::removeAccessibleSelectionFromContext(jobject access void AccessBridgeJavaEntryPoints::selectAllAccessibleSelectionFromContext(jobject accessibleContext) { - jthrowable exception; PrintDebugString("[INFO]: Calling AccessBridgeJavaEntryPoints::selectAllAccessibleSelectionFromContext(%p):", accessibleContext); @@ -4683,7 +4605,6 @@ AccessBridgeJavaEntryPoints::selectAllAccessibleSelectionFromContext(jobject acc BOOL AccessBridgeJavaEntryPoints::addJavaEventNotification(jlong type) { - jthrowable exception; PrintDebugString("[INFO]: in AccessBridgeJavaEntryPoints::addJavaEventNotification(%016I64X);", type); @@ -4701,7 +4622,6 @@ AccessBridgeJavaEntryPoints::addJavaEventNotification(jlong type) { BOOL AccessBridgeJavaEntryPoints::removeJavaEventNotification(jlong type) { - jthrowable exception; PrintDebugString("[INFO]: in AccessBridgeJavaEntryPoints::removeJavaEventNotification(%016I64X):", type); @@ -4719,7 +4639,6 @@ AccessBridgeJavaEntryPoints::removeJavaEventNotification(jlong type) { BOOL AccessBridgeJavaEntryPoints::addAccessibilityEventNotification(jlong type) { - jthrowable exception; PrintDebugString("[INFO]: in AccessBridgeJavaEntryPoints::addAccessibilityEventNotification(%016I64X);", type); @@ -4739,7 +4658,6 @@ AccessBridgeJavaEntryPoints::addAccessibilityEventNotification(jlong type) { BOOL AccessBridgeJavaEntryPoints::removeAccessibilityEventNotification(jlong type) { - jthrowable exception; PrintDebugString("[INFO]: in AccessBridgeJavaEntryPoints::removeAccessibilityEventNotification(%016I64X):", type); @@ -4753,4 +4671,4 @@ AccessBridgeJavaEntryPoints::removeAccessibilityEventNotification(jlong type) { return FALSE; } return TRUE; -} +} \ No newline at end of file diff --git a/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java b/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java index 2f6fc4d4df2..a7912e3234d 100644 --- a/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java +++ b/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -52,8 +52,6 @@ public String type() { public VirtualMachine attachVirtualMachine(String vmid) throws AttachNotSupportedException, IOException { - checkAttachPermission(); - // AttachNotSupportedException will be thrown if the target VM can be determined // to be not attachable. testAttachable(vmid); @@ -72,7 +70,6 @@ public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) // implementation which only returns a list of attachable VMs. if (vmd instanceof HotSpotVirtualMachineDescriptor) { assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable(); - checkAttachPermission(); return new VirtualMachineImpl(this, vmd.id()); } else { return attachVirtualMachine(vmd.id()); diff --git a/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java b/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java index fd89af02511..156590885bf 100644 --- a/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java +++ b/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -49,8 +49,6 @@ public String type() { public VirtualMachine attachVirtualMachine(String vmid) throws AttachNotSupportedException, IOException { - checkAttachPermission(); - // AttachNotSupportedException will be thrown if the target VM can be determined // to be not attachable. testAttachable(vmid); @@ -69,7 +67,6 @@ public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) // implementation which only returns a list of attachable VMs. if (vmd instanceof HotSpotVirtualMachineDescriptor) { assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable(); - checkAttachPermission(); return new VirtualMachineImpl(this, vmd.id()); } else { return attachVirtualMachine(vmd.id()); diff --git a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java index 35ce808c187..69cd4dcdb99 100644 --- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java @@ -34,7 +34,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Optional; + +import java.util.regex.Pattern; import static java.nio.charset.StandardCharsets.UTF_8; @@ -51,26 +52,9 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine { private static final Path TMPDIR = Path.of("/tmp"); private static final Path PROC = Path.of("/proc"); - private static final Path NS_MNT = Path.of("ns/mnt"); - private static final Path NS_PID = Path.of("ns/pid"); - private static final Path SELF = PROC.resolve("self"); private static final Path STATUS = Path.of("status"); private static final Path ROOT_TMP = Path.of("root/tmp"); - private static final Optional SELF_MNT_NS; - - static { - Path nsPath = null; - - try { - nsPath = Files.readSymbolicLink(SELF.resolve(NS_MNT)); - } catch (IOException _) { - // do nothing - } finally { - SELF_MNT_NS = Optional.ofNullable(nsPath); - } - } - String socket_path; /** @@ -97,13 +81,16 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine { if (!socket_file.exists()) { // Keep canonical version of File, to delete, in case target process ends and /proc link has gone: File f = createAttachFile(pid, ns_pid).getCanonicalFile(); + + boolean timedout = false; + try { - sendQuitTo(pid); + checkCatchesAndSendQuitTo(pid, false); // give the target VM time to start the attach mechanism final int delay_step = 100; final long timeout = attachTimeout(); - long time_spend = 0; + long time_spent = 0; long delay = 0; do { // Increase timeout on each attempt to reduce polling @@ -112,18 +99,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine { Thread.sleep(delay); } catch (InterruptedException x) { } - time_spend += delay; - if (time_spend > timeout/2 && !socket_file.exists()) { + timedout = (time_spent += delay) > timeout; + + if (time_spent > timeout/2 && !socket_file.exists()) { // Send QUIT again to give target VM the last chance to react - sendQuitTo(pid); + checkCatchesAndSendQuitTo(pid, !timedout); } - } while (time_spend <= timeout && !socket_file.exists()); + } while (!timedout && !socket_file.exists()); + if (!socket_file.exists()) { throw new AttachNotSupportedException( String.format("Unable to open socket file %s: " + "target process %d doesn't respond within %dms " + - "or HotSpot VM not loaded", socket_path, pid, - time_spend)); + "or HotSpot VM not loaded", socket_path, pid, time_spent)); } } finally { f.delete(); @@ -257,79 +245,32 @@ private File createAttachFile(long pid, long ns_pid) throws AttachNotSupportedEx } private String findTargetProcessTmpDirectory(long pid, long ns_pid) throws AttachNotSupportedException, IOException { - // We need to handle at least 4 different cases: - // 1. Caller and target processes share PID namespace and root filesystem (host to host or container to - // container with both /tmp mounted between containers). - // 2. Caller and target processes share PID namespace and root filesystem but the target process has elevated - // privileges (host to host). - // 3. Caller and target processes share PID namespace but NOT root filesystem (container to container). - // 4. Caller and target processes share neither PID namespace nor root filesystem (host to container). - - Optional target = ProcessHandle.of(pid); - Optional ph = target; - long nsPid = ns_pid; - Optional prevPidNS = Optional.empty(); - - while (ph.isPresent()) { - final var curPid = ph.get().pid(); - final var procPidPath = PROC.resolve(Long.toString(curPid)); - Optional targetMountNS = Optional.empty(); - - try { - // attempt to read the target's mnt ns id - targetMountNS = Optional.ofNullable(Files.readSymbolicLink(procPidPath.resolve(NS_MNT))); - } catch (IOException _) { - // if we fail to read the target's mnt ns id then we either don't have access or it no longer exists! - if (!Files.exists(procPidPath)) { - throw new IOException(String.format("unable to attach, %s non-existent! process: %d terminated", procPidPath, pid)); - } - // the process still exists, but we don't have privileges to read its procfs - } - - final var sameMountNS = SELF_MNT_NS.isPresent() && SELF_MNT_NS.equals(targetMountNS); - - if (sameMountNS) { - return TMPDIR.toString(); // we share TMPDIR in common! - } else { - // we could not read the target's mnt ns - final var procPidRootTmp = procPidPath.resolve(ROOT_TMP); - if (Files.isReadable(procPidRootTmp)) { - return procPidRootTmp.toString(); // not in the same mnt ns but tmp is accessible via /proc - } - } - - // let's attempt to obtain the pid ns, best efforts to avoid crossing pid ns boundaries (as with a container) - Optional curPidNS = Optional.empty(); - - try { - // attempt to read the target's pid ns id - curPidNS = Optional.ofNullable(Files.readSymbolicLink(procPidPath.resolve(NS_PID))); - } catch (IOException _) { - // if we fail to read the target's pid ns id then we either don't have access or it no longer exists! - if (!Files.exists(procPidPath)) { - throw new IOException(String.format("unable to attach, %s non-existent! process: %d terminated", procPidPath, pid)); - } - // the process still exists, but we don't have privileges to read its procfs - } - - // recurse "up" the process hierarchy if appropriate. PID 1 cannot have a parent in the same namespace - final var havePidNSes = prevPidNS.isPresent() && curPidNS.isPresent(); - final var ppid = ph.get().parent(); - - if (ppid.isPresent() && (havePidNSes && curPidNS.equals(prevPidNS)) || (!havePidNSes && nsPid > 1)) { - ph = ppid; - nsPid = getNamespacePid(ph.get().pid()); // get the ns pid of the parent - prevPidNS = curPidNS; - } else { - ph = Optional.empty(); - } - } - - if (target.orElseThrow(AttachNotSupportedException::new).isAlive()) { - return TMPDIR.toString(); // fallback... - } else { - throw new IOException(String.format("unable to attach, process: %d terminated", pid)); - } + final var procPidRoot = PROC.resolve(Long.toString(pid)).resolve(ROOT_TMP); + + /* We need to handle at least 4 different cases: + * 1. Caller and target processes share PID namespace and root filesystem (host to host or container to + * container with both /tmp mounted between containers). + * 2. Caller and target processes share PID namespace and root filesystem but the target process has elevated + * privileges (host to host). + * 3. Caller and target processes share PID namespace but NOT root filesystem (container to container). + * 4. Caller and target processes share neither PID namespace nor root filesystem (host to container) + * + * if target is elevated, we cant use /proc//... so we have to fallback to /tmp, but that may not be shared + * with the target/attachee process, we can try, except in the case where the ns_pid also exists in this pid ns + * which is ambiguous, if we share /tmp with the intended target, the attach will succeed, if we do not, + * then we will potentially attempt to attach to some arbitrary process with the same pid (in this pid ns) + * as that of the intended target (in its * pid ns). + * + * so in that case we should prehaps throw - or risk sending SIGQUIT to some arbitrary process... which could kill it + * + * however we can also check the target pid's signal masks to see if it catches SIGQUIT and only do so if in + * fact it does ... this reduces the risk of killing an innocent process in the current ns as opposed to + * attaching to the actual target JVM ... c.f: checkCatchesAndSendQuitTo() below. + * + * note that if pid == ns_pid we are in a shared pid ns with the target and may (potentially) share /tmp + */ + + return (Files.isWritable(procPidRoot) ? procPidRoot : TMPDIR).toString(); } /* @@ -378,6 +319,70 @@ private long getNamespacePid(long pid) throws AttachNotSupportedException, IOExc } } + private static final String FIELD = "field"; + private static final String MASK = "mask"; + + private static final Pattern SIGNAL_MASK_PATTERN = Pattern.compile("(?<" + FIELD + ">Sig\\p{Alpha}{3}):\\s+(?<" + MASK + ">\\p{XDigit}{16}).*"); + + private static final long SIGQUIT = 0b100; // mask bit for SIGQUIT + + private static boolean checkCatchesAndSendQuitTo(int pid, boolean throwIfNotReady) throws AttachNotSupportedException, IOException { + var quitIgn = false; + var quitBlk = false; + var quitCgt = false; + + final var procPid = PROC.resolve(Integer.toString(pid)); + + var readBlk = false; + var readIgn = false; + var readCgt = false; + + + if (!Files.exists(procPid)) throw new IOException("non existent JVM pid: " + pid); + + for (var line : Files.readAllLines(procPid.resolve("status"))) { + + if (!line.startsWith("Sig")) continue; // to speed things up ... avoids the matcher/RE invocation... + + final var m = SIGNAL_MASK_PATTERN.matcher(line); + + if (!m.matches()) continue; + + var sigmask = m.group(MASK); + final var slen = sigmask.length(); + + sigmask = sigmask.substring(slen / 2 , slen); // only really interested in the non r/t signals ... + + final var sigquit = (Long.valueOf(sigmask, 16) & SIGQUIT) != 0L; + + switch (m.group(FIELD)) { + case "SigBlk": { quitBlk = sigquit; readBlk = true; break; } + case "SigIgn": { quitIgn = sigquit; readIgn = true; break; } + case "SigCgt": { quitCgt = sigquit; readCgt = true; break; } + } + + if (readBlk && readIgn && readCgt) break; + } + + final boolean okToSendQuit = (!quitIgn && quitCgt); // ignore blocked as it may be temporary ... + + if (okToSendQuit) { + sendQuitTo(pid); + } else if (throwIfNotReady) { + final var cmdline = Files.lines(procPid.resolve("cmdline")).findFirst(); + + var cmd = "null"; // default + + if (cmdline.isPresent()) { + cmd = cmdline.get(); + cmd = cmd.substring(0, cmd.length() - 1); // remove trailing \0 + } + + throw new AttachNotSupportedException("pid: " + pid + " cmd: '" + cmd + "' state is not ready to participate in attach handshake!"); + } + + return okToSendQuit; + } //-- native methods diff --git a/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java b/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java index d44684f81af..d57fd7961ab 100644 --- a/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java +++ b/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -49,8 +49,6 @@ public String type() { public VirtualMachine attachVirtualMachine(String vmid) throws AttachNotSupportedException, IOException { - checkAttachPermission(); - // AttachNotSupportedException will be thrown if the target VM can be determined // to be not attachable. testAttachable(vmid); @@ -69,7 +67,6 @@ public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) // implementation which only returns a list of attachable VMs. if (vmd instanceof HotSpotVirtualMachineDescriptor) { assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable(); - checkAttachPermission(); return new VirtualMachineImpl(this, vmd.id()); } else { return attachVirtualMachine(vmd.id()); diff --git a/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java b/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java index da3f61e49ce..6446473d9d6 100644 --- a/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java +++ b/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java @@ -32,7 +32,6 @@ import java.util.List; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; -import com.sun.tools.attach.AttachPermission; import com.sun.tools.attach.AttachNotSupportedException; import java.util.ServiceLoader; @@ -84,10 +83,6 @@ public abstract class AttachProvider { * Initializes a new instance of this class. */ protected AttachProvider() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(new AttachPermission("createAttachProvider")); } /** diff --git a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotAttachProvider.java b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotAttachProvider.java index c73a15db921..f833ee1afb3 100644 --- a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotAttachProvider.java +++ b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotAttachProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.tools.attach; import com.sun.tools.attach.VirtualMachineDescriptor; -import com.sun.tools.attach.AttachPermission; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.spi.AttachProvider; @@ -47,16 +46,6 @@ public abstract class HotSpotAttachProvider extends AttachProvider { public HotSpotAttachProvider() { } - public void checkAttachPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission( - new AttachPermission("attachVirtualMachine") - ); - } - } - /* * This listVirtualMachines implementation is based on jvmstat. Can override * this in platform implementations when there is a more efficient mechanism diff --git a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java index 10d23f33535..ace00100aab 100644 --- a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java +++ b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java @@ -37,7 +37,6 @@ import java.io.InputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Properties; import java.util.stream.Collectors; @@ -54,8 +53,7 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine { @SuppressWarnings("removal") private static long pid() { - PrivilegedAction pa = () -> ProcessHandle.current(); - return AccessController.doPrivileged(pa).pid(); + return ProcessHandle.current().pid(); } private static final boolean ALLOW_ATTACH_SELF; @@ -361,12 +359,7 @@ protected int detectVersion() throws IOException { */ protected boolean isAPIv2Enabled() { // if "jdk.attach.compat" property is set, only v1 is enabled. - try { - String value = System.getProperty("jdk.attach.compat"); - return !("true".equalsIgnoreCase(value)); - } catch (SecurityException se) { - } - return true; + return !Boolean.getBoolean("jdk.attach.compat"); } /* @@ -563,7 +556,6 @@ long attachTimeout() { String s = System.getProperty("sun.tools.attach.attachTimeout"); attachTimeout = Long.parseLong(s); - } catch (SecurityException se) { } catch (NumberFormatException ne) { } if (attachTimeout <= 0) { diff --git a/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java b/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java index 503d9592370..f4826a81366 100644 --- a/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java +++ b/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -51,8 +51,6 @@ public String type() { public VirtualMachine attachVirtualMachine(String vmid) throws AttachNotSupportedException, IOException { - checkAttachPermission(); - // AttachNotSupportedException will be thrown if the target VM can be determined // to be not attachable. testAttachable(vmid); diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java index 041ab301d64..2f259bfa191 100644 --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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,9 +23,6 @@ * questions. */ -/* - */ - package sun.nio.cs.ext; import java.nio.ByteBuffer; @@ -67,8 +64,6 @@ protected static class Encoder extends CharsetEncoder { public static final byte PLANE2 = (byte)0xA2; public static final byte PLANE3 = (byte)0xA3; - protected final byte maximumDesignatorLength = 4; - protected byte[] SODesig, SS2Desig = null, SS3Desig = null; diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/SJIS_0213.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/SJIS_0213.java index 1ac70f2d2e3..5853d01bdfc 100644 --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/SJIS_0213.java +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/SJIS_0213.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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,10 +31,6 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Arrays; -import sun.nio.cs.CharsetMapping; import sun.nio.cs.*; /* @@ -77,13 +73,8 @@ public CharsetEncoder newEncoder() { } private static class Holder { - @SuppressWarnings("removal") - static final CharsetMapping mapping = AccessController.doPrivileged( - new PrivilegedAction() { - public CharsetMapping run() { - return CharsetMapping.get(SJIS_0213.class.getResourceAsStream("sjis0213.dat")); - } - }); + static final CharsetMapping mapping = + CharsetMapping.get(SJIS_0213.class.getResourceAsStream("sjis0213.dat")); } protected static class Decoder extends CharsetDecoder { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacScope.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacScope.java index 3dfbbc1ff52..9b3a50a035a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacScope.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacScope.java @@ -87,12 +87,26 @@ public JavacScope getEnclosingScope() { } else { // synthesize an outermost "star-import" scope return new JavacScope(env) { - public boolean isStarImportScope() { - return true; + @Override + public ScopeType getScopeType() { + return ScopeType.STAR_IMPORT; } @DefinedBy(Api.COMPILER_TREE) public JavacScope getEnclosingScope() { - return null; + return new JavacScope(env) { + @Override + public ScopeType getScopeType() { + return ScopeType.MODULE_IMPORT; + } + @Override @DefinedBy(Api.COMPILER_TREE) + public JavacScope getEnclosingScope() { + return null; + } + @Override @DefinedBy(Api.COMPILER_TREE) + public Iterable getLocalElements() { + return env.toplevel.moduleImportScope.getSymbols(VALIDATOR); + } + }; } @DefinedBy(Api.COMPILER_TREE) public Iterable getLocalElements() { @@ -122,21 +136,27 @@ public Env getEnv() { return env; } - public boolean isStarImportScope() { - return false; + public ScopeType getScopeType() { + return ScopeType.ORDINARY; } public boolean equals(Object other) { return other instanceof JavacScope javacScope && env.equals(javacScope.env) - && isStarImportScope() == javacScope.isStarImportScope(); + && getScopeType()== javacScope.getScopeType(); } public int hashCode() { - return env.hashCode() + (isStarImportScope() ? 1 : 0); + return env.hashCode() + getScopeType().hashCode(); } public String toString() { - return "JavacScope[env=" + env + ",starImport=" + isStarImportScope() + "]"; + return "JavacScope[env=" + env + ", scope type=" + getScopeType() + "]"; + } + + private enum ScopeType { + ORDINARY, + STAR_IMPORT, + MODULE_IMPORT; } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java index 8f84f5d7fbd..ce719230455 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -1402,6 +1402,7 @@ public void putComment(JCTree tree, Comment c) { jcCompilationUnit.namedImportScope = new NamedImportScope(psym); jcCompilationUnit.packge = psym; jcCompilationUnit.starImportScope = new StarImportScope(psym); + jcCompilationUnit.moduleImportScope = new StarImportScope(psym); jcCompilationUnit.toplevelScope = WriteableScope.create(psym); return new TreePath(jcCompilationUnit); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java index e5d9a9e2ac4..2491cd31f0d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java @@ -70,7 +70,6 @@ public enum Kind { AMBIGUOUS(Category.RESOLUTION_TARGET), // overloaded target HIDDEN(Category.RESOLUTION_TARGET), // not overloaded non-target STATICERR(Category.RESOLUTION_TARGET), // overloaded? target - MISSING_ENCL(Category.RESOLUTION), // not overloaded non-target BAD_RESTRICTED_TYPE(Category.RESOLUTION), // not overloaded non-target ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR), // not overloaded non-target WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD), // overloaded target diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java index d024dc75225..622c13d8b47 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java @@ -181,7 +181,7 @@ public enum LintCategory { CLASSFILE("classfile"), /** - * Warn about"dangling" documentation comments, + * Warn about "dangling" documentation comments, * not attached to any declaration. */ DANGLING_DOC_COMMENTS("dangling-doc-comments"), diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index 5e9a75a0b6b..c66e1758616 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -27,6 +27,7 @@ import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Source.Feature; +import com.sun.tools.javac.code.Symbol.ModuleSymbol; import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Warnings; @@ -133,11 +134,23 @@ public boolean participatesInPreview(Symtab syms, Symbol s, Symbol previewSymbol return true; } + return participatesInPreview(syms, s.packge().modle); + } + + /** + * Returns true if module {@code m} is deemed to participate in the preview, and + * therefore no warnings or errors will be produced. + * + * @param syms the symbol table + * @param m the module to check + * @return true if {@code m} is participating in the preview of {@code previewSymbol} + */ + public boolean participatesInPreview(Symtab syms, ModuleSymbol m) { // If java.base's jdk.internal.javac package is exported to s's module then // s participates in the preview API return syms.java_base.exports.stream() .filter(ed -> ed.packge.fullname == names.jdk_internal_javac) - .anyMatch(ed -> ed.modules.contains(s.packge().modle)); + .anyMatch(ed -> ed.modules.contains(m)); } /** @@ -211,6 +224,7 @@ public boolean isPreview(Feature feature) { case FLEXIBLE_CONSTRUCTORS -> true; case PRIMITIVE_PATTERNS -> true; case MODULE_IMPORTS -> true; + case JAVA_BASE_TRANSITIVE -> true; //Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing). //When real preview features will be added, this method can be implemented to return 'true' //for those selected features, and 'false' for all the others. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java index 4a226e4de3b..572a7b12675 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java @@ -262,6 +262,7 @@ public enum Feature { PRIMITIVE_PATTERNS(JDK23, Fragments.FeaturePrimitivePatterns, DiagKind.PLURAL), FLEXIBLE_CONSTRUCTORS(JDK22, Fragments.FeatureFlexibleConstructors, DiagKind.NORMAL), MODULE_IMPORTS(JDK23, Fragments.FeatureModuleImports, DiagKind.PLURAL), + JAVA_BASE_TRANSITIVE(JDK24, Fragments.FeatureJavaBaseTransitive, DiagKind.PLURAL), PRIVATE_MEMBERS_IN_PERMITS_CLAUSE(JDK19), ERASE_POLY_SIG_RETURN_TYPE(JDK24), ; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 07a136c1700..62c12334629 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2590,8 +2590,7 @@ public void visitApply(JCMethodInvocation tree) { } else if (methName == names._super) { // qualifier omitted; check for existence // of an appropriate implicit qualifier. - rs.resolveImplicitThis(tree.meth.pos(), - localEnv, site, true); + checkNewInnerClass(tree.meth.pos(), localEnv, site, true); } } else if (tree.meth.hasTag(SELECT)) { log.error(tree.meth.pos(), @@ -2798,11 +2797,9 @@ public void visitNewClass(final JCNewClass tree) { log.error(tree.encl.pos(), Errors.QualifiedNewOfStaticClass(clazztype.tsym)); } } - } else if (!clazztype.tsym.isInterface() && - (clazztype.tsym.flags_field & NOOUTERTHIS) == 0 && - clazztype.getEnclosingType().hasTag(CLASS)) { + } else { // Check for the existence of an apropos outer instance - rs.resolveImplicitThis(tree.pos(), env, clazztype); + checkNewInnerClass(tree.pos(), env, clazztype, false); } // Attribute constructor arguments. @@ -3067,6 +3064,24 @@ public void report(DiagnosticPosition _unused, JCDiagnostic details) { }; } + void checkNewInnerClass(DiagnosticPosition pos, Env env, Type type, boolean isSuper) { + boolean isLocal = type.tsym.owner.kind == MTH; + if ((type.tsym.flags() & (INTERFACE | ENUM | RECORD)) != 0 || + (!isLocal && !type.tsym.isInner()) || + (isSuper && env.enclClass.sym.isAnonymous())) { + // nothing to check + return; + } + Symbol res = isLocal ? + rs.findLocalClassOwner(env, type.tsym) : + rs.findSelfContaining(pos, env, type.getEnclosingType().tsym, isSuper); + if (res.exists()) { + rs.accessBase(res, pos, env.enclClass.sym.type, names._this, true); + } else { + log.error(pos, Errors.EnclClassRequired(type.tsym)); + } + } + /** Make an attributed null check tree. */ public JCExpression makeNullCheck(JCExpression arg) { @@ -3639,7 +3654,6 @@ public void visitReference(final JCMemberReference that) { boolean targetError; switch (refSym.kind) { case ABSENT_MTH: - case MISSING_ENCL: targetError = false; break; case WRONG_MTH: @@ -3690,11 +3704,7 @@ public void visitReference(final JCMemberReference that) { } if (!env.info.attributionMode.isSpeculative && that.getMode() == JCMemberReference.ReferenceMode.NEW) { - Type enclosingType = exprType.getEnclosingType(); - if (enclosingType != null && enclosingType.hasTag(CLASS)) { - // Check for the existence of an appropriate outer instance - rs.resolveImplicitThis(that.pos(), env, exprType); - } + checkNewInnerClass(that.pos(), env, exprType, false); } if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { @@ -4188,6 +4198,7 @@ public void visitBindingPattern(JCBindingPattern tree) { if (chk.checkUnique(tree.var.pos(), v, env.info.scope)) { chk.checkTransparentVar(tree.var.pos(), v, env.info.scope); } + chk.validate(tree.var.vartype, env, true); if (tree.var.isImplicitlyTyped()) { setSyntheticVariableType(tree.var, type == Type.noType ? syms.errType : type); @@ -4197,7 +4208,6 @@ public void visitBindingPattern(JCBindingPattern tree) { annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v, tree.var.pos()); } annotate.flush(); - chk.validate(tree.var.vartype, env, true); result = tree.type; if (v.isUnnamedVariable()) { matchBindings = MatchBindingsComputer.EMPTY; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java index 926be3b6e26..1042a9747ba 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java @@ -223,6 +223,7 @@ Env topLevelEnv(JCCompilationUnit tree) { tree.toplevelScope = WriteableScope.create(tree.packge); tree.namedImportScope = new NamedImportScope(tree.packge); tree.starImportScope = new StarImportScope(tree.packge); + tree.moduleImportScope = new StarImportScope(tree.packge); localEnv.info.scope = tree.toplevelScope; localEnv.info.lint = lint; return localEnv; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 29ab8435ada..df28548152a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -910,7 +910,7 @@ private Set reduceBindingPatterns(Type selectorType, Set toAdd = new HashSet<>(); for (Type sup : types.directSupertypes(bpOne.type)) { - ClassSymbol clazz = (ClassSymbol) sup.tsym; + ClassSymbol clazz = (ClassSymbol) types.erasure(sup).tsym; clazz.complete(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java index 3d893252218..bfad334d194 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -64,8 +64,11 @@ import com.sun.tools.javac.code.Directive.UsesDirective; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Flags.Flag; +import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.ModuleFinder; +import com.sun.tools.javac.code.Preview; import com.sun.tools.javac.code.Source; import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol; @@ -74,6 +77,7 @@ import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.ModuleFlags; +import com.sun.tools.javac.code.Symbol.ModuleResolutionFlags; import com.sun.tools.javac.code.Symbol.ModuleSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symtab; @@ -99,6 +103,7 @@ import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -112,14 +117,9 @@ import static com.sun.tools.javac.code.Flags.PUBLIC; import static com.sun.tools.javac.code.Flags.UNATTRIBUTED; -import com.sun.tools.javac.code.Kinds; - import static com.sun.tools.javac.code.Kinds.Kind.ERR; import static com.sun.tools.javac.code.Kinds.Kind.MDL; import static com.sun.tools.javac.code.Kinds.Kind.MTH; -import com.sun.tools.javac.code.Lint; - -import com.sun.tools.javac.code.Symbol.ModuleResolutionFlags; import static com.sun.tools.javac.code.TypeTag.CLASS; @@ -141,6 +141,7 @@ public class Modules extends JCTree.Visitor { private final Symtab syms; private final Attr attr; private final Check chk; + private final Preview preview; private final DeferredLintHandler deferredLintHandler; private final TypeEnvs typeEnvs; private final Types types; @@ -150,6 +151,7 @@ public class Modules extends JCTree.Visitor { private final Target target; private final boolean allowModules; private final boolean allowAccessIntoSystem; + private final boolean allowRequiresTransitiveJavaBase; public final boolean multiModuleMode; @@ -192,6 +194,7 @@ protected Modules(Context context) { syms = Symtab.instance(context); attr = Attr.instance(context); chk = Check.instance(context); + preview = Preview.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); typeEnvs = TypeEnvs.instance(context); moduleFinder = ModuleFinder.instance(context); @@ -203,6 +206,12 @@ protected Modules(Context context) { Options options = Options.instance(context); allowAccessIntoSystem = options.isUnset(Option.RELEASE); + + Preview preview = Preview.instance(context); + + allowRequiresTransitiveJavaBase = + Feature.JAVA_BASE_TRANSITIVE.allowedInSource(source) && + (!preview.isPreview(Feature.JAVA_BASE_TRANSITIVE) || preview.isEnabled()); lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option); multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH); @@ -249,7 +258,12 @@ public void initModules(List trees) { public boolean enter(List trees, ClassSymbol c) { Assert.check(rootModules != null || inInitModules || !allowModules); - return enter(trees, modules -> {}, c); + return enter(trees, modules -> { + //make sure java.base is completed in all cases before continuing. + //the next steps may query if the current module participates in preview, + //and that requires a completed java.base: + syms.java_base.complete(); + }, c); } private boolean enter(List trees, Consumer> init, ClassSymbol c) { @@ -807,11 +821,16 @@ public void visitRequires(JCRequires tree) { allRequires.add(msym); Set flags = EnumSet.noneOf(RequiresFlag.class); if (tree.isTransitive) { - if (msym == syms.java_base && source.compareTo(Source.JDK10) >= 0) { - log.error(tree.pos(), Errors.ModifierNotAllowedHere(names.transitive)); - } else { - flags.add(RequiresFlag.TRANSITIVE); + if (msym == syms.java_base && + !allowRequiresTransitiveJavaBase && + !preview.participatesInPreview(syms, sym)) { + if (source.compareTo(Source.JDK10) >= 0) { + log.error(DiagnosticFlag.SOURCE_LEVEL, + tree.pos(), + Feature.JAVA_BASE_TRANSITIVE.error(source.name)); + } } + flags.add(RequiresFlag.TRANSITIVE); } if (tree.isStaticPhase) { if (msym == syms.java_base && source.compareTo(Source.JDK10) >= 0) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index b6d7e166902..43a0c61a069 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -2149,23 +2149,32 @@ public interface RecoveryLoadClass { return null; }; - private final RecoveryLoadClass starImportScopeRecovery = (env, name) -> { - Scope importScope = env.toplevel.starImportScope; - Symbol existing = importScope.findFirst(Convert.shortName(name), - sym -> sym.kind == TYP && sym.flatName() == name); + private final RecoveryLoadClass starImportScopeRecovery = + onDemandImportScopeRecovery(false); - if (existing != null) { - try { - existing = finder.loadClass(existing.packge().modle, name); + private final RecoveryLoadClass moduleImportScopeRecovery = + onDemandImportScopeRecovery(true); + + private RecoveryLoadClass onDemandImportScopeRecovery(boolean moduleImportScope) { + return (env, name) -> { + Scope importScope = moduleImportScope ? env.toplevel.moduleImportScope + : env.toplevel.starImportScope; + Symbol existing = importScope.findFirst(Convert.shortName(name), + sym -> sym.kind == TYP && sym.flatName() == name); + + if (existing != null) { + try { + existing = finder.loadClass(existing.packge().modle, name); - return new InvisibleSymbolError(env, true, existing); - } catch (CompletionFailure cf) { - //ignore + return new InvisibleSymbolError(env, true, existing); + } catch (CompletionFailure cf) { + //ignore + } } - } - return null; - }; + return null; + }; + } Symbol lookupPackage(Env env, Name name) { PackageSymbol pack = syms.lookupPackage(env.toplevel.modle, name); @@ -2433,6 +2442,11 @@ Symbol findType(Env env, Name name) { sym = findGlobalType(env, env.toplevel.starImportScope, name, starImportScopeRecovery); if (sym.exists()) return sym; else bestSoFar = bestOf(bestSoFar, sym); + + sym = findGlobalType(env, env.toplevel.moduleImportScope, name, moduleImportScopeRecovery); + if (sym.exists()) return sym; + + else bestSoFar = bestOf(bestSoFar, sym); } return bestSoFar; @@ -3730,11 +3744,10 @@ class ConstructorReferenceLookupHelper extends ReferenceLookupHelper { @Override protected Symbol lookup(Env env, MethodResolutionPhase phase) { - Symbol sym = needsInference ? + return needsInference ? findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) : findMethod(env, site, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()); - return enclosingInstanceMissing(env, site) ? new BadConstructorReferenceError(sym) : sym; } @Override @@ -3779,6 +3792,63 @@ Symbol lookupMethod(Env env, DiagnosticPosition pos, Symbol locatio } } + /** + * Find a "valid" reference to an enclosing 'A.this' such that A is a subclass of the provided class symbol. + * A reference to an enclosing 'A.this' is "valid" if (a) we're not in the early-construction context for A + * and (b) if the current class is not an inner class of A. + */ + Symbol findSelfContaining(DiagnosticPosition pos, + Env env, + TypeSymbol c, + boolean isSuper) { + Env env1 = isSuper ? env.outer : env; + boolean staticOnly = false; + while (env1.outer != null) { + if (isStatic(env1)) staticOnly = true; + if (env1.enclClass.sym.isSubClass(c, types)) { + Symbol sym = env1.info.scope.findFirst(names._this); + if (sym != null) { + if (staticOnly) { + // current class is not an inner class, stop search + return new StaticError(sym); + } else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym)) { + // early construction context, stop search + return new RefBeforeCtorCalledError(sym); + } else { + // found it + return sym; + } + } + } + if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; + env1 = env1.outer; + } + return varNotFound; + } + + /** + * Resolve the (method) owner of a local class. This can fail if the local class + * is referenced from a static context nested inside the local class. Effectively, + * this lookup succeeds if we can access a local variable declared inside the owner + * method from the provided env. + */ + Symbol findLocalClassOwner(Env env, TypeSymbol c) { + Symbol owner = c.owner; + Assert.check(owner.kind == MTH); + Env env1 = env; + boolean staticOnly = false; + while (env1.outer != null) { + if (env1.info.scope.owner == owner) { + return (staticOnly) ? + new BadLocalClassCreation(c) : + owner; + } + if (isStatic(env1)) staticOnly = true; + env1 = env1.outer; + } + return methodNotFound; + } + /** * Resolve `c.name' where name == this or name == super. * @param pos The position to use for error reporting. @@ -3803,15 +3873,15 @@ Symbol resolveSelf(DiagnosticPosition pos, else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym)) sym = new RefBeforeCtorCalledError(sym); return accessBase(sym, pos, env.enclClass.sym.type, - name, true); + name, true); } } if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; env1 = env1.outer; } if (c.isInterface() && - name == names._super && !isStatic(env) && - types.isDirectSuperInterface(c, env.enclClass.sym)) { + name == names._super && !isStatic(env) && + types.isDirectSuperInterface(c, env.enclClass.sym)) { //this might be a default super call if one of the superinterfaces is 'c' for (Type t : pruneInterfaces(env.enclClass.type)) { if (t.tsym == c) { @@ -3826,8 +3896,8 @@ else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbo for (Type i : types.directSupertypes(env.enclClass.type)) { if (i.tsym.isSubClass(c, types) && i.tsym != c) { log.error(pos, - Errors.IllegalDefaultSuperCall(c, - Fragments.RedundantSupertype(c, i))); + Errors.IllegalDefaultSuperCall(c, + Fragments.RedundantSupertype(c, i))); return syms.errSymbol; } } @@ -3934,76 +4004,6 @@ public boolean isEarlyReference(Env env, JCTree base, VarSymbol v) (base == null || TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, base)); } - /** - * Resolve `c.this' for an enclosing class c that contains the - * named member. - * @param pos The position to use for error reporting. - * @param env The environment current at the expression. - * @param member The member that must be contained in the result. - */ - Symbol resolveSelfContaining(DiagnosticPosition pos, - Env env, - Symbol member, - boolean isSuperCall) { - Symbol sym = resolveSelfContainingInternal(env, member, isSuperCall); - if (sym == null) { - log.error(pos, Errors.EnclClassRequired(member)); - return syms.errSymbol; - } else { - return accessBase(sym, pos, env.enclClass.sym.type, sym.name, true); - } - } - - boolean enclosingInstanceMissing(Env env, Type type) { - if (type.hasTag(CLASS) && type.getEnclosingType().hasTag(CLASS)) { - Symbol encl = resolveSelfContainingInternal(env, type.tsym, false); - return encl == null || encl.kind.isResolutionError(); - } - return false; - } - - private Symbol resolveSelfContainingInternal(Env env, - Symbol member, - boolean isSuperCall) { - Name name = names._this; - Env env1 = isSuperCall ? env.outer : env; - boolean staticOnly = false; - if (env1 != null) { - while (env1 != null && env1.outer != null) { - if (isStatic(env1)) staticOnly = true; - if (env1.enclClass.sym.isSubClass(member.owner.enclClass(), types)) { - Symbol sym = env1.info.scope.findFirst(name); - if (sym != null) { - if (staticOnly) sym = new StaticError(sym); - return sym; - } - } - if ((env1.enclClass.sym.flags() & STATIC) != 0) - staticOnly = true; - env1 = env1.outer; - } - } - return null; - } - - /** - * Resolve an appropriate implicit this instance for t's container. - * JLS 8.8.5.1 and 15.9.2 - */ - Type resolveImplicitThis(DiagnosticPosition pos, Env env, Type t) { - return resolveImplicitThis(pos, env, t, false); - } - - Type resolveImplicitThis(DiagnosticPosition pos, Env env, Type t, boolean isSuperCall) { - Type thisType = (t.tsym.owner.kind.matches(KindSelector.VAL_MTH) - ? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this) - : resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type; - if (env.info.ctorPrologue && thisType.tsym == env.enclClass.sym) { - log.error(pos, Errors.CantRefBeforeCtorCalled(names._this)); - } - return thisType; - } - /* *************************************************************************** * ResolveError classes, indicating error situations when accessing symbols ****************************************************************************/ @@ -4727,6 +4727,28 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, } } + /** + * Specialization of {@link StaticError} for illegal + * creation of local class instances from a static context. + */ + class BadLocalClassCreation extends StaticError { + BadLocalClassCreation(Symbol sym) { + super(sym, "bad local class creation"); + } + + @Override + JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, + DiagnosticPosition pos, + Symbol location, + Type site, + Name name, + List argtypes, + List typeargtypes) { + return diags.create(dkind, log.currentSource(), pos, + "local.cant.be.inst.static", kindName(sym), sym); + } + } + /** * Specialization of {@link InvalidSymbolError} for illegal * early accesses within a constructor prologue. @@ -4886,23 +4908,6 @@ JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol } } - /** - * BadConstructorReferenceError error class indicating that a constructor reference symbol has been found, - * but pointing to a class for which an enclosing instance is not available. - */ - class BadConstructorReferenceError extends InvalidSymbolError { - - public BadConstructorReferenceError(Symbol sym) { - super(MISSING_ENCL, sym, "BadConstructorReferenceError"); - } - - @Override - JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List argtypes, List typeargtypes) { - return diags.create(dkind, log.currentSource(), pos, - "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType()); - } - } - class BadClassFileError extends InvalidSymbolError { private final CompletionFailure ex; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java index b518d7edb4b..40dcf854ff9 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java @@ -220,6 +220,7 @@ void finishImports(JCCompilationUnit toplevel, Runnable resolve) { chk.checkImportedPackagesObservable(toplevel); toplevel.namedImportScope.finalizeScope(); toplevel.starImportScope.finalizeScope(); + toplevel.moduleImportScope.finalizeScope(); } catch (CompletionFailure cf) { chk.completionError(toplevel.pos(), cf); } finally { @@ -331,7 +332,7 @@ private void implicitImports(JCCompilationUnit tree, Env env) { throw new Abort(); } importAll(make.at(tree.pos()).Import(make.Select(make.QualIdent(javaLang.owner), javaLang), false), - javaLang, env); + javaLang, env, false); List defs = tree.getTypeDecls(); boolean isImplicitClass = !defs.isEmpty() && @@ -341,7 +342,7 @@ private void implicitImports(JCCompilationUnit tree, Env env) { doModuleImport(make.ModuleImport(make.QualIdent(syms.java_base))); if (peekTypeExists(syms.ioType.tsym)) { doImport(make.Import(make.Select(make.QualIdent(syms.ioType.tsym), - names.asterisk), true)); + names.asterisk), true), false); } } } @@ -413,7 +414,7 @@ private void handleImports(List imports) { if (imp instanceof JCModuleImport mimp) { doModuleImport(mimp); } else { - doImport((JCImport) imp); + doImport((JCImport) imp, false); } } } @@ -438,7 +439,7 @@ private void checkClassPackageClash(JCPackageDecl tree) { annotate.annotateLater(tree.annotations, env, env.toplevel.packge, tree.pos()); } - private void doImport(JCImport tree) { + private void doImport(JCImport tree, boolean fromModuleImport) { JCFieldAccess imp = tree.qualid; Name name = TreeInfo.name(imp); @@ -450,16 +451,20 @@ private void doImport(JCImport tree) { if (name == names.asterisk) { // Import on demand. chk.checkCanonical(imp.selected); - if (tree.staticImport) + if (tree.staticImport) { + Assert.check(!fromModuleImport); importStaticAll(tree, p, env); - else - importAll(tree, p, env); + } else { + importAll(tree, p, env, fromModuleImport); + } } else { // Named type import. if (tree.staticImport) { + Assert.check(!fromModuleImport); importNamedStatic(tree, p, name, localEnv); chk.checkCanonical(imp.selected); } else { + Assert.check(!fromModuleImport); Type importedType = attribImportType(imp, localEnv); Type originalType = importedType.getOriginalType(); TypeSymbol c = originalType.hasTag(CLASS) ? originalType.tsym : importedType.tsym; @@ -506,7 +511,7 @@ private void doModuleImport(JCModuleImport tree) { JCImport nestedImport = make.at(tree.pos) .Import(make.Select(make.QualIdent(pkg), names.asterisk), false); - doImport(nestedImport); + doImport(nestedImport, true); } for (RequiresDirective requires : currentModule.requires) { @@ -542,8 +547,13 @@ Type attribImportType(JCTree tree, Env env) { */ private void importAll(JCImport imp, final TypeSymbol tsym, - Env env) { - env.toplevel.starImportScope.importAll(types, tsym.members(), typeImportFilter, imp, cfHandler); + Env env, + boolean fromModuleImport) { + StarImportScope targetScope = + fromModuleImport ? env.toplevel.moduleImportScope + : env.toplevel.starImportScope; + + targetScope.importAll(types, tsym.members(), typeImportFilter, imp, cfHandler); } /** Import all static members of a class or package on demand. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 233629e10bb..f70b96697b3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -199,6 +199,9 @@ public class ClassReader { /** The minor version number of the class file being read. */ int minorVersion; + /** true if the class file being read is a preview class file. */ + boolean previewClassFile; + /** UTF-8 validation level */ Convert.Validation utf8validation; @@ -1200,7 +1203,9 @@ protected void read(Symbol sym, int attrLen) { ModuleSymbol rsym = poolReader.getModule(nextChar()); Set flags = readRequiresFlags(nextChar()); if (rsym == syms.java_base && majorVersion >= V54.major) { - if (flags.contains(RequiresFlag.TRANSITIVE)) { + if (flags.contains(RequiresFlag.TRANSITIVE) && + (majorVersion != Version.MAX().major || !previewClassFile) && + !preview.participatesInPreview(syms, msym)) { throw badClassFile("bad.requires.flag", RequiresFlag.TRANSITIVE); } if (flags.contains(RequiresFlag.STATIC_PHASE)) { @@ -3185,7 +3190,7 @@ private void readClassBuffer(ClassSymbol c) throws IOException { majorVersion = nextChar(); int maxMajor = Version.MAX().major; int maxMinor = Version.MAX().minor; - boolean previewClassFile = + previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION; if (majorVersion > maxMajor || majorVersion * 1000 + minorVersion < diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index a93f5a9a794..0bbcd56293f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -667,7 +667,8 @@ void reportDanglingDocComment(Comment c) { var pos = c.getPos(); if (pos != null) { deferredLintHandler.report(lint -> { - if (lint.isEnabled(Lint.LintCategory.DANGLING_DOC_COMMENTS)) { + if (lint.isEnabled(Lint.LintCategory.DANGLING_DOC_COMMENTS) && + !shebang(c, pos)) { log.warning(Lint.LintCategory.DANGLING_DOC_COMMENTS, pos, Warnings.DanglingDocComment); } @@ -675,6 +676,14 @@ void reportDanglingDocComment(Comment c) { } } + /** Returns true for a comment that acts similarly to shebang in UNIX */ + private boolean shebang(Comment c, JCDiagnostic.DiagnosticPosition pos) { + var src = log.currentSource(); + return c.getStyle() == Comment.CommentStyle.JAVADOC_LINE && + c.getPos().getStartPosition() == 0 && + src.getLineNumber(pos.getEndPosition(src.getEndPosTable())) == 1; + } + /** * Ignores any recent documentation comments found by the scanner, * such as those that cannot be associated with a nearby declaration. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index a24dd2f95bd..bd666f3427d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -921,10 +921,6 @@ compiler.misc.unexpected.ret.val=\ compiler.err.mod.not.allowed.here=\ modifier {0} not allowed here -# 0: name -compiler.err.modifier.not.allowed.here=\ - modifier {0} not allowed here - compiler.err.intf.not.allowed.here=\ interface not allowed here @@ -1099,11 +1095,6 @@ compiler.misc.not.def.access.class.intf.cant.access.reason=\ {1}.{0} in package {2} is not accessible\n\ ({3}) -# 0: symbol, 1: list of type, 2: type -compiler.misc.cant.access.inner.cls.constr=\ - cannot access constructor {0}({1})\n\ - an enclosing instance of type {2} is not in scope - # 0: symbol, 1: symbol compiler.err.not.def.public.cant.access=\ {0} is not public in {1}; cannot be accessed from outside package @@ -2887,6 +2878,11 @@ compiler.err.abstract.cant.be.accessed.directly=\ compiler.err.non-static.cant.be.ref=\ non-static {0} {1} cannot be referenced from a static context +## The first argument ({0}) is a "kindname". +# 0: symbol kind, 1: symbol +compiler.err.local.cant.be.inst.static=\ + local {0} {1} cannot be instantiated from a static context + # 0: symbol kind, 1: symbol compiler.misc.bad.static.method.in.unbound.lookup=\ unexpected static {0} {1} found in unbound lookup @@ -3252,6 +3248,9 @@ compiler.misc.feature.flexible.constructors=\ compiler.misc.feature.module.imports=\ module imports +compiler.misc.feature.java.base.transitive=\ + transitive modifier for java.base + compiler.warn.underscore.as.identifier=\ as of release 9, ''_'' is a keyword, and may not be used as an identifier diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java index 003f70eeecc..a2837013506 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -538,6 +538,8 @@ public static class JCCompilationUnit extends JCTree implements CompilationUnitT public NamedImportScope namedImportScope; /** A scope for all import-on-demands. */ public StarImportScope starImportScope; + /** A scope for all single module imports. */ + public StarImportScope moduleImportScope; /** Line starting positions, defined only if option -g is set. */ public Position.LineMap lineMap = null; /** A table that stores all documentation comments indexed by the tree diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java index b4c6f804a2f..0d0852cb91b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -738,12 +738,18 @@ public JCFieldAccess Select(JCExpression base, Symbol sym) { } /** Create a qualified identifier from a symbol, adding enough qualifications - * to make the reference unique. + * to make the reference unique. The types in the AST nodes will be erased. */ public JCExpression QualIdent(Symbol sym) { - return isUnqualifiable(sym) + JCExpression result = isUnqualifiable(sym) ? Ident(sym) : Select(QualIdent(sym.owner), sym); + + if (sym.kind == TYP) { + result.setType(types.erasure(sym.type)); + } + + return result; } /** Create an identifier that refers to the variable declared in given variable @@ -1138,26 +1144,17 @@ boolean isUnqualifiable(Symbol sym) { sym.owner.kind == MTH || sym.owner.kind == VAR) { return true; } else if (sym.kind == TYP && toplevel != null) { - Iterator it = toplevel.namedImportScope.getSymbolsByName(sym.name).iterator(); - if (it.hasNext()) { - Symbol s = it.next(); - return - s == sym && - !it.hasNext(); - } - it = toplevel.packge.members().getSymbolsByName(sym.name).iterator(); - if (it.hasNext()) { - Symbol s = it.next(); - return - s == sym && - !it.hasNext(); - } - it = toplevel.starImportScope.getSymbolsByName(sym.name).iterator(); - if (it.hasNext()) { - Symbol s = it.next(); - return - s == sym && - !it.hasNext(); + for (Scope scope : new Scope[] {toplevel.namedImportScope, + toplevel.packge.members(), + toplevel.starImportScope, + toplevel.moduleImportScope}) { + Iterator it = scope.getSymbolsByName(sym.name).iterator(); + if (it.hasNext()) { + Symbol s = it.next(); + return + s == sym && + !it.hasNext(); + } } } return sym.kind == TYP && sym.isImplicit(); diff --git a/src/jdk.compiler/share/man/javac.1 b/src/jdk.compiler/share/man/javac.1 deleted file mode 100644 index ebee0369238..00000000000 --- a/src/jdk.compiler/share/man/javac.1 +++ /dev/null @@ -1,2372 +0,0 @@ -.\" Copyright (c) 1994, 2023, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JAVAC" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -javac - read Java declarations and compile them into class files -.SH SYNOPSIS -.PP -\f[V]javac\f[R] [\f[I]options\f[R]] -[\f[I]sourcefiles-or-classnames\f[R]] -.TP -\f[I]options\f[R] -Command-line options. -.TP -\f[I]sourcefiles-or-classnames\f[R] -Source files to be compiled (for example, \f[V]Shape.java\f[R]) or the -names of previously compiled classes to be processed for annotations -(for example, \f[V]geometry.MyShape\f[R]). -.SH DESCRIPTION -.PP -The \f[V]javac\f[R] command reads \f[I]source files\f[R] that contain -module, package and type declarations written in the Java programming -language, and compiles them into \f[I]class files\f[R] that run on the -Java Virtual Machine. -.PP -The \f[V]javac\f[R] command can also \f[B]process annotations\f[R] in -Java source files and classes. -.PP -Source files must have a file name extension of \f[V].java\f[R]. -Class files have a file name extension of \f[V].class\f[R]. -Both source and class files normally have file names that identify the -contents. -For example, a class called \f[V]Shape\f[R] would be declared in a -source file called \f[V]Shape.java\f[R], and compiled into a class file -called \f[V]Shape.class\f[R]. -.PP -There are two ways to specify source files to \f[V]javac\f[R]: -.IP \[bu] 2 -For a small number of source files, you can list their file names on the -command line. -.IP \[bu] 2 -For a large number of source files, you can use the -\f[B]\f[VB]\[at]\f[B]\f[BI]filename\f[B]\f[R] option on the command line -to specify an \f[I]argument file\f[R] that lists their file names. -See \f[B]Standard Options\f[R] for a description of the option and -\f[B]Command-Line Argument Files\f[R] for a description of -\f[V]javac\f[R] argument files. -.PP -The order of source files specified on the command line or in an -argument file is not important. -\f[V]javac\f[R] will compile the files together, as a group, and will -automatically resolve any dependencies between the declarations in the -various source files. -.PP -\f[V]javac\f[R] expects that source files are arranged in one or more -directory hierarchies on the file system, described in \f[B]Arrangement -of Source Code\f[R]. -.PP -To compile a source file, \f[V]javac\f[R] needs to find the declaration -of every class or interface that is used, extended, or implemented by -the code in the source file. -This lets \f[V]javac\f[R] check that the code has the right to access -those classes and interfaces. -Rather than specifying the source files of those classes and interfaces -explicitly, you can use command-line options to tell \f[V]javac\f[R] -where to search for their source files. -If you have compiled those source files previously, you can use options -to tell \f[V]javac\f[R] where to search for the corresponding class -files. -The options, which all have names ending in \[dq]path\[dq], are -described in \f[B]Standard Options\f[R], and further described in -\f[B]Configuring a Compilation\f[R] and \f[B]Searching for Module, -Package and Type Declarations\f[R]. -.PP -By default, \f[V]javac\f[R] compiles each source file to a class file in -the same directory as the source file. -However, it is recommended to specify a separate destination directory -with the \f[B]\f[VB]-d\f[B]\f[R] option. -.PP -Command-line \f[B]options\f[R] and \f[B]environment variables\f[R] also -control how \f[V]javac\f[R] performs various tasks: -.IP \[bu] 2 -Compiling code to run on earlier releases of the JDK. -.IP \[bu] 2 -Compiling code to run under a debugger. -.IP \[bu] 2 -Checking for stylistic issues in Java source code. -.IP \[bu] 2 -Checking for problems in \f[V]javadoc\f[R] comments -(\f[V]/** ... */\f[R]). -.IP \[bu] 2 -Processing annotations in source files and class files. -.IP \[bu] 2 -Upgrading and patching modules in the compile-time environment. -.PP -\f[V]javac\f[R] supports \f[B]Compiling for Earlier Releases Of The -Platform\f[R] and can also be invoked from Java code using one of a -number of \f[B]APIs\f[R] -.SH OPTIONS -.PP -\f[V]javac\f[R] provides \f[B]standard options\f[R], and \f[B]extra -options\f[R] that are either non-standard or are for advanced use. -.PP -Some options take one or more arguments. -If an argument contains spaces or other whitespace characters, the value -should be quoted according to the conventions of the environment being -used to invoke javac. -If the option begins with a single dash (\f[V]-\f[R]) the argument -should either directly follow the option name, or should be separated -with a colon (\f[V]:\f[R]) or whitespace, depending on the option. -If the option begins with a double dash (\f[V]--\f[R]), the argument may -be separated either by whitespace or by an equals (\f[V]=\f[R]) -character with no additional whitespace. -For example, -.IP -.nf -\f[CB] --Aname=\[dq]J. Duke\[dq] --proc:only --d myDirectory ---module-version 3 ---module-version=3 -\f[R] -.fi -.PP -In the following lists of options, an argument of \f[I]path\f[R] -represents a search path, composed of a list of file system locations -separated by the platform path separator character, (semicolon -\f[V];\f[R] on Windows, or colon \f[V]:\f[R] on other systems.) -Depending on the option, the file system locations may be directories, -JAR files or JMOD files. -.SS Standard Options -.TP -\f[V]\[at]\f[R]\f[I]filename\f[R] -Reads options and file names from a file. -To shorten or simplify the \f[V]javac\f[R] command, you can specify one -or more files that contain arguments to the \f[V]javac\f[R] command -(except \f[B]\f[VB]-J\f[B]\f[R] options). -This lets you to create \f[V]javac\f[R] commands of any length on any -operating system. -See \f[B]Command-Line Argument Files\f[R]. -.TP -\f[V]-A\f[R]\f[I]key\f[R][\f[V]=\f[R]\f[I]value\f[R]] -Specifies options to pass to annotation processors. -These options are not interpreted by \f[V]javac\f[R] directly, but are -made available for use by individual processors. -The \f[I]key\f[R] value should be one or more identifiers separated by a -dot (\f[V].\f[R]). -.TP -\f[V]--add-modules\f[R] \f[I]module\f[R]\f[V],\f[R]\f[I]module\f[R] -Specifies root modules to resolve in addition to the initial modules, or -all modules on the module path if \f[I]module\f[R] is -\f[V]ALL-MODULE-PATH\f[R]. -.TP -\f[V]--boot-class-path\f[R] \f[I]path\f[R] or \f[V]-bootclasspath\f[R] \f[I]path\f[R] -Overrides the location of the bootstrap class files. -.RS -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -For JDK 9 or later, see \f[B]\f[VB]--system\f[B]\f[R]. -.RE -.TP -\f[V]--class-path\f[R] \f[I]path\f[R], \f[V]-classpath\f[R] \f[I]path\f[R], or \f[V]-cp\f[R] \f[I]path\f[R] -Specifies where to find user class files and annotation processors. -This class path overrides the user class path in the \f[V]CLASSPATH\f[R] -environment variable. -.RS -.IP \[bu] 2 -If \f[V]--class-path\f[R], \f[V]-classpath\f[R], or \f[V]-cp\f[R] are -not specified, then the user class path is the value of the -\f[V]CLASSPATH\f[R] environment variable, if that is set, or else the -current directory. -.IP \[bu] 2 -If not compiling code for modules, if the -\f[B]\f[VB]--source-path\f[B]\f[R] or -sourcepath\[ga] option is not -specified, then the user class path is also searched for source files. -.IP \[bu] 2 -If the \f[B]\f[VB]-processorpath\f[B]\f[R] option is not specified, then -the class path is also searched for annotation processors. -.RE -.TP -\f[V]-d\f[R] \f[I]directory\f[R] -Sets the destination directory (or \f[I]class output directory\f[R]) for -class files. -If a class is part of a package, then \f[V]javac\f[R] puts the class -file in a subdirectory that reflects the module name (if appropriate) -and package name. -The directory, and any necessary subdirectories, will be created if they -do not already exist. -.RS -.PP -If the \f[V]-d\f[R] option is not specified, then \f[V]javac\f[R] puts -each class file in the same directory as the source file from which it -was generated. -.PP -Except when compiling code for multiple modules, the contents of the -class output directory will be organized in a package hierarchy. -When compiling code for multiple modules, the contents of the output -directory will be organized in a module hierarchy, with the contents of -each module in a separate subdirectory, each organized as a package -hierarchy. -.PP -\f[B]Note:\f[R] When compiling code for one or more modules, the class -output directory will automatically be checked when searching for -previously compiled classes. -When not compiling for modules, for backwards compatibility, the -directory is \f[I]not\f[R] automatically checked for previously compiled -classes, and so it is recommended to specify the class output directory -as one of the locations on the user class path, using the -\f[V]--class-path\f[R] option or one of its alternate forms. -.RE -.TP -\f[V]-deprecation\f[R] -Shows a description of each use or override of a deprecated member or -class. -Without the \f[V]-deprecation\f[R] option, \f[V]javac\f[R] shows a -summary of the source files that use or override deprecated members or -classes. -The \f[V]-deprecation\f[R] option is shorthand for -\f[V]-Xlint:deprecation\f[R]. -.TP -\f[V]--enable-preview\f[R] -Enables preview language features. -Used in conjunction with either \f[B]\f[VB]-source\f[B]\f[R] or -\f[B]\f[VB]--release\f[B]\f[R]. -.TP -\f[V]-encoding\f[R] \f[I]encoding\f[R] -Specifies character encoding used by source files, such as EUC-JP and -UTF-8. -If the \f[V]-encoding\f[R] option is not specified, then the platform -default converter is used. -.TP -\f[V]-endorseddirs\f[R] \f[I]directories\f[R] -Overrides the location of the endorsed standards path. -.RS -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -.RE -.TP -\f[V]-extdirs\f[R] \f[I]directories\f[R] -Overrides the location of the installed extensions. -\f[V]directories\f[R] is a list of directories, separated by the -platform path separator (\f[V];\f[R] on Windows, and \f[V]:\f[R] -otherwise). -Each JAR file in the specified directories is searched for class files. -All JAR files found become part of the class path. -.RS -.PP -If you are compiling for a release of the platform that supports the -Extension Mechanism, then this option specifies the directories that -contain the extension classes. -See [Compiling for Other Releases of the Platform]. -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -.RE -.TP -\f[V]-g\f[R] -Generates all debugging information, including local variables. -By default, only line number and source file information is generated. -.TP -\f[V]-g:\f[R][\f[V]lines\f[R], \f[V]vars\f[R], \f[V]source\f[R]] -Generates only the kinds of debugging information specified by the -comma-separated list of keywords. -Valid keywords are: -.RS -.TP -\f[V]lines\f[R] -Line number debugging information. -.TP -\f[V]vars\f[R] -Local variable debugging information. -.TP -\f[V]source\f[R] -Source file debugging information. -.RE -.TP -\f[V]-g:none\f[R] -Does not generate debugging information. -.TP -\f[V]-h\f[R] \f[I]directory\f[R] -Specifies where to place generated native header files. -.RS -.PP -When you specify this option, a native header file is generated for each -class that contains native methods or that has one or more constants -annotated with the \f[B]\f[VB]java.lang.annotation.Native\f[B]\f[R] -annotation. -If the class is part of a package, then the compiler puts the native -header file in a subdirectory that reflects the module name (if -appropriate) and package name. -The directory, and any necessary subdirectories, will be created if they -do not already exist. -.RE -.TP -\f[V]--help\f[R], \f[V]-help\f[R] or \f[V]-?\f[R] -Prints a synopsis of the standard options. -.TP -\f[V]--help-extra\f[R] or \f[V]-X\f[R] -Prints a synopsis of the set of extra options. -.TP -\f[V]--help-lint\f[R] -Prints the supported keys for the \f[V]-Xlint\f[R] option. -.TP -\f[V]-implicit:\f[R][\f[V]none\f[R], \f[V]class\f[R]] -Specifies whether or not to generate class files for implicitly -referenced files: -.RS -.IP \[bu] 2 -\f[V]-implicit:class\f[R] --- Automatically generates class files. -.IP \[bu] 2 -\f[V]-implicit:none\f[R] --- Suppresses class file generation. -.PP -If this option is not specified, then the default automatically -generates class files. -In this case, the compiler issues a warning if any class files are -generated when also doing annotation processing. -The warning is not issued when the \f[V]-implicit\f[R] option is -explicitly set. -See \f[B]Searching for Module, Package and Type Declarations\f[R]. -.RE -.TP -\f[V]-J\f[R]\f[I]option\f[R] -Passes \f[I]option\f[R] to the runtime system, where \f[I]option\f[R] is -one of the Java options described on \f[B]java\f[R] command. -For example, \f[V]-J-Xms48m\f[R] sets the startup memory to 48 MB. -.RS -.PP -\f[B]Note:\f[R] The \f[V]CLASSPATH\f[R] environment variable, -\f[V]-classpath\f[R] option, \f[V]-bootclasspath\f[R] option, and -\f[V]-extdirs\f[R] option do not specify the classes used to run -\f[V]javac\f[R]. -Trying to customize the compiler implementation with these options and -variables is risky and often does not accomplish what you want. -If you must customize the compiler implementation, then use the -\f[V]-J\f[R] option to pass options through to the underlying Java -launcher. -.RE -.TP -\f[V]--limit-modules\f[R] \f[I]module\f[R]\f[V],\f[R]\f[I]module\f[R]* -Limits the universe of observable modules. -.TP -\f[V]--module\f[R] \f[I]module-name\f[R] (\f[V],\f[R]\f[I]module-name\f[R])* or \f[V]-m\f[R] \f[I]module-name\f[R] (\f[V],\f[R]\f[I]module-name\f[R])* -Compiles those source files in the named modules that are newer than the -corresponding files in the output directory. -.TP -\f[V]--module-path\f[R] \f[I]path\f[R] or \f[V]-p\f[R] \f[I]path\f[R] -Specifies where to find application modules. -.TP -\f[V]--module-source-path\f[R] \f[I]module-source-path\f[R] -Specifies where to find source files when compiling code in multiple -modules. -See [Compilation Modes] and \f[B]The Module Source Path Option\f[R]. -.TP -\f[V]--module-version\f[R] \f[I]version\f[R] -Specifies the version of modules that are being compiled. -.TP -\f[V]-nowarn\f[R] -Disables warning messages. -This option operates the same as the \f[V]-Xlint:none\f[R] option. -.TP -\f[V]-parameters\f[R] -Generates metadata for reflection on method parameters. -Stores formal parameter names of constructors and methods in the -generated class file so that the method -\f[V]java.lang.reflect.Executable.getParameters\f[R] from the Reflection -API can retrieve them. -.TP -\f[V]-proc:\f[R][\f[V]none\f[R], \f[V]only\f[R], \f[V]full\f[R]] -Controls whether annotation processing and compilation are done. -\f[V]-proc:none\f[R] means that compilation takes place without -annotation processing. -\f[V]-proc:only\f[R] means that only annotation processing is done, -without any subsequent compilation. -If this option is not used, or \f[V]-proc:full\f[R] is specified, -annotation processing and compilation are done. -.TP -\f[V]-processor\f[R] \f[I]class1\f[R][\f[V],\f[R]\f[I]class2\f[R]\f[V],\f[R]\f[I]class3\f[R]...] -Names of the annotation processors to run. -This bypasses the default discovery process. -.TP -\f[V]--processor-module-path\f[R] \f[I]path\f[R] -Specifies the module path used for finding annotation processors. -.TP -\f[V]--processor-path\f[R] \f[I]path\f[R] or \f[V]-processorpath\f[R] \f[I]path\f[R] -Specifies where to find annotation processors. -If this option is not used, then the class path is searched for -processors. -.TP -\f[V]-profile\f[R] \f[I]profile\f[R] -Checks that the API used is available in the specified profile. -This option is deprecated and may be removed in a future release. -.RS -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -.RE -.TP -\f[V]--release\f[R] \f[I]release\f[R] -Compiles source code according to the rules of the Java programming -language for the specified Java SE release, generating class files which -target that release. -Source code is compiled against the combined Java SE and JDK API for the -specified release. -.RS -.PP -The supported values of \f[I]release\f[R] are the current Java SE -release and a limited number of previous releases, detailed in the -command-line help. -.PP -For the current release, the Java SE API consists of the -\f[V]java.*\f[R], \f[V]javax.*\f[R], and \f[V]org.*\f[R] packages that -are exported by the Java SE modules in the release; the JDK API consists -of the \f[V]com.*\f[R] and \f[V]jdk.*\f[R] packages that are exported by -the JDK modules in the release, plus the \f[V]javax.*\f[R] packages that -are exported by standard, but non-Java SE, modules in the release. -.PP -For previous releases, the Java SE API and the JDK API are as defined in -that release. -.PP -\f[B]Note:\f[R] When using \f[V]--release\f[R], you cannot also use the -\f[B]\f[VB]--source\f[B]\f[R]/\f[V]-source\f[R] or -\f[B]\f[VB]--target\f[B]\f[R]/\f[V]-target\f[R] options. -.PP -\f[B]Note:\f[R] When using \f[V]--release\f[R] to specify a release that -supports the Java Platform Module System, the \f[V]--add-exports\f[R] -option cannot be used to enlarge the set of packages exported by the -Java SE, JDK, and standard modules in the specified release. -.RE -.TP -\f[V]-s\f[R] \f[I]directory\f[R] -Specifies the directory used to place the generated source files. -If a class is part of a package, then the compiler puts the source file -in a subdirectory that reflects the module name (if appropriate) and -package name. -The directory, and any necessary subdirectories, will be created if they -do not already exist. -.RS -.PP -Except when compiling code for multiple modules, the contents of the -source output directory will be organized in a package hierarchy. -When compiling code for multiple modules, the contents of the source -output directory will be organized in a module hierarchy, with the -contents of each module in a separate subdirectory, each organized as a -package hierarchy. -.RE -.TP -\f[V]--source\f[R] \f[I]release\f[R] or \f[V]-source\f[R] \f[I]release\f[R] -Compiles source code according to the rules of the Java programming -language for the specified Java SE release. -The supported values of \f[I]release\f[R] are the current Java SE -release and a limited number of previous releases, detailed in the -command-line help. -.RS -.PP -If the option is not specified, the default is to compile source code -according to the rules of the Java programming language for the current -Java SE release. -.RE -.TP -\f[V]--source-path\f[R] \f[I]path\f[R] or \f[V]-sourcepath\f[R] \f[I]path\f[R] -Specifies where to find source files. -Except when compiling multiple modules together, this is the source code -path used to search for class or interface definitions. -.RS -.PP -\f[B]Note:\f[R] Classes found through the class path might be recompiled -when their source files are also found. -See \f[B]Searching for Module, Package and Type Declarations\f[R]. -.RE -.TP -\f[V]--system\f[R] \f[I]jdk\f[R] | \f[V]none\f[R] -Overrides the location of system modules. -.TP -\f[V]--target\f[R] \f[I]release\f[R] or \f[V]-target\f[R] \f[I]release\f[R] -Generates \f[V]class\f[R] files suitable for the specified Java SE -release. -The supported values of \f[I]release\f[R] are the current Java SE -release and a limited number of previous releases, detailed in the -command-line help. -.RS -.PP -\f[B]Note:\f[R] The target release must be equal to or higher than the -source release. -(See \f[B]\f[VB]--source\f[B]\f[R].) -.RE -.TP -\f[V]--upgrade-module-path\f[R] \f[I]path\f[R] -Overrides the location of upgradeable modules. -.TP -\f[V]-verbose\f[R] -Outputs messages about what the compiler is doing. -Messages include information about each class loaded and each source -file compiled. -.TP -\f[V]--version\f[R] or \f[V]-version\f[R] -Prints version information. -.TP -\f[V]-Werror\f[R] -Terminates compilation when warnings occur. -.SS Extra Options -.TP -\f[V]--add-exports\f[R] \f[I]module\f[R]\f[V]/\f[R]\f[I]package\f[R]\f[V]=\f[R]\f[I]other-module\f[R](\f[V],\f[R]\f[I]other-module\f[R])* -Specifies a package to be considered as exported from its defining -module to additional modules or to all unnamed modules when the value of -\f[I]other-module\f[R] is \f[V]ALL-UNNAMED\f[R]. -.TP -\f[V]--add-reads\f[R] \f[I]module\f[R]\f[V]=\f[R]\f[I]other-module\f[R](\f[V],\f[R]\f[I]other-module\f[R])* -Specifies additional modules to be considered as required by a given -module. -.TP -\f[V]--default-module-for-created-files\f[R] \f[I]module-name\f[R] -Specifies the fallback target module for files created by annotation -processors, if none is specified or inferred. -.TP -\f[V]--disable-line-doc-comments\f[R] -Disables support for documentation comments with lines beginning ///. -.TP -\f[V]-Djava.endorsed.dirs=\f[R]\f[I]dirs\f[R] -Overrides the location of the endorsed standards path. -.RS -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -.RE -.TP -\f[V]-Djava.ext.dirs=\f[R]\f[I]dirs\f[R] -Overrides the location of installed extensions. -.RS -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -.RE -.TP -\f[V]--patch-module\f[R] \f[I]module\f[R]\f[V]=\f[R]\f[I]path\f[R] -Overrides or augments a module with classes and resources in JAR files -or directories. -.TP -\f[V]-Xbootclasspath:\f[R]\f[I]path\f[R] -Overrides the location of the bootstrap class files. -.RS -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -.RE -.TP -\f[V]-Xbootclasspath/a:\f[R]\f[I]path\f[R] -Adds a suffix to the bootstrap class path. -.RS -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -.RE -.TP -\f[V]-Xbootclasspath/p:\f[R]\f[I]path\f[R] -Adds a prefix to the bootstrap class path. -.RS -.PP -\f[B]Note:\f[R] This can only be used when compiling for releases prior -to JDK 9. -As applicable, see the descriptions in \f[B]\f[VB]--release\f[B]\f[R], -\f[B]\f[VB]-source\f[B]\f[R], or \f[B]\f[VB]-target\f[B]\f[R] for -details. -.RE -.TP -\f[V]-Xdiags:\f[R][\f[V]compact\f[R], \f[V]verbose\f[R]] -Selects a diagnostic mode. -.TP -\f[V]-Xdoclint\f[R] -Enables recommended checks for problems in documentation comments. -.TP -\f[V]-Xdoclint:\f[R](\f[V]all\f[R]|\f[V]none\f[R]|[\f[V]-\f[R]]\f[I]group\f[R])[\f[V]/\f[R]\f[I]access\f[R]] -Enables or disables specific groups of checks in documentation comments. -.RS -.PP -\f[I]group\f[R] can have one of the following values: -\f[V]accessibility\f[R], \f[V]html\f[R], \f[V]missing\f[R], -\f[V]reference\f[R], \f[V]syntax\f[R]. -.PP -The variable \f[I]access\f[R] specifies the minimum visibility level of -classes and members that the \f[V]-Xdoclint\f[R] option checks. -It can have one of the following values (in order of most to least -visible): \f[V]public\f[R], \f[V]protected\f[R], \f[V]package\f[R], -\f[V]private\f[R]. -.PP -The default \f[I]access\f[R] level is \f[V]private\f[R]. -.PP -When prefixed by \f[V]doclint:\f[R], the \f[I]group\f[R] names and -\f[V]all\f[R] can be used with \f[V]\[at]SuppressWarnings\f[R] to -suppress warnings about documentation comments in parts of the code -being compiled. -.PP -For more information about these groups of checks, see the -\f[B]DocLint\f[R] section of the \f[V]javadoc\f[R] command -documentation. -The \f[V]-Xdoclint\f[R] option is disabled by default in the -\f[V]javac\f[R] command. -.PP -For example, the following option checks classes and members (with all -groups of checks) that have the access level of protected and higher -(which includes protected and public): -.RS -.PP -\f[V]-Xdoclint:all/protected\f[R] -.RE -.PP -The following option enables all groups of checks for all access levels, -except it will not check for HTML errors for classes and members that -have the access level of package and higher (which includes package, -protected and public): -.RS -.PP -\f[V]-Xdoclint:all,-html/package\f[R] -.RE -.RE -.TP -\f[V]-Xdoclint/package:\f[R][\f[V]-\f[R]]\f[I]packages\f[R](\f[V],\f[R][\f[V]-\f[R]]\f[I]package\f[R])* -Enables or disables checks in specific packages. -Each \f[I]package\f[R] is either the qualified name of a package or a -package name prefix followed by \f[V].*\f[R], which expands to all -sub-packages of the given package. -Each \f[I]package\f[R] can be prefixed with a hyphen (\f[V]-\f[R]) to -disable checks for a specified package or packages. -.RS -.PP -For more information, see the \f[B]DocLint\f[R] section of the -\f[V]javadoc\f[R] command documentation. -.RE -.TP -\f[V]-Xlint\f[R] -Enables all recommended warnings. -In this release, enabling all available warnings is recommended. -.TP -\f[V]-Xlint:\f[R][\f[V]-\f[R]]\f[I]key\f[R](\f[V],\f[R][\f[V]-\f[R]]\f[I]key\f[R])* -Supplies warnings to enable or disable, separated by comma. -Precede a key by a hyphen (\f[V]-\f[R]) to disable the specified -warning. -.RS -.PP -Supported values for \f[I]key\f[R] are: -.IP \[bu] 2 -\f[V]all\f[R]: Enables all warnings. -.IP \[bu] 2 -\f[V]auxiliaryclass\f[R]: Warns about an auxiliary class that is hidden -in a source file, and is used from other files. -.IP \[bu] 2 -\f[V]cast\f[R]: Warns about the use of unnecessary casts. -.IP \[bu] 2 -\f[V]classfile\f[R]: Warns about the issues related to classfile -contents. -.IP \[bu] 2 -\f[V]dangling-doc-comments\f[R]: Warns about extra or misplaced -documentation comments near the beginning of a declaration. -.IP \[bu] 2 -\f[V]deprecation\f[R]: Warns about the use of deprecated items. -.IP \[bu] 2 -\f[V]dep-ann\f[R]: Warns about the items marked as deprecated in -\f[V]javadoc\f[R] but without the \f[V]\[at]Deprecated\f[R] annotation. -.IP \[bu] 2 -\f[V]divzero\f[R]: Warns about the division by the constant integer 0. -.IP \[bu] 2 -\f[V]empty\f[R]: Warns about an empty statement after \f[V]if\f[R]. -.IP \[bu] 2 -\f[V]exports\f[R]: Warns about the issues regarding module exports. -.IP \[bu] 2 -\f[V]fallthrough\f[R]: Warns about the falling through from one case of -a switch statement to the next. -.IP \[bu] 2 -\f[V]finally\f[R]: Warns about \f[V]finally\f[R] clauses that do not -terminate normally. -.IP \[bu] 2 -\f[V]incubating\f[R]: Warns about the use of incubating modules. -.IP \[bu] 2 -\f[V]lossy-conversions\f[R]: Warns about possible lossy conversions in -compound assignment. -.IP \[bu] 2 -\f[V]missing-explicit-ctor\f[R]: Warns about missing explicit -constructors in public and protected classes in exported packages. -.IP \[bu] 2 -\f[V]module\f[R]: Warns about the module system-related issues. -.IP \[bu] 2 -\f[V]opens\f[R]: Warns about the issues related to module opens. -.IP \[bu] 2 -\f[V]options\f[R]: Warns about the issues relating to use of command -line options. -.IP \[bu] 2 -\f[V]output-file-clash\f[R]: Warns if any output file is overwritten -during compilation. -This can occur, for example, on case-insensitive filesystems. -.IP \[bu] 2 -\f[V]overloads\f[R]: Warns about the issues related to method overloads. -.IP \[bu] 2 -\f[V]overrides\f[R]: Warns about the issues related to method overrides. -.IP \[bu] 2 -\f[V]path\f[R]: Warns about the invalid path elements on the command -line. -.IP \[bu] 2 -\f[V]preview\f[R]: Warns about the use of preview language features. -.IP \[bu] 2 -\f[V]processing\f[R]: Warns about the issues related to annotation -processing. -.IP \[bu] 2 -\f[V]rawtypes\f[R]: Warns about the use of raw types. -.IP \[bu] 2 -\f[V]removal\f[R]: Warns about the use of an API that has been marked -for removal. -.IP \[bu] 2 -\f[V]restricted\f[R]: Warns about the use of restricted methods. -.IP \[bu] 2 -\f[V]requires-automatic\f[R]: Warns developers about the use of -automatic modules in requires clauses. -.IP \[bu] 2 -\f[V]requires-transitive-automatic\f[R]: Warns about automatic modules -in requires transitive. -.IP \[bu] 2 -\f[V]serial\f[R]: Warns about the serializable classes that do not -provide a serial version ID. -Also warns about access to non-public members from a serializable -element. -.IP \[bu] 2 -\f[V]static\f[R]: Warns about the accessing a static member using an -instance. -.IP \[bu] 2 -\f[V]strictfp\f[R]: Warns about unnecessary use of the -\f[V]strictfp\f[R] modifier. -.IP \[bu] 2 -\f[V]synchronization\f[R]: Warns about synchronization attempts on -instances of value-based classes. -.IP \[bu] 2 -\f[V]text-blocks\f[R]: Warns about inconsistent white space characters -in text block indentation. -.IP \[bu] 2 -\f[V]this-escape\f[R]: Warns about constructors leaking \f[V]this\f[R] -prior to subclass initialization. -.IP \[bu] 2 -\f[V]try\f[R]: Warns about the issues relating to the use of try blocks -(that is, try-with-resources). -.IP \[bu] 2 -\f[V]unchecked\f[R]: Warns about the unchecked operations. -.IP \[bu] 2 -\f[V]varargs\f[R]: Warns about the potentially unsafe \f[V]vararg\f[R] -methods. -.IP \[bu] 2 -\f[V]none\f[R]: Disables all warnings. -.PP -With the exception of \f[V]all\f[R] and \f[V]none\f[R], the keys can be -used with the \f[V]\[at]SuppressWarnings\f[R] annotation to suppress -warnings in a part of the source code being compiled. -.PP -See \f[B]Examples of Using -Xlint keys\f[R]. -.RE -.TP -\f[V]-Xmaxerrs\f[R] \f[I]number\f[R] -Sets the maximum number of errors to print. -.TP -\f[V]-Xmaxwarns\f[R] \f[I]number\f[R] -Sets the maximum number of warnings to print. -.TP -\f[V]-Xpkginfo:\f[R][\f[V]always\f[R], \f[V]legacy\f[R], \f[V]nonempty\f[R]] -Specifies when and how the \f[V]javac\f[R] command generates -\f[V]package-info.class\f[R] files from \f[V]package-info.java\f[R] -files using one of the following options: -.RS -.TP -\f[V]always\f[R] -Generates a \f[V]package-info.class\f[R] file for every -\f[V]package-info.java\f[R] file. -This option may be useful if you use a build system such as Ant, which -checks that each \f[V].java\f[R] file has a corresponding -\f[V].class\f[R] file. -.TP -\f[V]legacy\f[R] -Generates a \f[V]package-info.class\f[R] file only if -\f[V]package-info.java\f[R] contains annotations. -This option does not generate a \f[V]package-info.class\f[R] file if -\f[V]package-info.java\f[R] contains only comments. -.RS -.PP -\f[B]Note:\f[R] A \f[V]package-info.class\f[R] file might be generated -but be empty if all the annotations in the \f[V]package-info.java\f[R] -file have \f[V]RetentionPolicy.SOURCE\f[R]. -.RE -.TP -\f[V]nonempty\f[R] -Generates a \f[V]package-info.class\f[R] file only if -\f[V]package-info.java\f[R] contains annotations with -\f[V]RetentionPolicy.CLASS\f[R] or \f[V]RetentionPolicy.RUNTIME\f[R]. -.RE -.TP -\f[V]-Xplugin:\f[R]\f[I]name\f[R] \f[I]args\f[R] -Specifies the name and optional arguments for a plug-in to be run. -If \f[I]args\f[R] are provided, \f[I]name\f[R] and \f[I]args\f[R] should -be quoted or otherwise escape the whitespace characters between the name -and all the arguments. -For details on the API for a plugin, see the API documentation for -\f[B]jdk.compiler/com.sun.source.util.Plugin\f[R]. -.TP -\f[V]-Xprefer:\f[R][\f[V]source\f[R], \f[V]newer\f[R]] -Specifies which file to read when both a source file and class file are -found for an implicitly compiled class using one of the following -options. -See \f[B]Searching for Module, Package and Type Declarations\f[R]. -.RS -.IP \[bu] 2 -\f[V]-Xprefer:newer\f[R]: Reads the newer of the source or class files -for a type (default). -.IP \[bu] 2 -\f[V]-Xprefer:source\f[R] : Reads the source file. -Use \f[V]-Xprefer:source\f[R] when you want to be sure that any -annotation processors can access annotations declared with a retention -policy of \f[V]SOURCE\f[R]. -.RE -.TP -\f[V]-Xprint\f[R] -Prints a textual representation of specified types for debugging -purposes. -This does not perform annotation processing or compilation. -The format of the output could change. -.TP -\f[V]-XprintProcessorInfo\f[R] -Prints information about which annotations a processor is asked to -process. -.TP -\f[V]-XprintRounds\f[R] -Prints information about initial and subsequent annotation processing -rounds. -.TP -\f[V]-Xstdout\f[R] \f[I]filename\f[R] -Sends compiler messages to the named file. -By default, compiler messages go to \f[V]System.err\f[R]. -.SH ENVIRONMENT VARIABLES -.SS CLASSPATH -.PP -If the \f[B]\f[VB]--class-path\f[B]\f[R] option or any of its alternate -forms are not specified, the class path will default to the value of the -\f[V]CLASSPATH\f[R] environment variable if it is set. -However, it is recommended that this environment variable should -\f[I]not\f[R] be set, and that the \f[V]--class-path\f[R] option should -be used to provide an explicit value for the class path when one is -required. -.SS JDK_JAVAC_OPTIONS -.PP -The content of the \f[V]JDK_JAVAC_OPTIONS\f[R] environment variable, -separated by white-spaces ( ) or white-space characters -(\f[V]\[rs]n\f[R], \f[V]\[rs]t\f[R], \f[V]\[rs]r\f[R], or -\f[V]\[rs]f\f[R]) is prepended to the command line arguments passed to -\f[V]javac\f[R] as a list of arguments. -.PP -The encoding requirement for the environment variable is the same as the -\f[V]javac\f[R] command line on the system. -\f[V]JDK_JAVAC_OPTIONS\f[R] environment variable content is treated in -the same manner as that specified in the command line. -.PP -Single quotes (\f[V]\[aq]\f[R]) or double quotes (\f[V]\[dq]\f[R]) can -be used to enclose arguments that contain whitespace characters. -All content between the open quote and the first matching close quote -are preserved by simply removing the pair of quotes. -In case a matching quote is not found, the launcher will abort with an -error message. -\f[V]\[at]\f[R]\f[I]files\f[R] are supported as they are specified in -the command line. -However, as in \f[V]\[at]\f[R]\f[I]files\f[R], use of a wildcard is not -supported. -.PP -\f[B]Examples of quoting arguments containing white spaces:\f[R] -.RS -.PP -\f[V]export JDK_JAVAC_OPTIONS=\[aq]\[at]\[dq]C:\[rs]white spaces\[rs]argfile\[dq]\[aq]\f[R] -.RE -.RS -.PP -\f[V]export JDK_JAVAC_OPTIONS=\[aq]\[dq]\[at]C:\[rs]white spaces\[rs]argfile\[dq]\[aq]\f[R] -.RE -.RS -.PP -\f[V]export JDK_JAVAC_OPTIONS=\[aq]\[at]C:\[rs]\[dq]white spaces\[dq]\[rs]argfile\[aq]\f[R] -.RE -.SH COMMAND-LINE ARGUMENT FILES -.PP -An argument file can include command-line options and source file names -in any combination. -The arguments within a file can be separated by spaces or new line -characters. -If a file name contains embedded spaces, then put the whole file name in -double quotation marks. -.PP -File names within an argument file are relative to the current -directory, not to the location of the argument file. -Wildcards (\f[V]*\f[R]) are not allowed in these lists (such as for -specifying \f[V]*.java\f[R]). -Use of the at sign (\f[V]\[at]\f[R]) to recursively interpret files is -not supported. -The \f[V]-J\f[R] options are not supported because they\[aq]re passed to -the launcher, which does not support argument files. -.PP -When executing the \f[V]javac\f[R] command, pass in the path and name of -each argument file with the at sign (\f[V]\[at]\f[R]) leading character. -When the \f[V]javac\f[R] command encounters an argument beginning with -the at sign (\f[V]\[at]\f[R]), it expands the contents of that file into -the argument list. -.SS Examples of Using javac \[at]filename -.TP -Single Argument File -You could use a single argument file named \f[V]argfile\f[R] to hold all -\f[V]javac\f[R] arguments: -.RS -.RS -.PP -\f[V]javac \[at]argfile\f[R] -.RE -.PP -This argument file could contain the contents of both files shown in the -following \f[B]Two Argument Files\f[R] example. -.RE -.TP -Two Argument Files -You can create two argument files: one for the \f[V]javac\f[R] options -and the other for the source file names. -Note that the following lists have no line-continuation characters. -.RS -.PP -Create a file named \f[V]options\f[R] that contains the following: -.PP -\f[B]Linux and macOS:\f[R] -.IP -.nf -\f[CB] --d classes --g --sourcepath /java/pubs/ws/1.3/src/share/classes -\f[R] -.fi -.PP -\f[B]Windows:\f[R] -.IP -.nf -\f[CB] --d classes --g --sourcepath C:\[rs]java\[rs]pubs\[rs]ws\[rs]1.3\[rs]src\[rs]share\[rs]classes -\f[R] -.fi -.PP -Create a file named \f[V]sources\f[R] that contains the following: -.IP -.nf -\f[CB] -MyClass1.java -MyClass2.java -MyClass3.java -\f[R] -.fi -.PP -Then, run the \f[V]javac\f[R] command as follows: -.RS -.PP -\f[V]javac \[at]options \[at]sources\f[R] -.RE -.RE -.TP -Argument Files with Paths -The argument files can have paths, but any file names inside the files -are relative to the current working directory (not \f[V]path1\f[R] or -\f[V]path2\f[R]): -.RS -.RS -.PP -\f[V]javac \[at]path1/options \[at]path2/sources\f[R] -.RE -.RE -.SH ARRANGEMENT OF SOURCE CODE -.PP -In the Java language, classes and interfaces can be organized into -packages, and packages can be organized into modules. -\f[V]javac\f[R] expects that the physical arrangement of source files in -directories of the file system will mirror the organization of classes -into packages, and packages into modules. -.PP -It is a widely adopted convention that module names and package names -begin with a lower-case letter, and that class names begin with an -upper-case letter. -.SS Arrangement of Source Code for a Package -.PP -When classes and interfaces are organized into a package, the package is -represented as a directory, and any subpackages are represented as -subdirectories. -.PP -For example: -.IP \[bu] 2 -The package \f[V]p\f[R] is represented as a directory called -\f[V]p\f[R]. -.IP \[bu] 2 -The package \f[V]p.q\f[R] -- that is, the subpackage \f[V]q\f[R] of -package \f[V]p\f[R] -- is represented as the subdirectory \f[V]q\f[R] of -directory \f[V]p\f[R]. -The directory tree representing package \f[V]p.q\f[R] is therefore -\f[V]p\[rs]q\f[R] on Windows, and \f[V]p/q\f[R] on other systems. -.IP \[bu] 2 -The package \f[V]p.q.r\f[R] is represented as the directory tree -\f[V]p\[rs]q\[rs]r\f[R] (on Windows) or \f[V]p/q/r\f[R] (on other -systems). -.PP -Within a directory or subdirectory, \f[V].java\f[R] files represent -classes and interfaces in the corresponding package or subpackage. -.PP -For example: -.IP \[bu] 2 -The class \f[V]X\f[R] declared in package \f[V]p\f[R] is represented by -the file \f[V]X.java\f[R] in the \f[V]p\f[R] directory. -.IP \[bu] 2 -The class \f[V]Y\f[R] declared in package \f[V]p.q\f[R] is represented -by the file \f[V]Y.java\f[R] in the \f[V]q\f[R] subdirectory of -directory \f[V]p\f[R]. -.IP \[bu] 2 -The class \f[V]Z\f[R] declared in package \f[V]p.q.r\f[R] is represented -by the file \f[V]Z.java\f[R] in the \f[V]r\f[R] subdirectory of -\f[V]p\[rs]q\f[R] (on Windows) or \f[V]p/q\f[R] (on other systems). -.PP -In some situations, it is convenient to split the code into separate -directories, each structured as described above, and the aggregate list -of directories specified to \f[V]javac\f[R]. -.SS Arrangement of Source Code for a Module -.PP -In the Java language, a module is a set of packages designed for reuse. -In addition to \f[V].java\f[R] files for classes and interfaces, each -module has a source file called \f[V]module-info.java\f[R] which: -.IP "1." 3 -declares the module\[aq]s name; -.IP "2." 3 -lists the packages exported by the module (to allow reuse by other -modules); -.IP "3." 3 -lists other modules required by the module (to reuse their exported -packages). -.PP -When packages are organized into a module, the module is represented by -one or more directories representing the packages in the module, one of -which contains the \f[V]module-info.java\f[R] file. -It may be convenient, but it is not required, to use a single directory, -named after the module, to contain the \f[V]module-info.java\f[R] file -alongside the directory tree which represents the packages in the module -(i.e., the \f[I]package hierarchy\f[R] described above). -The exact arrangement of source code for a module is typically dictated -by the conventions adopted by a development environment (IDE) or build -system. -.PP -For example: -.IP \[bu] 2 -The module \f[V]a.b.c\f[R] may be represented by the directory -\f[V]a.b.c\f[R], on all systems. -.IP \[bu] 2 -The module\[aq]s declaration is represented by the file -\f[V]module-info.java\f[R] in the \f[V]a.b.c\f[R] directory. -.IP \[bu] 2 -If the module contains package \f[V]p.q.r\f[R], then the \f[V]a.b.c\f[R] -directory contains the directory tree \f[V]p\[rs]q\[rs]r\f[R] (on -Windows) or \f[V]p/q/r\f[R] (on other systems). -.PP -The development environment may prescribe some directory hierarchy -between the directory named for the module and the source files to be -read by \f[V]javac\f[R]. -.PP -For example: -.IP \[bu] 2 -The module \f[V]a.b.c\f[R] may be represented by the directory -\f[V]a.b.c\f[R] -.IP \[bu] 2 -The module\[aq]s declaration and the module\[aq]s packages may be in -some subdirectory of \f[V]a.b.c\f[R], such as -\f[V]src\[rs]main\[rs]java\f[R] (on Windows) or \f[V]src/main/java\f[R] -(on other systems). -.SH CONFIGURING A COMPILATION -.PP -This section describes how to configure \f[V]javac\f[R] to perform a -basic compilation. -.PP -See \f[B]Configuring the Module System\f[R] for additional details for -use when compiling for a release of the platform that supports modules. -.SS Source Files -.IP \[bu] 2 -Specify the source files to be compiled on the command line. -.PP -If there are no compilation errors, the corresponding class files will -be placed in the \f[B]output directory\f[R]. -.PP -Some systems may limit the amount you can put on a command line; to work -around those limits, you can use \f[B]argument files\f[R]. -.PP -When compiling code for modules, you can also specify source files -indirectly, by using the \f[B]\f[VB]--module\f[B]\f[R] or \f[V]-m\f[R] -option. -.SS Output Directory -.IP \[bu] 2 -Use the \f[B]\f[VB]-d\f[B]\f[R] option to specify an output directory in -which to put the compiled class files. -.PP -This will normally be organized in a \f[B]package hierarchy\f[R], unless -you are compiling source code from multiple modules, in which case it -will be organized as a \f[B]module hierarchy\f[R]. -.PP -When the compilation has been completed, if you are compiling one or -more modules, you can place the output directory on the module path for -the Java \f[B]launcher\f[R]; otherwise, you can place the place the -output directory on the class path for the Java launcher. -.SS Precompiled Code -.PP -The code to be compiled may refer to libraries beyond what is provided -by the platform. -If so, you must place these libraries on the class path or module path. -If the library code is not in a module, place it on the class path; if -it is in a module, place it on the module path. -.IP \[bu] 2 -Use the \f[B]\f[VB]--class-path\f[B]\f[R] option to specify libraries to -be placed on the class path. -Locations on the class path should be organized in a \f[B]package -hierarchy\f[R]. -You can also use alternate forms of the option: \f[V]-classpath\f[R] or -\f[V]-cp\f[R]. -.IP \[bu] 2 -Use the \f[B]\f[VB]--module-path\f[B]\f[R] option to specify libraries -to be placed on the module path. -Locations on the module path should either be modules or directories of -modules. -You can also use an alternate form of the option: \f[V]-p\f[R]. -.RS 2 -.PP -See \f[B]Configuring the Module System\f[R] for details on how to modify -the default configuration of library modules. -.RE -.PP -\f[B]Note\f[R]: the options for the class path and module path are not -mutually exclusive, although it is not common to specify the class path -when compiling code for one or more modules. -.SS Additional Source Files -.PP -The code to be compiled may refer to types in additional source files -that are not specified on the command line. -If so, you must put those source files on either the source path or -module path. -You can only specify one of these options: if you are not compiling code -for a module, or if you are only compiling code for a single module, use -the source path; if you are compiling code for multiple modules, use the -module source path. -.IP \[bu] 2 -Use the \f[B]\f[VB]--source-path\f[B]\f[R] option to specify the -locations of additional source files that may be read by javac. -Locations on the source path should be organized in a \f[B]package -hierarchy\f[R]. -You can also use an alternate form of the option: \f[V]-sourcepath\f[R]. -.IP \[bu] 2 -Use the \f[B]\f[VB]--module-source-path\f[B]\f[R] option one or more -times to specify the location of additional source files in different -modules that may be read by javac, or when compiling source files in -multiple modules. -You can either specify the locations for each module -\f[B]individually\f[R], or you can organize the source files so that you -can specify the locations all \f[B]together\f[R]. -For more details, see \f[B]The Module Source Path Option\f[R]. -.PP -If you want to be able to refer to types in additional source files but -do not want them to be compiled, use the \f[B]\f[VB]-implicit\f[B]\f[R] -option. -.PP -\f[B]Note\f[R]: if you are compiling code for multiple modules, you must -always specify a module source path, and all source files specified on -the command line must be in one of the directories on the module source -path, or in a subdirectory thereof. -.SS Example of Compiling Multiple Source Files -.PP -This example compiles the \f[V]Aloha.java\f[R], \f[V]GutenTag.java\f[R], -\f[V]Hello.java\f[R], and \f[V]Hi.java\f[R] source files in the -\f[V]greetings\f[R] package. -.PP -\f[B]Linux and macOS:\f[R] -.IP -.nf -\f[CB] -% javac greetings/*.java -% ls greetings -Aloha.class GutenTag.class Hello.class Hi.class -Aloha.java GutenTag.java Hello.java Hi.java -\f[R] -.fi -.PP -\f[B]Windows:\f[R] -.IP -.nf -\f[CB] -C:\[rs]>javac greetings\[rs]*.java -C:\[rs]>dir greetings -Aloha.class GutenTag.class Hello.class Hi.class -Aloha.java GutenTag.java Hello.java Hi.java -\f[R] -.fi -.SS Example of Specifying a User Class Path -.PP -After changing one of the source files in the previous example, -recompile it: -.PP -\f[B]Linux and macOS:\f[R] -.IP -.nf -\f[CB] -pwd -/examples -javac greetings/Hi.java -\f[R] -.fi -.PP -\f[B]Windows:\f[R] -.IP -.nf -\f[CB] -C:\[rs]>cd -\[rs]examples -C:\[rs]>javac greetings\[rs]Hi.java -\f[R] -.fi -.PP -Because \f[V]greetings.Hi\f[R] refers to other classes in the -\f[V]greetings\f[R] package, the compiler needs to find these other -classes. -The previous example works because the default user class path is the -directory that contains the package directory. -If you want to recompile this file without concern for which directory -you are in, then add the examples directory to the user class path by -setting \f[V]CLASSPATH\f[R]. -This example uses the \f[V]-classpath\f[R] option. -.PP -\f[B]Linux and macOS:\f[R] -.RS -.PP -\f[V]javac -classpath /examples /examples/greetings/Hi.java\f[R] -.RE -.PP -\f[B]Windows:\f[R] -.RS -.PP -\f[V]C:\[rs]>javac -classpath \[rs]examples \[rs]examples\[rs]greetings\[rs]Hi.java\f[R] -.RE -.PP -If you change \f[V]greetings.Hi\f[R] to use a banner utility, then that -utility also needs to be accessible through the user class path. -.PP -\f[B]Linux and macOS:\f[R] -.IP -.nf -\f[CB] -javac -classpath /examples:/lib/Banners.jar \[rs] - /examples/greetings/Hi.java -\f[R] -.fi -.PP -\f[B]Windows:\f[R] -.IP -.nf -\f[CB] -C:\[rs]>javac -classpath \[rs]examples;\[rs]lib\[rs]Banners.jar \[ha] - \[rs]examples\[rs]greetings\[rs]Hi.java -\f[R] -.fi -.PP -To execute a class in the \f[V]greetings\f[R] package, the program needs -access to the \f[V]greetings\f[R] package, and to the classes that the -\f[V]greetings\f[R] classes use. -.PP -\f[B]Linux and macOS:\f[R] -.RS -.PP -\f[V]java -classpath /examples:/lib/Banners.jar greetings.Hi\f[R] -.RE -.PP -\f[B]Windows:\f[R] -.RS -.PP -\f[V]C:\[rs]>java -classpath \[rs]examples;\[rs]lib\[rs]Banners.jar greetings.Hi\f[R] -.RE -.SH CONFIGURING THE MODULE SYSTEM -.PP -If you want to include additional modules in your compilation, use the -\f[B]\f[VB]--add-modules\f[B]\f[R] option. -This may be necessary when you are compiling code that is not in a -module, or which is in an automatic module, and the code refers to API -in the additional modules. -.PP -If you want to restrict the set of modules in your compilation, use the -\f[B]\f[VB]--limit-modules\f[B]\f[R] option. -This may be useful if you want to ensure that the code you are compiling -is capable of running on a system with a limited set of modules -installed. -.PP -If you want to break encapsulation and specify that additional packages -should be considered as exported from a module, use the -\f[B]\f[VB]--add-exports\f[B]\f[R] option. -This may be useful when performing white-box testing; relying on access -to internal API in production code is strongly discouraged. -.PP -If you want to specify that additional packages should be considered as -required by a module, use the \f[B]\f[VB]--add-reads\f[B]\f[R] option. -This may be useful when performing white-box testing; relying on access -to internal API in production code is strongly discouraged. -.PP -You can patch additional content into any module using the -\f[B]\f[VB]--patch-module\f[B]\f[R] option. -See [Patching a Module] for more details. -.SH SEARCHING FOR MODULE, PACKAGE AND TYPE DECLARATIONS -.PP -To compile a source file, the compiler often needs information about a -module or type, but the declaration is not in the source files specified -on the command line. -.PP -\f[V]javac\f[R] needs type information for every class or interface -used, extended, or implemented in the source file. -This includes classes and interfaces not explicitly mentioned in the -source file, but that provide information through inheritance. -.PP -For example, when you create a subclass of \f[V]java.awt.Window\f[R], -you are also using the ancestor classes of \f[V]Window\f[R]: -\f[V]java.awt.Container\f[R], \f[V]java.awt.Component\f[R], and -\f[V]java.lang.Object\f[R]. -.PP -When compiling code for a module, the compiler also needs to have -available the declaration of that module. -.PP -A successful search may produce a class file, a source file, or both. -If both are found, then you can use the \f[B]\f[VB]-Xprefer\f[B]\f[R] -option to instruct the compiler which to use. -.PP -If a search finds and uses a source file, then by default -\f[V]javac\f[R] compiles that source file. -This behavior can be altered with \f[B]\f[VB]-implicit\f[B]\f[R]. -.PP -The compiler might not discover the need for some type information until -after annotation processing completes. -When the type information is found in a source file and no -\f[B]\f[VB]-implicit\f[B]\f[R] option is specified, the compiler gives a -warning that the file is being compiled without being subject to -annotation processing. -To disable the warning, either specify the file on the command line (so -that it will be subject to annotation processing) or use the -\f[B]\f[VB]-implicit\f[B]\f[R] option to specify whether or not class -files should be generated for such source files. -.PP -The way that \f[V]javac\f[R] locates the declarations of those types -depends on whether the reference exists within code for a module or not. -.SS Searching Package Oriented Paths -.PP -When searching for a source or class file on a path composed of package -oriented locations, \f[V]javac\f[R] will check each location on the path -in turn for the possible presence of the file. -The first occurrence of a particular file shadows (hides) any subsequent -occurrences of like-named files. -This shadowing does not affect any search for any files with a different -name. -This can be convenient when searching for source files, which may be -grouped in different locations, such as shared code, platform-specific -code and generated code. -It can also be useful when injecting alternate versions of a class file -into a package, to debugging or other instrumentation reasons. -But, it can also be dangerous, such as when putting incompatible -different versions of a library on the class path. -.SS Searching Module Oriented Paths -.PP -Prior to scanning any module paths for any package or type declarations, -\f[V]javac\f[R] will lazily scan the following paths and locations to -determine the modules that will be used in the compilation. -.IP \[bu] 2 -The module source path (see the -\f[B]\f[VB]--module-source-path\f[B]\f[R] option) -.IP \[bu] 2 -The path for upgradeable modules (see the -\f[B]\f[VB]--upgrade-module-path\f[B]\f[R] option) -.IP \[bu] 2 -The system modules (see the \f[B]\f[VB]--system\f[B]\f[R] option) -.IP \[bu] 2 -The user module path ( see the \f[B]\f[VB]--module-path\f[B]\f[R] -option) -.PP -For any module, the first occurrence of the module during the scan -completely shadows (hides) any subsequent appearance of a like-named -module. -While locating the modules, \f[V]javac\f[R] is able to determine the -packages exported by the module and to associate with each module a -package oriented path for the contents of the module. -For any previously compiled module, this path will typically be a single -entry for either a directory or a file that provides an internal -directory-like hierarchy, such as a JAR file. -Thus, when searching for a type that is in a package that is known to be -exported by a module, \f[V]javac\f[R] can locate the declaration -directly and efficiently. -.SS Searching for the Declaration of a Module -.PP -If the module has been previously compiled, the module declaration is -located in a file named \f[V]module-info.class\f[R] in the root of the -package hierarchy for the content of the module. -.PP -If the module is one of those currently being compiled, the module -declaration will be either the file named \f[V]module-info.class\f[R] in -the root of the package hierarchy for the module in the class output -directory, or the file named \f[V]module-info.java\f[R] in one of the -locations on the source path or one the module source path for the -module. -.SS Searching for the Declaration of a Type When the Reference is not in a Module -.PP -When searching for a type that is referenced in code that is not in a -module, \f[V]javac\f[R] will look in the following places: -.IP \[bu] 2 -The platform classes (or the types in exported packages of the platform -modules) (This is for compiled class files only.) -.IP \[bu] 2 -Types in exported packages of any modules on the module path, if -applicable. -(This is for compiled class files only.) -.IP \[bu] 2 -Types in packages on the class path and/or source path: -.RS 2 -.IP \[bu] 2 -If both are specified, \f[V]javac\f[R] looks for compiled class files on -the class path and for source files on the source path. -.IP \[bu] 2 -If the class path is specified, but not source path, \f[V]javac\f[R] -looks for both compiled class files and source files on the class path. -.IP \[bu] 2 -If the class path is not specified, it defaults to the current -directory. -.RE -.PP -When looking for a type on the class path and/or source path, if both a -compiled class file and a source file are found, the most recently -modified file will be used by default. -If the source file is newer, it will be compiled and will may override -any previously compiled version of the file. -You can use the \f[B]\f[VB]-Xprefer\f[B]\f[R] option to override the -default behavior. -.SS Searching for the Declaration of a Type When the Reference is in a Module -.PP -When searching for a type that is referenced in code in a module, -\f[V]javac\f[R] will examine the declaration of the enclosing module to -determine if the type is in a package that is exported from another -module that is readable by the enclosing module. -If so, \f[V]javac\f[R] will simply and directly go to the definition of -that module to find the definition of the required type. -Unless the module is another of the modules being compiled, -\f[V]javac\f[R] will only look for compiled class files files. -In other words, \f[V]javac\f[R] will not look for source files in -platform modules or modules on the module path. -.PP -If the type being referenced is not in some other readable module, -\f[V]javac\f[R] will examine the module being compiled to try and find -the declaration of the type. -\f[V]javac\f[R] will look for the declaration of the type as follows: -.IP \[bu] 2 -Source files specified on the command line or on the source path or -module source path. -.IP \[bu] 2 -Previously compiled files in the output directory. -.SH DIRECTORY HIERARCHIES -.PP -\f[V]javac\f[R] generally assumes that source files and compiled class -files will be organized in a file system directory hierarchy or in a -type of file that supports in an internal directory hierarchy, such as a -JAR file. -Three different kinds of hierarchy are supported: a \f[I]package -hierarchy\f[R], a \f[I]module hierarchy\f[R], and a \f[I]module source -hierarchy\f[R]. -.PP -While \f[V]javac\f[R] is fairly relaxed about the organization of source -code, beyond the expectation that source will be organized in one or -package hierarchies, and can generally accommodate organizations -prescribed by development environments and build tools, Java tools in -general, and \f[V]javac\f[R] and the Java launcher in particular, are -more stringent regarding the organization of compiled class files, and -will be organized in package hierarchies or module hierarchies, as -appropriate. -.PP -The location of these hierarchies are specified to \f[V]javac\f[R] with -command-line options, whose names typically end in \[dq]path\[dq], like -\f[B]\f[VB]--source-path\f[B]\f[R] or \f[B]\f[VB]--class-path\f[B]\f[R]. -Also as a general rule, path options whose name includes the word -\f[V]module\f[R], like \f[B]\f[VB]--module-path\f[B]\f[R], are used to -specify module hierarchies, although some module-related path options -allow a package hierarchy to be specified on a per-module basis. -All other path options are used to specify package hierarchies. -.SS Package Hierarchy -.PP -In a package hierarchy, directories and subdirectories are used to -represent the component parts of the package name, with the source file -or compiled class file for a type being stored as a file with an -extension of \f[V].java\f[R] or \f[V].class\f[R] in the most nested -directory. -.PP -For example, in a package hierarchy, the source file for a class -\f[V]com.example.MyClass\f[R] will be stored in the file -\f[I]com/example/MyClass.java\f[R] -.SS Module Hierarchy -.PP -In a module hierarchy, the first level of directories are named for the -modules in the hierarchy; within each of those directories the contents -of the module are organized in package hierarchies. -.PP -For example, in a module hierarchy, the compiled class file for a type -called \f[V]com.example.MyClass\f[R] in a module called -\f[V]my.library\f[R] will be stored in -\f[I]my.library/com/example/MyClass.class\f[R]. -.PP -The various output directories used by \f[V]javac\f[R] (the class output -directory, the source output directory, and native header output -directory) will all be organized in a module hierarchy when multiple -modules are being compiled. -.SS Module Source Hierarchy -.PP -Although the source for each individual module should always be -organized in a package hierarchy, it may be convenient to group those -hierarchies into a module source hierarchy. -This is similar to a module hierarchy, except that there may be -intervening directories between the directory for the module and the -directory that is the root of the package hierarchy for the source code -of the module. -.PP -For example, in a module source hierarchy, the source file for a type -called \f[V]com.example.MyClass\f[R] in a module called -\f[V]my.library\f[R] may be stored in a file such as -\f[I]my.library/src/main/java/com/example/MyClass.java\f[R]. -.SH THE MODULE SOURCE PATH OPTION -.PP -The \f[B]\f[VB]--module-source-path\f[B]\f[R] option has two forms: a -\f[I]module-specific form\f[R], in which a package path is given for -each module containing code to be compiled, and a -\f[I]module-pattern\f[R] form, in which the source path for each module -is specified by a pattern. -The module-specific form is generally simpler to use when only a small -number of modules are involved; the module-pattern form may be more -convenient when the number of modules is large and the modules are -organized in a regular manner that can be described by a pattern. -.PP -Multiple instances of the \f[V]--module-source-path\f[R] option may be -given, each one using either the module-pattern form or the -module-specific form, subject to the following limitations: -.IP \[bu] 2 -the module-pattern form may be used at most once -.IP \[bu] 2 -the module-specific form may be used at most once for any given module -.PP -If the module-specific form is used for any module, the associated -search path overrides any path that might otherwise have been inferred -from the module-pattern form. -.SS Module-specific form -.PP -The module-specific form allows an explicit search path to be given for -any specific module. -This form is: -.IP \[bu] 2 -\f[V]--module-source-path\f[R] -\f[I]module-name\f[R]\f[V]=\f[R]\f[I]file-path\f[R] -(\f[I]path-separator\f[R] \f[I]file-path\f[R])* -.PP -The path separator character is \f[V];\f[R] on Windows, and \f[V]:\f[R] -otherwise. -.PP -\f[B]Note:\f[R] this is similar to the form used for the -\f[B]\f[VB]--patch-module\f[B]\f[R] option. -.SS Module-pattern form -.PP -The module-pattern form allows a concise specification of the module -source path for any number of modules organized in regular manner. -.IP \[bu] 2 -\f[V]--module-source-path\f[R] \f[I]pattern\f[R] -.PP -The pattern is defined by the following rules, which are applied in -order: -.IP \[bu] 2 -The argument is considered to be a series of segments separated by the -path separator character (\f[V];\f[R] on Windows, and \f[V]:\f[R] -otherwise). -.IP \[bu] 2 -Each segment containing curly braces of the form -.RS 2 -.IP -.nf -\f[CB] -string1{alt1 ( ,alt2 )* } string2 -\f[R] -.fi -.PP -is considered to be replaced by a series of segments formed by -\[dq]expanding\[dq] the braces: -.IP -.nf -\f[CB] -string1 alt1 string2 -string1 alt2 string2 -and so on... -\f[R] -.fi -.PP -The braces may be nested. -.PP -This rule is applied for all such usages of braces. -.RE -.IP \[bu] 2 -Each segment must have at most one asterisk (\f[V]*\f[R]). -If a segment does not contain an asterisk, it is considered to be as -though the file separator character and an asterisk are appended. -.RS 2 -.PP -For any module \f[I]M\f[R], the source path for that module is formed -from the series of segments obtained by substituting the module name -\f[I]M\f[R] for the asterisk in each segment. -.PP -\f[B]Note\f[R]: in this context, the asterisk is just used as a special -marker, to denote the position in the path of the module name. -It should not be confused with the use of \f[V]*\f[R] as a file name -wildcard character, as found on most operating systems. -.RE -.SH PATCHING MODULES -.PP -javac allows any content, whether in source or compiled form, to be -patched into any module using the \f[B]\f[VB]--patch-module\f[B]\f[R] -option. -You may want to do this to compile alternative implementations of a -class to be patched at runtime into a JVM, or to inject additional -classes into the module, such as when testing. -.PP -The form of the option is: -.IP \[bu] 2 -\f[V]--patch-module\f[R] -\f[I]module-name\f[R]\f[V]=\f[R]\f[I]file-path\f[R] -(\f[I]path-separator\f[R] \f[I]file-path\f[R] )* -.PP -The path separator character is \f[V];\f[R] on Windows, and \f[V]:\f[R] -otherwise. -The paths given for the module must specify the root of a package -hierarchy for the contents of the module -.PP -The option may be given at most once for any given module. -Any content on the path will hide any like-named content later in the -path and in the patched module. -.PP -When patching source code into more than one module, the -\f[B]\f[VB]--module-source-path\f[B]\f[R] must also be used, so that the -output directory is organized in a module hierarchy, and capable of -holding the compiled class files for the modules being compiled. -.SH ANNOTATION PROCESSING -.PP -The \f[V]javac\f[R] command provides direct support for annotation -processing. -.PP -The API for annotation processors is defined in the -\f[V]javax.annotation.processing\f[R] and \f[V]javax.lang.model\f[R] -packages and subpackages. -.SS How Annotation Processing Works -.PP -Unless annotation processing is disabled with the -\f[B]\f[VB]-proc:none\f[B]\f[R] option, the compiler searches for any -annotation processors that are available. -The search path can be specified with the -\f[B]\f[VB]-processorpath\f[B]\f[R] option. -If no path is specified, then the user class path is used. -Processors are located by means of service provider-configuration files -named \f[V]META-INF/services/javax.annotation.processing.Processor\f[R] -on the search path. -Such files should contain the names of any annotation processors to be -used, listed one per line. -Alternatively, processors can be specified explicitly, using the -\f[B]\f[VB]-processor\f[B]\f[R] option. -.PP -After scanning the source files and classes on the command line to -determine what annotations are present, the compiler queries the -processors to determine what annotations they process. -When a match is found, the processor is called. -A processor can claim the annotations it processes, in which case no -further attempt is made to find any processors for those annotations. -After all of the annotations are claimed, the compiler does not search -for additional processors. -.PP -If any processors generate new source files, then another round of -annotation processing occurs: Any newly generated source files are -scanned, and the annotations processed as before. -Any processors called on previous rounds are also called on all -subsequent rounds. -This continues until no new source files are generated. -.PP -After a round occurs where no new source files are generated, the -annotation processors are called one last time, to give them a chance to -complete any remaining work. -Finally, unless the \f[B]\f[VB]-proc:only\f[B]\f[R] option is used, the -compiler compiles the original and all generated source files. -.PP -If you use an annotation processor that generates additional source -files to be included in the compilation, you can specify a default -module to be used for the newly generated files, for use when a module -declaration is not also generated. -In this case, use the -\f[B]\f[VB]--default-module-for-created-files\f[B]\f[R] option. -.SS Compilation Environment and Runtime Environment. -.PP -The declarations in source files and previously compiled class files are -analyzed by \f[V]javac\f[R] in a \f[I]compilation environment\f[R] that -is distinct from the \f[I]runtime environment\f[R] used to execute -\f[V]javac\f[R] itself. -Although there is a deliberate similarity between many \f[V]javac\f[R] -options and like-named options for the Java \f[B]launcher\f[R], such as -\f[V]--class-path\f[R], \f[V]--module-path\f[R] and so on, it is -important to understand that in general the \f[V]javac\f[R] options just -affect the environment in which the source files are compiled, and do -not affect the operation of \f[V]javac\f[R] itself. -.PP -The distinction between the compilation environment and runtime -environment is significant when it comes to using annotation processors. -Although annotations processors process elements (declarations) that -exist in the compilation environment, the annotation processor itself is -executed in the runtime environment. -If an annotation processor has dependencies on libraries that are not in -modules, the libraries can be placed, along with the annotation -processor itself, on the processor path. -(See the \f[B]\f[VB]--processor-path\f[B]\f[R] option.) -If the annotation processor and its dependencies are in modules, you -should use the processor module path instead. -(See the \f[B]\f[VB]--processor-module-path\f[B]\f[R] option.) -When those are insufficient, it may be necessary to provide further -configuration of the runtime environment. -This can be done in two ways: -.IP "1." 3 -If \f[V]javac\f[R] is invoked from the command line, options can be -passed to the underlying runtime by prefixing the option with -\f[B]\f[VB]-J\f[B]\f[R]. -.IP "2." 3 -You can start an instance of a Java Virtual Machine directly and use -command line options and API to configure an environment in which -\f[V]javac\f[R] can be invoked via one of its \f[B]APIs\f[R]. -.SH COMPILING FOR EARLIER RELEASES OF THE PLATFORM -.PP -\f[V]javac\f[R] can compile code that is to be used on other releases of -the platform, using either the \f[B]\f[VB]--release\f[B]\f[R] option, or -the \f[B]\f[VB]--source\f[B]\f[R]/\f[V]-source\f[R] and -\f[B]\f[VB]--target\f[B]\f[R]/\f[V]-target\f[R] options, together with -additional options to specify the platform classes. -.PP -Depending on the desired platform release, there are some restrictions -on some of the options that can be used. -.IP \[bu] 2 -When compiling for JDK 8 and earlier releases, you cannot use any option -that is intended for use with the module system. -This includes all of the following options: -.RS 2 -.IP \[bu] 2 -\f[B]\f[VB]--module-source-path\f[B]\f[R], -\f[B]\f[VB]--upgrade-module-path\f[B]\f[R], -\f[B]\f[VB]--system\f[B]\f[R], \f[B]\f[VB]--module-path\f[B]\f[R], -\f[B]\f[VB]--add-modules\f[B]\f[R], \f[B]\f[VB]--add-exports\f[B]\f[R], -\f[V]--add-opens\f[R], \f[B]\f[VB]--add-reads\f[B]\f[R], -\f[B]\f[VB]--limit-modules\f[B]\f[R], -\f[B]\f[VB]--patch-module\f[B]\f[R] -.PP -If you use the \f[V]--source\f[R]/\f[V]-source\f[R] or -\f[V]--target\f[R]/\f[V]-target\f[R] options, you should also set the -appropriate platform classes using the boot class path family of -options. -.RE -.IP \[bu] 2 -When compiling for JDK 9 and later releases, you cannot use any option -that is intended to configure the boot class path. -This includes all of the following options: -.RS 2 -.IP \[bu] 2 -\f[B]\f[VB]-Xbootclasspath/p:\f[B]\f[R], -\f[B]\f[VB]-Xbootclasspath\f[B]\f[R], -\f[B]\f[VB]-Xbootclasspath/a:\f[B]\f[R], -\f[B]\f[VB]-endorseddirs\f[B]\f[R], -\f[B]\f[VB]-Djava.endorsed.dirs\f[B]\f[R], -\f[B]\f[VB]-extdirs\f[B]\f[R], \f[B]\f[VB]-Djava.ext.dirs\f[B]\f[R], -\f[B]\f[VB]-profile\f[B]\f[R] -.PP -If you use the \f[V]--source\f[R]/\f[V]-source\f[R] or -\f[V]--target\f[R]/\f[V]-target\f[R] options, you should also set the -appropriate platform classes using the \f[V]--system\f[R] option to give -the location of an appropriate installed release of JDK. -.RE -.PP -When using the \f[V]--release\f[R] option, only the supported documented -API for that release may be used; you cannot use any options to break -encapsulation to access any internal classes. -.SH APIS -.PP -The \f[V]javac\f[R] compiler can be invoked using an API in three -different ways: -.TP -The \f[B]Java Compiler API\f[R] -This provides the most flexible way to invoke the compiler, including -the ability to compile source files provided in memory buffers or other -non-standard file systems. -.TP -The \f[B]ToolProvider API\f[R] -A \f[V]ToolProvider\f[R] for \f[V]javac\f[R] can be obtained by calling -\f[V]ToolProvider.findFirst(\[dq]javac\[dq])\f[R]. -This returns an object with the equivalent functionality of the -command-line tool. -.RS -.PP -\f[B]Note\f[R]: This API should not be confused with the like-named API -in the \f[B]\f[VB]javax.tools\f[B]\f[R] package. -.RE -.TP -The \f[V]javac\f[R] \f[B]Legacy API\f[R] -This API is retained for backward compatibility only. -All new code should use either the Java Compiler API or the ToolProvider -API. -.PP -\f[B]Note:\f[R] All other classes and methods found in a package with -names that start with \f[V]com.sun.tools.javac\f[R] (subpackages of -\f[V]com.sun.tools.javac\f[R]) are strictly internal and subject to -change at any time. -.SH EXAMPLES OF USING -XLINT KEYS -.TP -\f[V]cast\f[R] -Warns about unnecessary and redundant casts, for example: -.RS -.RS -.PP -\f[V]String s = (String) \[dq]Hello!\[dq]\f[R] -.RE -.RE -.TP -\f[V]classfile\f[R] -Warns about issues related to class file contents. -.TP -\f[V]deprecation\f[R] -Warns about the use of deprecated items. -For example: -.RS -.IP -.nf -\f[CB] -java.util.Date myDate = new java.util.Date(); -int currentDay = myDate.getDay(); -\f[R] -.fi -.PP -The method \f[V]java.util.Date.getDay\f[R] has been deprecated since JDK -1.1. -.RE -.TP -\f[V]dep-ann\f[R] -Warns about items that are documented with the \f[V]\[at]deprecated\f[R] -Javadoc comment, but do not have the \f[V]\[at]Deprecated\f[R] -annotation, for example: -.RS -.IP -.nf -\f[CB] -/** - * \[at]deprecated As of Java SE 7, replaced by {\[at]link #newMethod()} - */ -public static void deprecatedMethod() { } -public static void newMethod() { } -\f[R] -.fi -.RE -.TP -\f[V]divzero\f[R] -Warns about division by the constant integer 0, for example: -.RS -.RS -.PP -\f[V]int divideByZero = 42 / 0;\f[R] -.RE -.RE -.TP -\f[V]empty\f[R] -Warns about empty statements after \f[V]if\f[R]statements, for example: -.RS -.IP -.nf -\f[CB] -class E { - void m() { - if (true) ; - } -} -\f[R] -.fi -.RE -.TP -\f[V]fallthrough\f[R] -Checks the switch blocks for fall-through cases and provides a warning -message for any that are found. -Fall-through cases are cases in a switch block, other than the last case -in the block, whose code does not include a \f[V]break\f[R] statement, -allowing code execution to fall through from that case to the next case. -For example, the code following the case 1 label in this switch block -does not end with a \f[V]break\f[R] statement: -.RS -.IP -.nf -\f[CB] -switch (x) { -case 1: - System.out.println(\[dq]1\[dq]); - // No break statement here. -case 2: - System.out.println(\[dq]2\[dq]); -} -\f[R] -.fi -.PP -If the \f[V]-Xlint:fallthrough\f[R] option was used when compiling this -code, then the compiler emits a warning about possible fall-through into -case, with the line number of the case in question. -.RE -.TP -\f[V]finally\f[R] -Warns about \f[V]finally\f[R] clauses that cannot be completed normally, -for example: -.RS -.IP -.nf -\f[CB] -public static int m() { - try { - throw new NullPointerException(); - } catch (NullPointerException(); { - System.err.println(\[dq]Caught NullPointerException.\[dq]); - return 1; - } finally { - return 0; - } - } -\f[R] -.fi -.PP -The compiler generates a warning for the \f[V]finally\f[R] block in this -example. -When the \f[V]int\f[R] method is called, it returns a value of 0. -A \f[V]finally\f[R] block executes when the \f[V]try\f[R] block exits. -In this example, when control is transferred to the \f[V]catch\f[R] -block, the \f[V]int\f[R] method exits. -However, the \f[V]finally\f[R] block must execute, so it\[aq]s executed, -even though control was transferred outside the method. -.RE -.TP -\f[V]options\f[R] -Warns about issues that related to the use of command-line options. -See \f[B]Compiling for Earlier Releases of the Platform\f[R]. -.TP -\f[V]overrides\f[R] -Warns about issues related to method overrides. -For example, consider the following two classes: -.RS -.IP -.nf -\f[CB] -public class ClassWithVarargsMethod { - void varargsMethod(String... s) { } -} - -public class ClassWithOverridingMethod extends ClassWithVarargsMethod { - \[at]Override - void varargsMethod(String[] s) { } -} -\f[R] -.fi -.PP -The compiler generates a warning similar to the following:. -.IP -.nf -\f[CB] -warning: [override] varargsMethod(String[]) in ClassWithOverridingMethod -overrides varargsMethod(String...) in ClassWithVarargsMethod; overriding -method is missing \[aq]...\[aq] -\f[R] -.fi -.PP -When the compiler encounters a \f[V]varargs\f[R] method, it translates -the \f[V]varargs\f[R] formal parameter into an array. -In the method \f[V]ClassWithVarargsMethod.varargsMethod\f[R], the -compiler translates the \f[V]varargs\f[R] formal parameter -\f[V]String... s\f[R] to the formal parameter \f[V]String[] s\f[R], an -array that matches the formal parameter of the method -\f[V]ClassWithOverridingMethod.varargsMethod\f[R]. -Consequently, this example compiles. -.RE -.TP -\f[V]path\f[R] -Warns about invalid path elements and nonexistent path directories on -the command line (with regard to the class path, the source path, and -other paths). -Such warnings cannot be suppressed with the -\f[V]\[at]SuppressWarnings\f[R] annotation. -For example: -.RS -.IP \[bu] 2 -\f[B]Linux and macOS:\f[R] -\f[V]javac -Xlint:path -classpath /nonexistentpath Example.java\f[R] -.IP \[bu] 2 -\f[B]Windows:\f[R] -\f[V]javac -Xlint:path -classpath C:\[rs]nonexistentpath Example.java\f[R] -.RE -.TP -\f[V]processing\f[R] -Warns about issues related to annotation processing. -The compiler generates this warning when you have a class that has an -annotation, and you use an annotation processor that cannot handle that -type of annotation. -For example, the following is a simple annotation processor: -.RS -.PP -\f[B]Source file AnnoProc.java\f[R]: -.IP -.nf -\f[CB] -import java.util.*; -import javax.annotation.processing.*; -import javax.lang.model.*; -import javax.lang.model.element.*; - -\[at]SupportedAnnotationTypes(\[dq]NotAnno\[dq]) -public class AnnoProc extends AbstractProcessor { - public boolean process(Set elems, RoundEnvironment renv){ - return true; - } - - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latest(); - } -} -\f[R] -.fi -.PP -\f[B]Source file AnnosWithoutProcessors.java\f[R]: -.IP -.nf -\f[CB] -\[at]interface Anno { } - -\[at]Anno -class AnnosWithoutProcessors { } -\f[R] -.fi -.PP -The following commands compile the annotation processor -\f[V]AnnoProc\f[R], then run this annotation processor against the -source file \f[V]AnnosWithoutProcessors.java\f[R]: -.IP -.nf -\f[CB] -javac AnnoProc.java -javac -cp . -Xlint:processing -processor AnnoProc -proc:only AnnosWithoutProcessors.java -\f[R] -.fi -.PP -When the compiler runs the annotation processor against the source file -\f[V]AnnosWithoutProcessors.java\f[R], it generates the following -warning: -.IP -.nf -\f[CB] -warning: [processing] No processor claimed any of these annotations: Anno -\f[R] -.fi -.PP -To resolve this issue, you can rename the annotation defined and used in -the class \f[V]AnnosWithoutProcessors\f[R] from \f[V]Anno\f[R] to -\f[V]NotAnno\f[R]. -.RE -.TP -\f[V]rawtypes\f[R] -Warns about unchecked operations on raw types. -The following statement generates a \f[V]rawtypes\f[R] warning: -.RS -.RS -.PP -\f[V]void countElements(List l) { ... }\f[R] -.RE -.PP -The following example does not generate a \f[V]rawtypes\f[R] warning: -.RS -.PP -\f[V]void countElements(List l) { ... }\f[R] -.RE -.PP -\f[V]List\f[R] is a raw type. -However, \f[V]List\f[R] is an unbounded wildcard parameterized type. -Because \f[V]List\f[R] is a parameterized interface, always specify its -type argument. -In this example, the \f[V]List\f[R] formal argument is specified with an -unbounded wildcard (\f[V]?\f[R]) as its formal type parameter, which -means that the \f[V]countElements\f[R] method can accept any -instantiation of the \f[V]List\f[R] interface. -.RE -.TP -\f[V]serial\f[R] -Warns about missing \f[V]serialVersionUID\f[R] definitions on -serializable classes. -For example: -.RS -.IP -.nf -\f[CB] -public class PersistentTime implements Serializable -{ - private Date time; - - public PersistentTime() { - time = Calendar.getInstance().getTime(); - } - - public Date getTime() { - return time; - } -} -\f[R] -.fi -.PP -The compiler generates the following warning: -.IP -.nf -\f[CB] -warning: [serial] serializable class PersistentTime has no definition of -serialVersionUID -\f[R] -.fi -.PP -If a serializable class does not explicitly declare a field named -\f[V]serialVersionUID\f[R], then the serialization runtime environment -calculates a default \f[V]serialVersionUID\f[R] value for that class -based on various aspects of the class, as described in the Java Object -Serialization Specification. -However, it\[aq]s strongly recommended that all serializable classes -explicitly declare \f[V]serialVersionUID\f[R] values because the default -process of computing \f[V]serialVersionUID\f[R] values is highly -sensitive to class details that can vary depending on compiler -implementations. -As a result, this might cause an unexpected -\f[V]InvalidClassExceptions\f[R] during deserialization. -To guarantee a consistent \f[V]serialVersionUID\f[R] value across -different Java compiler implementations, a serializable class must -declare an explicit \f[V]serialVersionUID\f[R] value. -.RE -.TP -\f[V]static\f[R] -Warns about issues relating to the use of static variables, for example: -.RS -.IP -.nf -\f[CB] -class XLintStatic { - static void m1() { } - void m2() { this.m1(); } -} -\f[R] -.fi -.PP -The compiler generates the following warning: -.IP -.nf -\f[CB] -warning: [static] static method should be qualified by type name, -XLintStatic, instead of by an expression -\f[R] -.fi -.PP -To resolve this issue, you can call the \f[V]static\f[R] method -\f[V]m1\f[R] as follows: -.RS -.PP -\f[V]XLintStatic.m1();\f[R] -.RE -.PP -Alternately, you can remove the \f[V]static\f[R] keyword from the -declaration of the method \f[V]m1\f[R]. -.RE -.TP -\f[V]this-escape\f[R] -Warns about constructors leaking \f[V]this\f[R] prior to subclass -initialization. -For example, this class: -.RS -.IP -.nf -\f[CB] -public class MyClass { - public MyClass() { - System.out.println(this.hashCode()); - } -} -\f[R] -.fi -.PP -generates the following warning: -.IP -.nf -\f[CB] -MyClass.java:3: warning: [this-escape] possible \[aq]this\[aq] escape - before subclass is fully initialized - System.out.println(this.hashCode()); - \[ha] -\f[R] -.fi -.PP -A \[aq]this\[aq] escape warning is generated when a constructor does -something that might result in a subclass method being invoked before -the constructor returns. -In such cases the subclass method would be operating on an incompletely -initialized instance. -In the above example, a subclass of \f[V]MyClass\f[R] that overrides -\f[V]hashCode()\f[R] to incorporate its own fields would likely produce -an incorrect result when invoked as shown. -.PP -Warnings are only generated if a subclass could exist that is outside of -the current module (or package, if no module) being compiled. -So, for example, constructors in final and non-public classes do not -generate warnings. -.RE -.TP -\f[V]try\f[R] -Warns about issues relating to the use of \f[V]try\f[R] blocks, -including try-with-resources statements. -For example, a warning is generated for the following statement because -the resource \f[V]ac\f[R] declared in the \f[V]try\f[R] block is not -used: -.RS -.IP -.nf -\f[CB] -try ( AutoCloseable ac = getResource() ) { // do nothing} -\f[R] -.fi -.RE -.TP -\f[V]unchecked\f[R] -Gives more detail for unchecked conversion warnings that are mandated by -the Java Language Specification, for example: -.RS -.IP -.nf -\f[CB] -List l = new ArrayList(); -List ls = l; // unchecked warning -\f[R] -.fi -.PP -During type erasure, the types \f[V]ArrayList\f[R] and -\f[V]List\f[R] become \f[V]ArrayList\f[R] and \f[V]List\f[R], -respectively. -.PP -The \f[V]ls\f[R] command has the parameterized type -\f[V]List\f[R]. -When the \f[V]List\f[R] referenced by \f[V]l\f[R] is assigned to -\f[V]ls\f[R], the compiler generates an unchecked warning. -At compile time, the compiler and JVM cannot determine whether -\f[V]l\f[R] refers to a \f[V]List\f[R] type. -In this case, \f[V]l\f[R] does not refer to a \f[V]List\f[R] -type. -As a result, heap pollution occurs. -.PP -A heap pollution situation occurs when the \f[V]List\f[R] object -\f[V]l\f[R], whose static type is \f[V]List\f[R], is assigned to -another \f[V]List\f[R] object, \f[V]ls\f[R], that has a different static -type, \f[V]List\f[R]. -However, the compiler still allows this assignment. -It must allow this assignment to preserve backward compatibility with -releases of Java SE that do not support generics. -Because of type erasure, \f[V]List\f[R] and -\f[V]List\f[R] both become \f[V]List\f[R]. -Consequently, the compiler allows the assignment of the object -\f[V]l\f[R], which has a raw type of \f[V]List\f[R], to the object -\f[V]ls\f[R]. -.RE -.TP -\f[V]varargs\f[R] -Warns about unsafe use of variable arguments (\f[V]varargs\f[R]) -methods, in particular, those that contain non-reifiable arguments, for -example: -.RS -.IP -.nf -\f[CB] -public class ArrayBuilder { - public static void addToList (List listArg, T... elements) { - for (T x : elements) { - listArg.add(x); - } - } -} -\f[R] -.fi -.PP -A non-reifiable type is a type whose type information is not fully -available at runtime. -.PP -The compiler generates the following warning for the definition of the -method \f[V]ArrayBuilder.addToList\f[R]: -.IP -.nf -\f[CB] -warning: [varargs] Possible heap pollution from parameterized vararg type T -\f[R] -.fi -.PP -When the compiler encounters a varargs method, it translates the -\f[V]varargs\f[R] formal parameter into an array. -However, the Java programming language does not permit the creation of -arrays of parameterized types. -In the method \f[V]ArrayBuilder.addToList\f[R], the compiler translates -the \f[V]varargs\f[R] formal parameter \f[V]T...\f[R] elements to the -formal parameter \f[V]T[]\f[R] elements, an array. -However, because of type erasure, the compiler converts the -\f[V]varargs\f[R] formal parameter to \f[V]Object[]\f[R] elements. -Consequently, there\[aq]s a possibility of heap pollution. -.RE diff --git a/src/jdk.compiler/share/man/javac.md b/src/jdk.compiler/share/man/javac.md new file mode 100644 index 00000000000..7761cde2b58 --- /dev/null +++ b/src/jdk.compiler/share/man/javac.md @@ -0,0 +1,1971 @@ +--- +# Copyright (c) 1994, 2024, 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. +# + +title: 'JAVAC(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +javac - read Java declarations and compile them into class files + +## Synopsis + +`javac` \[*options*\] \[*sourcefiles-or-classnames*\] + +*options* +: Command-line options. + +*sourcefiles-or-classnames* +: Source files to be compiled (for example, `Shape.java`) or + the names of previously compiled classes to be processed for annotations + (for example, `geometry.MyShape`). + +## Description + +The `javac` command reads _source files_ that contain module, package and type +declarations written in the Java programming language, and compiles them into _class files_ +that run on the Java Virtual Machine. + +The `javac` command can also [process annotations](#annotation-processing) +in Java source files and classes. + +Source files must have a file name extension of `.java`. +Class files have a file name extension of `.class`. +Both source and class files normally have file names that identify the contents. +For example, a class called `Shape` would be declared in a source file +called `Shape.java`, and compiled into a class file called `Shape.class`. + +There are two ways to specify source files to `javac`: + +- For a small number of source files, you can list their file names on + the command line. + +- For a large number of source files, you can use the [`@`*filename*](#option-at) + option on the command line to specify an _argument file_ that lists + their file names. See [Standard Options] for a description of the + option and [Command-Line Argument Files] for a description of + `javac` argument files. + +The order of source files specified on the command line or in an +argument file is not important. `javac` will compile the files together, +as a group, and will automatically resolve any dependencies between +the declarations in the various source files. + +`javac` expects that source files are arranged in one or more directory +hierarchies on the file system, described in [Arrangement of Source +Code]. + +To compile a source file, `javac` needs to find the declaration of +every class or interface that is used, extended, or implemented by the +code in the source file. This lets `javac` check that the code has the +right to access those classes and interfaces. Rather than specifying +the source files of those classes and interfaces explicitly, you can +use command-line options to tell `javac` where to search for their +source files. If you have compiled those source files previously, you +can use options to tell `javac` where to search for the corresponding +class files. The options, which all have names ending in "path", are +described in [Standard Options], and further described in +[Configuring a Compilation] and [Searching for Module, Package and Type Declarations]. + +By default, `javac` compiles each source file to a class file in the +same directory as the source file. However, it is recommended to +specify a separate destination directory with the [`-d`](#option-d) option. + +Command-line [options] and [environment variables] also control how +`javac` performs various tasks: + +- Compiling code to run on earlier releases of the JDK. +- Compiling code to run under a debugger. +- Checking for stylistic issues in Java source code. +- Checking for problems in `javadoc` comments (`/** ... */`). +- Processing annotations in source files and class files. +- Upgrading and patching modules in the compile-time environment. + +`javac` supports [Compiling for Earlier Releases Of The Platform] +and can also be invoked from Java code using one of a number of [APIs] + +## Options + +`javac` provides [standard options], and [extra options] that are either +non-standard or are for advanced use. + +Some options take one or more arguments. +If an argument contains spaces or other whitespace characters, +the value should be quoted according to the conventions of the +environment being used to invoke javac. +If the option begins with a single dash (`-`) the argument should +either directly follow the option name, or should be separated with a +colon (`:`) or whitespace, depending on the option. If the option begins with +a double dash (`--`), the argument may be separated either by whitespace +or by an equals (`=`) character with no additional whitespace. +For example, + + -Aname="J. Duke" + -proc:only + -d myDirectory + --module-version 3 + --module-version=3 + +In the following lists of options, an argument of *path* represents +a search path, composed of a list of file system locations separated +by the platform path separator character, (semicolon `;` on Windows, +or colon `:` on other systems.) Depending on the option, the +file system locations may be directories, JAR files or JMOD files. + +### Standard Options + +`@`*filename* +: Reads options and file names from a file. To shorten or simplify the + `javac` command, you can specify one or more files that contain arguments + to the `javac` command (except [`-J`](#option-J) options). This lets you to create + `javac` commands of any length on any operating system. + See [Command-Line Argument Files]. + +`-A`*key*\[`=`*value*\] +: Specifies options to pass to annotation processors. These options are not + interpreted by `javac` directly, but are made available for use by + individual processors. The *key* value should be one or more identifiers + separated by a dot (`.`). + +`--add-modules` *module*`,`*module* +: Specifies root modules to resolve in addition to the initial modules, or + all modules on the module path if *module* is `ALL-MODULE-PATH`. + +`--boot-class-path` *path* or `-bootclasspath` *path* +: Overrides the location of the bootstrap class files. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), or + [`-target`](#option-target) for details. For JDK 9 or later, see [`--system`](#option-system). + +`--class-path` *path*, `-classpath` *path*, or `-cp` *path* +: Specifies where to find user class files and annotation processors. This + class path overrides the user class path in the `CLASSPATH` environment + variable. + + - If `--class-path`, `-classpath`, or `-cp` are not specified, then the + user class path is the value of the `CLASSPATH` environment variable, + if that is set, or else the current directory. + + - If not compiling code for modules, if the [`--source-path`](#option-source-path) or -sourcepath` + option is not specified, then the user class path is also searched for source files. + + - If the [`-processorpath`](#option-processor-path) option is not specified, then the class path is + also searched for annotation processors. + +`-d` *directory* +: Sets the destination directory (or _class output directory_) for class files. + If a class is part of a package, then `javac` puts the class file in a + subdirectory that reflects the module name (if appropriate) and package name. + The directory, and any necessary subdirectories, will be created if they + do not already exist. + + If the `-d` option is not specified, then `javac` puts each class file in + the same directory as the source file from which it was generated. + + Except when compiling code for multiple modules, the contents of the + class output directory will be organized in a package hierarchy. + When compiling code for multiple modules, the contents of the output + directory will be organized in a module hierarchy, with the contents of each + module in a separate subdirectory, each organized as a package + hierarchy. + + **Note:** + When compiling code for one or more modules, the class output directory will + automatically be checked when searching for previously compiled classes. + When not compiling for modules, for backwards compatibility, + the directory is _not_ automatically checked for previously compiled classes, + and so it is recommended to specify the class output directory as one + of the locations on the user class path, using the `--class-path` option or one of + its alternate forms. + +`-deprecation` +: Shows a description of each use or override of a deprecated member or + class. Without the `-deprecation` option, `javac` shows a summary of the + source files that use or override deprecated members or classes. The + `-deprecation` option is shorthand for `-Xlint:deprecation`. + +`--enable-preview` +: Enables preview language features. Used in conjunction with either + [`-source`](#option-source) or [`--release`](#option-release). + +`-encoding` *encoding* +: Specifies character encoding used by source files, such as EUC-JP and + UTF-8. If the `-encoding` option is not specified, then the platform default + converter is used. + +`-endorseddirs` *directories* +: Overrides the location of the endorsed standards path. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), or + [`-target`](#option-target) for details. + +`-extdirs` *directories* +: Overrides the location of the installed extensions. + `directories` is a list of directories, separated by the platform path separator + (`;` on Windows, and `:` otherwise). + Each JAR file in the specified directories is searched for class files. + All JAR files found become part of the class path. + + If you are compiling for a release of the platform that supports the + Extension Mechanism, then this option specifies the directories that + contain the extension classes. + See [Compiling for Other Releases of the Platform]. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), or + [`-target`](#option-target) for details. + +`-g` +: Generates all debugging information, including local variables. By default, + only line number and source file information is generated. + +`-g:`\[`lines`, `vars`, `source`\] +: Generates only the kinds of debugging information specified by the + comma-separated list of keywords. Valid keywords are: + + `lines` + : Line number debugging information. + + `vars` + : Local variable debugging information. + + `source` + : Source file debugging information. + +`-g:none` +: Does not generate debugging information. + +`-h` *directory* +: Specifies where to place generated native header files. + + When you specify this option, a native header file is generated for each + class that contains native methods or that has one or more constants + annotated with the [`java.lang.annotation.Native`]( + ../../api/java.base/java/lang/annotation/Native.html) + annotation. If the class is part of a package, then the compiler puts the + native header file in a subdirectory that reflects the module name + (if appropriate) and package name. + The directory, and any necessary subdirectories, will be created if they + do not already exist. + +`--help`, `-help` or `-?` +: Prints a synopsis of the standard options. + +`--help-extra` or `-X` +: Prints a synopsis of the set of extra options. + +`--help-lint` +: Prints the supported keys for the `-Xlint` option. + +`-implicit:`\[`none`, `class`\] +: Specifies whether or not to generate class files for implicitly referenced + files: + + - `-implicit:class` --- Automatically generates class files. + + - `-implicit:none` --- Suppresses class file generation. + + If this option is not specified, then the default automatically generates + class files. In this case, the compiler issues a warning if any class files + are generated when also doing annotation processing. The warning is not + issued when the `-implicit` option is explicitly set. + See [Searching for Module, Package and Type Declarations]. + +`-J`*option* +: Passes *option* to the runtime system, where *option* is one of the Java + options described on [java](java.html) command. For example, `-J-Xms48m` + sets the startup memory to 48 MB. + + **Note:** The `CLASSPATH` environment variable, `-classpath` option, `-bootclasspath` + option, and `-extdirs` option do not specify the classes used to run + `javac`. Trying to customize the compiler implementation with these options + and variables is risky and often does not accomplish what you want. If you + must customize the compiler implementation, then use the `-J` option to + pass options through to the underlying Java launcher. + +`--limit-modules` *module*`,`*module*\* +: Limits the universe of observable modules. + +`--module` *module-name* (`,`*module-name*)* or `-m` *module-name* (`,`*module-name*)* +: Compiles those source files in the named modules that are newer + than the corresponding files in the output directory. + +`--module-path` *path* or `-p` *path* +: Specifies where to find application modules. + +`--module-source-path` *module-source-path* +: Specifies where to find source files when compiling code + in multiple modules. See [The Module Source Path Option]. + +`--module-version` *version* +: Specifies the version of modules that are being compiled. + +`-nowarn` +: Disables warning messages. This option operates the same as the + `-Xlint:none` option. + +`-parameters` +: Generates metadata for reflection on method parameters. Stores formal + parameter names of constructors and methods in the generated class file so + that the method `java.lang.reflect.Executable.getParameters` from the + Reflection API can retrieve them. + +`-proc:`\[`none`, `only`, `full`\] +: Controls whether annotation processing and compilation are done. + + - `-proc:none` means that compilation takes place without annotation + processing + + - `-proc:only` means that only annotation processing is done, + without any subsequent compilation. + + - `-proc:full` means annotation processing and compilation are done. + + If this option is not used, annotation processing and compilation + are done if at least one other option is used to explicitly + configure annotation processing. + +`-processor` *class1*\[`,`*class2*`,`*class3*...\] +: Names of the annotation processors to run. This bypasses the default + discovery process. + +`--processor-module-path` *path* +: Specifies the module path used for finding annotation processors. + +`--processor-path` *path* or `-processorpath` *path* +: Specifies where to find annotation processors. If this option is not used, + then the class path is searched for processors. + +`-profile` *profile* +: Checks that the API used is available in the specified profile. + This option is deprecated and may be removed in a future release. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), + or [`-target`](#option-target) for details. + +`--release` *release* +: Compiles source code according to the rules of the Java programming language + for the specified Java SE release, generating class files which target + that release. + Source code is compiled against the combined Java SE and JDK API for the + specified release. + + The supported values of *release* are the current Java SE release and a + limited number of previous releases, detailed in the command-line help. + + For the current release, the Java SE API consists of the `java.*`, + `javax.*`, and `org.*` packages that are exported by the Java SE modules in + the release; the JDK API consists of the `com.*` and `jdk.*` packages that + are exported by the JDK modules in the release, plus the `javax.*` packages + that are exported by standard, but non-Java SE, modules in the release. + + For previous releases, the Java SE API and the JDK API are as defined in + that release. + + **Note:** When using `--release`, you cannot also use the [`--source`](#option-source)/`-source` or + [`--target`](#option-target)/`-target` options. + + **Note:** When using `--release` to specify a release that supports the Java + Platform Module System, the `--add-exports` option cannot be used to + enlarge the set of packages exported by the Java SE, JDK, and standard + modules in the specified release. + +`-s` *directory* +: Specifies the directory used to place the generated source files. If a + class is part of a package, then the compiler puts the source file in a + subdirectory that reflects the module name (if appropriate) and package name. + The directory, and any necessary subdirectories, will be created if they + do not already exist. + + Except when compiling code for multiple modules, the contents of the + source output directory will be organized in a package hierarchy. + When compiling code for multiple modules, the contents of the source output directory will be + organized in a module hierarchy, with the contents of each + module in a separate subdirectory, each organized as a package + hierarchy. + +`--source` *release* or `-source` *release* +: Compiles source code according to the rules of the Java programming language + for the specified Java SE release. + The supported values of *release* are the current Java SE release and a + limited number of previous releases, detailed in the command-line help. + + If the option is not specified, the default is to compile source code + according to the rules of the Java programming language for the current + Java SE release. + +`--source-path` *path* or `-sourcepath` *path* +: Specifies where to find source files. + Except when compiling multiple modules together, this is the source code path + used to search for class or interface definitions. + + **Note:** Classes found through the class path might be recompiled when their source + files are also found. See [Searching for Module, Package and Type Declarations]. + +`--system` *jdk* \| `none` +: Overrides the location of system modules. + +`--target` *release* or `-target` *release* +: Generates `class` files suitable for the specified Java SE release. + The supported values of *release* are the current Java SE release and a + limited number of previous releases, detailed in the command-line help. + + **Note:** The target release must be equal to or higher than the source release. + (See [`--source`](#option-source).) + +`--upgrade-module-path` *path* +: Overrides the location of upgradeable modules. + +`-verbose` +: Outputs messages about what the compiler is doing. Messages include + information about each class loaded and each source file compiled. + +`--version` or `-version` +: Prints version information. + +`-Werror` +: Terminates compilation when warnings occur. + +### Extra Options + +`--add-exports` *module*`/`*package*`=`*other-module*(`,`*other-module*)\* +: Specifies a package to be considered as exported from its defining module + to additional modules or to all unnamed modules when the value of + *other-module* is `ALL-UNNAMED`. + +`--add-reads` *module*`=`*other-module*(`,`*other-module*)\* +: Specifies additional modules to be considered as required by a given + module. + +`--default-module-for-created-files` *module-name* +: Specifies the fallback target module for files created by annotation + processors, if none is specified or inferred. + +`--disable-line-doc-comments` +: Disables support for documentation comments with lines beginning ///. + +`-Djava.endorsed.dirs=`*dirs* +: Overrides the location of the endorsed standards path. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), + or [`-target`](#option-target) for details. + +`-Djava.ext.dirs=`*dirs* +: Overrides the location of installed extensions. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), + or [`-target`](#option-target) for details. + +`--patch-module` *module*`=`*path* +: Overrides or augments a module with classes and resources in JAR files or + directories. + +`-Xbootclasspath:`*path* +: Overrides the location of the bootstrap class files. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), + or [`-target`](#option-target) for details. + +`-Xbootclasspath/a:`*path* +: Adds a suffix to the bootstrap class path. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), + or [`-target`](#option-target) for details. + +`-Xbootclasspath/p:`*path* +: Adds a prefix to the bootstrap class path. + + **Note:** This can only be used when compiling for releases prior to JDK 9. + As applicable, see the descriptions in [`--release`](#option-release), [`-source`](#option-source), + or [`-target`](#option-target) for details. + +`-Xdiags:`\[`compact`, `verbose`\] +: Selects a diagnostic mode. + +`-Xdoclint` +: Enables recommended checks for problems in documentation comments. + +`-Xdoclint:`(`all`|`none`|\[`-`\]*group*)\[`/`*access*\] +: Enables or disables specific groups of checks in documentation comments. + + *group* can have one of the following values: + `accessibility`, `html`, `missing`, `reference`, `syntax`. + + The variable *access* specifies the minimum visibility level of classes and + members that the `-Xdoclint` option checks. It can have one of the + following values (in order of most to least visible): + `public`, `protected`, `package`, `private`. + + The default *access* level is `private`. + + When prefixed by `doclint:`, the *group* names and `all` can be used with `@SuppressWarnings` + to suppress warnings about documentation comments in parts of the code being compiled. + + For more information about these groups of checks, see the [DocLint](javadoc.html#doclint) + section of the `javadoc` command documentation. + The `-Xdoclint` option is disabled by default in the `javac` command. + + For example, the following option checks classes and members (with all + groups of checks) that have the access level of protected and higher (which + includes protected and public): + + > `-Xdoclint:all/protected` + + The following option enables all groups of checks for all access levels, + except it will not check for HTML errors for classes and members that have the + access level of package and higher (which includes package, protected and + public): + + > `-Xdoclint:all,-html/package` + +`-Xdoclint/package:`\[`-`\]*packages*(`,`\[`-`\]*package*)\* +: Enables or disables checks in specific packages. Each *package* is either + the qualified name of a package or a package name prefix followed by `.*`, + which expands to all sub-packages of the given package. Each *package* can + be prefixed with a hyphen (`-`) to disable checks for a specified package + or packages. + + For more information, see the [DocLint](javadoc.html#doclint) + section of the `javadoc` command documentation. + +`-Xlint` +: Enables all recommended warnings. In this release, enabling all available + warnings is recommended. + +`-Xlint:`\[`-`\]*key*(`,`\[`-`\]*key*)\* +: Supplies warnings to enable or disable, separated by comma. Precede a key + by a hyphen (`-`) to disable the specified warning. + + Supported values for *key* are: + + - `all`: Enables all warnings. + + - `auxiliaryclass`: Warns about an auxiliary class that is hidden in a + source file, and is used from other files. + + - `cast`: Warns about the use of unnecessary casts. + + - `classfile`: Warns about the issues related to classfile contents. + + - `dangling-doc-comments`: Warns about extra or misplaced documentation + comments near the beginning of a declaration. + + - `deprecation`: Warns about the use of deprecated items. + + - `dep-ann`: Warns about the items marked as deprecated in `javadoc` but + without the `@Deprecated` annotation. + + - `divzero`: Warns about the division by the constant integer 0. + + - `empty`: Warns about an empty statement after `if`. + + - `exports`: Warns about the issues regarding module exports. + + - `fallthrough`: Warns about the falling through from one case of a + switch statement to the next. + + - `finally`: Warns about `finally` clauses that do not terminate normally. + + - `incubating`: Warns about the use of incubating modules. + + - `lossy-conversions`: Warns about possible lossy conversions + in compound assignment. + + - `missing-explicit-ctor`: Warns about missing explicit constructors in + public and protected classes in exported packages. + + - `module`: Warns about the module system-related issues. + + - `opens`: Warns about the issues related to module opens. + + - `options`: Warns about the issues relating to use of command line + options. + + - `output-file-clash`: Warns if any output file is overwritten during compilation. + This can occur, for example, on case-insensitive filesystems. + + - `overloads`: Warns about the issues related to method overloads. + + - `overrides`: Warns about the issues related to method overrides. + + - `path`: Warns about the invalid path elements on the command line. + + - `preview`: Warns about the use of preview language features. + + - `processing`: Warns about the issues related to annotation processing. + + - `rawtypes`: Warns about the use of raw types. + + - `removal`: Warns about the use of an API that has been marked for + removal. + + - `restricted`: Warns about the use of restricted methods. + + - `requires-automatic`: Warns developers about the use of automatic + modules in requires clauses. + + - `requires-transitive-automatic`: Warns about automatic modules in + requires transitive. + + - `serial`: Warns about the serializable classes that do not provide a + serial version ID. Also warns about access to non-public members from a + serializable element. + + - `static`: Warns about the accessing a static member using an instance. + + - `strictfp`: Warns about unnecessary use of the `strictfp` modifier. + + - `synchronization`: Warns about synchronization attempts on instances + of value-based classes. + + - `text-blocks`: Warns about inconsistent white space characters in text + block indentation. + + - `this-escape`: Warns about constructors leaking `this` prior to subclass initialization. + + - `try`: Warns about the issues relating to the use of try blocks (that + is, try-with-resources). + + - `unchecked`: Warns about the unchecked operations. + + - `varargs`: Warns about the potentially unsafe `vararg` methods. + + - `none`: Disables all warnings. + + With the exception of `all` and `none`, the keys can be used with + the `@SuppressWarnings` annotation to suppress warnings in a part + of the source code being compiled. + + See [Examples of Using -Xlint keys]. + +`-Xmaxerrs` *number* +: Sets the maximum number of errors to print. + +`-Xmaxwarns` *number* +: Sets the maximum number of warnings to print. + +`-Xpkginfo:`\[`always`, `legacy`, `nonempty`\] +: Specifies when and how the `javac` command generates `package-info.class` + files from `package-info.java` files using one of the following options: + + `always` + : Generates a `package-info.class` file for every `package-info.java` + file. This option may be useful if you use a build system such as Ant, + which checks that each `.java` file has a corresponding `.class` file. + + `legacy` + : Generates a `package-info.class` file only if `package-info.java` + contains annotations. This option does not generate a + `package-info.class` file if `package-info.java` contains only + comments. + + **Note:** A `package-info.class` file might be generated but be empty if all the + annotations in the `package-info.java` file have + `RetentionPolicy.SOURCE`. + + `nonempty` + : Generates a `package-info.class` file only if `package-info.java` + contains annotations with `RetentionPolicy.CLASS` or + `RetentionPolicy.RUNTIME`. + +`-Xplugin:`*name* *args* +: Specifies the name and optional arguments for a plug-in to be run. + If *args* are provided, *name* and *args* should be quoted or otherwise + escape the whitespace characters between the name and all the arguments. + For details on the API for a plugin, see the API documentation for + [jdk.compiler/com.sun.source.util.Plugin](../../api/jdk.compiler/com/sun/source/util/Plugin.html). + +`-Xprefer:`\[`source`, `newer`\] +: Specifies which file to read when both a source file and class file are + found for an implicitly compiled class using one of the following options. + See [Searching for Module, Package and Type Declarations]. + + - `-Xprefer:newer`: Reads the newer of the source or class files for a + type (default). + + - `-Xprefer:source` : Reads the source file. Use `-Xprefer:source` when + you want to be sure that any annotation processors can access + annotations declared with a retention policy of `SOURCE`. + +`-Xprint` +: Prints a textual representation of specified types for debugging purposes. + This does not perform annotation processing or compilation. The format of + the output could change. + +`-XprintProcessorInfo` +: Prints information about which annotations a processor is asked to process. + +`-XprintRounds` +: Prints information about initial and subsequent annotation processing + rounds. + +`-Xstdout` *filename* +: Sends compiler messages to the named file. By default, compiler messages go + to `System.err`. + +## Environment Variables + +### CLASSPATH + +If the [`--class-path`](#option-class-path) option or any of its alternate forms are not specified, +the class path will default to the value of the `CLASSPATH` environment +variable if it is set. +However, it is recommended that this environment variable should _not_ be set, +and that the `--class-path` option should be used to provide an explicit +value for the class path when one is required. + +### JDK\_JAVAC\_OPTIONS + +The content of the `JDK_JAVAC_OPTIONS` environment variable, separated by +white-spaces ( ) or white-space characters (`\n`, `\t`, `\r`, or `\f`) is +prepended to the command line arguments passed to `javac` as a list of +arguments. + +The encoding requirement for the environment variable is the same as the +`javac` command line on the system. `JDK_JAVAC_OPTIONS` environment variable +content is treated in the same manner as that specified in the command line. + +Single quotes (`'`) or double quotes (`"`) can be used to enclose arguments +that contain whitespace characters. All content between the open quote and the +first matching close quote are preserved by simply removing the pair of quotes. +In case a matching quote is not found, the launcher will abort with an error +message. `@`*files* are supported as they are specified in the command line. +However, as in `@`*files*, use of a wildcard is not supported. + +**Examples of quoting arguments containing white spaces:** + +> `export JDK_JAVAC_OPTIONS='@"C:\white spaces\argfile"'` + +> `export JDK_JAVAC_OPTIONS='"@C:\white spaces\argfile"'` + +> `export JDK_JAVAC_OPTIONS='@C:\"white spaces"\argfile'` + +## Command-Line Argument Files + +An argument file can include command-line options and source file names in any +combination. The arguments within a file can be separated by spaces or new line +characters. If a file name contains embedded spaces, then put the whole file +name in double quotation marks. + +File names within an argument file are relative to the current directory, not +to the location of the argument file. Wildcards (`*`) are not allowed in these +lists (such as for specifying `*.java`). Use of the at sign (`@`) to +recursively interpret files is not supported. The `-J` options are not supported +because they're passed to the launcher, which does not support argument files. + +When executing the `javac` command, pass in the path and name of each argument +file with the at sign (`@`) leading character. When the `javac` command +encounters an argument beginning with the at sign (`@`), it expands the +contents of that file into the argument list. + + +### Examples of Using javac @filename + +Single Argument File +: You could use a single argument file named `argfile` to hold all `javac` + arguments: + + > `javac @argfile` + + This argument file could contain the contents of both files shown in the + following **Two Argument Files** example. + +Two Argument Files +: You can create two argument files: one for the `javac` options and the + other for the source file names. Note that the following lists have no + line-continuation characters. + + Create a file named `options` that contains the following: + + **Linux and macOS:** + + ``` + -d classes + -g + -sourcepath /java/pubs/ws/1.3/src/share/classes + ``` + + **Windows:** + + ``` + -d classes + -g + -sourcepath C:\java\pubs\ws\1.3\src\share\classes + ``` + + Create a file named `sources` that contains the following: + + ``` + MyClass1.java + MyClass2.java + MyClass3.java + ``` + + Then, run the `javac` command as follows: + + > `javac @options @sources` + +Argument Files with Paths +: The argument files can have paths, but any file names inside the files are + relative to the current working directory (not `path1` or `path2`): + + > `javac @path1/options @path2/sources` + +## Arrangement of Source Code + +In the Java language, classes and interfaces can be organized into +packages, and packages can be organized into modules. `javac` expects +that the physical arrangement of source files in directories of the +file system will mirror the organization of classes into packages, and +packages into modules. + +It is a widely adopted convention that module names and package names +begin with a lower-case letter, and that class names begin with an +upper-case letter. + +### Arrangement of Source Code for a Package + +When classes and interfaces are organized into a package, the package +is represented as a directory, and any subpackages are represented as +subdirectories. + +For example: + +- The package `p` is represented as a directory called `p`. + +- The package `p.q` -- that is, the subpackage `q` of package `p` -- + is represented as the subdirectory `q` of directory `p`. The + directory tree representing package `p.q` is therefore `p\q` + on Windows, and `p/q` on other systems. + +- The package `p.q.r` is represented as the directory tree `p\q\r` + (on Windows) or `p/q/r` (on other systems). + +Within a directory or subdirectory, `.java` files represent classes +and interfaces in the corresponding package or subpackage. + +For example: + +- The class `X` declared in package `p` is represented by the file + `X.java` in the `p` directory. + +- The class `Y` declared in package `p.q` is represented by the file + `Y.java` in the `q` subdirectory of directory `p`. + +- The class `Z` declared in package `p.q.r` is represented by the file + `Z.java` in the `r` subdirectory of `p\q` (on Windows) or `p/q` + (on other systems). + +In some situations, it is convenient to split the code into +separate directories, each structured as described above, and +the aggregate list of directories specified to `javac`. + +### Arrangement of Source Code for a Module + +In the Java language, a module is a set of packages designed for +reuse. In addition to `.java` files for classes and interfaces, each +module has a source file called `module-info.java` which: + +1. declares the module's name; + +2. lists the packages exported by the module (to allow reuse by other + modules); + +3. lists other modules required by the module (to reuse their exported + packages). + +When packages are organized into a module, the module is represented +by one or more directories representing the packages in the module, +one of which contains the `module-info.java` file. It may be convenient, +but it is not required, to use a single directory, named after the module, +to contain the `module-info.java` file alongside the directory tree which +represents the packages in the module (i.e., the _package hierarchy_ +described above). The exact arrangement of source code for a module +is typically dictated by the conventions adopted by a development +environment (IDE) or build system. + +For example: + +- The module `a.b.c` may be represented by the directory `a.b.c`, on all + systems. + +- The module's declaration is represented by the file + `module-info.java` in the `a.b.c` directory. + +- If the module contains package `p.q.r`, then the `a.b.c` directory + contains the directory tree `p\q\r` (on Windows) or `p/q/r` + (on other systems). + +The development environment may prescribe some directory hierarchy +between the directory named for the module and the source files to +be read by `javac`. + +For example: + +- The module `a.b.c` may be represented by the directory `a.b.c` + +- The module's declaration and the module's packages may be in + some subdirectory of `a.b.c`, such as `src\main\java` (on Windows) + or `src/main/java` (on other systems). + + +## Configuring a Compilation + +This section describes how to configure `javac` to perform a basic compilation. + +See [Configuring the Module System] for additional details for use when compiling +for a release of the platform that supports modules. + +### Source Files + +* Specify the source files to be compiled on the command line. + +If there are no compilation errors, the corresponding class files will +be placed in the [output directory]. + +Some systems may limit the amount you can put on a command line; +to work around those limits, you can use [argument files](#command-line-argument-files). + +When compiling code for modules, you can also specify source files indirectly, +by using the [`--module`](#option-module) or `-m` option. + +### Output Directory + +* Use the [`-d`](#option-d) option to specify an output directory in which to put the compiled class files. + +This will normally be organized in a [package hierarchy](#package-hierarchy), +unless you are compiling source code from multiple modules, in which case it will be +organized as a [module hierarchy](#module-hierarchy). + +When the compilation has been completed, if you are compiling one or more modules, +you can place the output directory on the module path for the Java [launcher](java.html); +otherwise, you can place the place the output directory on the class path +for the Java launcher. + +### Precompiled Code + +The code to be compiled may refer to libraries beyond what is provided by the platform. +If so, you must place these libraries on the class path or module path. +If the library code is not in a module, place it on the class path; +if it is in a module, place it on the module path. + +* Use the [`--class-path`](#option-class-path) option to specify libraries to be placed on the class path. + Locations on the class path should be organized in a [package hierarchy](#package-hierarchy). + You can also use alternate forms of the option: `-classpath` or `-cp`. + +* Use the [`--module-path`](#option-module-path) option to specify libraries to be placed on the module path. + Locations on the module path should either be modules or directories of modules. + You can also use an alternate form of the option: `-p`. + + See [Configuring the Module System] for details on how to modify the default + configuration of library modules. + +**Note**: the options for the class path and module path are not mutually +exclusive, although it is not common to specify the class path when compiling +code for one or more modules. + +### Additional Source Files + +The code to be compiled may refer to types in additional source files that are not +specified on the command line. +If so, you must put those source files on either the source path or module path. +You can only specify one of these options: if you are not compiling code for a module, +or if you are only compiling code for a single module, use the source path; +if you are compiling code for multiple modules, use the module source path. + +* Use the [`--source-path`](#option-source-path) option to specify the locations of additional source + files that may be read by javac. + Locations on the source path should be organized in a [package hierarchy](#package-hierarchy). + You can also use an alternate form of the option: `-sourcepath`. + +* Use the [`--module-source-path`](#option-module-source-path) option one or more times to specify the location + of additional source files in different modules that may be read by javac, + or when compiling source files in multiple modules. + You can either specify the locations for each module [individually](#module-specific-form), + or you can organize the source files so that you can specify the locations all + [together](#module-pattern-form). For more details, see [The Module Source Path Option]. + +If you want to be able to refer to types in additional source files but do not +want them to be compiled, use the [`-implicit`](#option-implicit) option. + +**Note**: if you are compiling code for multiple modules, you must always specify +a module source path, and all source files specified on the command line must be +in one of the directories on the module source path, or in a subdirectory thereof. + + +### Example of Compiling Multiple Source Files + +This example compiles the `Aloha.java`, `GutenTag.java`, `Hello.java`, and +`Hi.java` source files in the `greetings` package. + +**Linux and macOS:** + +``` +% javac greetings/*.java +% ls greetings +Aloha.class GutenTag.class Hello.class Hi.class +Aloha.java GutenTag.java Hello.java Hi.java +``` + +**Windows:** + +``` +C:\>javac greetings\*.java +C:\>dir greetings +Aloha.class GutenTag.class Hello.class Hi.class +Aloha.java GutenTag.java Hello.java Hi.java +``` + +### Example of Specifying a User Class Path + +After changing one of the source files in the previous example, recompile it: + +**Linux and macOS:** + +``` +pwd +/examples +javac greetings/Hi.java +``` + +**Windows:** + +``` +C:\>cd +\examples +C:\>javac greetings\Hi.java +``` + +Because `greetings.Hi` refers to other classes in the `greetings` package, the +compiler needs to find these other classes. The previous example works because +the default user class path is the directory that contains the package +directory. If you want to recompile this file without concern for which +directory you are in, then add the examples directory to the user class path by +setting `CLASSPATH`. This example uses the `-classpath` option. + +**Linux and macOS:** + +> `javac -classpath /examples /examples/greetings/Hi.java` + +**Windows:** + +> `C:\>javac -classpath \examples \examples\greetings\Hi.java` + +If you change `greetings.Hi` to use a banner utility, then that utility also +needs to be accessible through the user class path. + +**Linux and macOS:** + +``` +javac -classpath /examples:/lib/Banners.jar \ + /examples/greetings/Hi.java +``` + +**Windows:** + +``` +C:\>javac -classpath \examples;\lib\Banners.jar ^ + \examples\greetings\Hi.java +``` + +To execute a class in the `greetings` package, the program needs access to the +`greetings` package, and to the classes that the `greetings` classes use. + +**Linux and macOS:** + +> `java -classpath /examples:/lib/Banners.jar greetings.Hi` + +**Windows:** + +> `C:\>java -classpath \examples;\lib\Banners.jar greetings.Hi` + +## Configuring the Module System + +If you want to include additional modules in your compilation, use the +[`--add-modules`](#option-add-modules) option. +This may be necessary when you are compiling code that is not in a module, +or which is in an automatic module, and the code refers to API in the additional +modules. + +If you want to restrict the set of modules in your compilation, use the +[`--limit-modules`](#option-limit-modules) option. +This may be useful if you want to ensure that the code you are compiling +is capable of running on a system with a limited set of modules installed. + +If you want to break encapsulation and specify that additional packages +should be considered as exported from a module, use the [`--add-exports`](#option-add-exports) option. +This may be useful when performing white-box testing; relying on access +to internal API in production code is strongly discouraged. + +If you want to specify that additional packages +should be considered as required by a module, use the [`--add-reads`](#option-add-reads) option. +This may be useful when performing white-box testing; relying on access +to internal API in production code is strongly discouraged. + +You can patch additional content into any module using the +[`--patch-module`](#option-patch-module) option. See [Patching a Module] for more details. + +## Searching for Module, Package and Type Declarations + +To compile a source file, the compiler often needs information about a module +or type, but the declaration is not in the source files specified on the command +line. + +`javac` needs type information for every class or interface used, +extended, or implemented in the source file. This includes classes and +interfaces not explicitly mentioned in the source file, but that provide +information through inheritance. + +For example, when you create a subclass of `java.awt.Window`, you are also +using the ancestor classes of `Window`: `java.awt.Container`, +`java.awt.Component`, and `java.lang.Object`. + +When compiling code for a module, the compiler also needs to have available +the declaration of that module. + +A successful search may produce a class file, a source file, or both. If +both are found, then you can use the [`-Xprefer`](#option-Xprefer) option to instruct the compiler +which to use. + +If a search finds and uses a source file, then by default `javac` +compiles that source file. This behavior can be altered with +[`-implicit`](#option-implicit). + +The compiler might not discover the need for some type information until after +annotation processing completes. When the type information is found in a source +file and no [`-implicit`](#option-implicit) option is specified, the compiler gives a warning that +the file is being compiled without being subject to annotation processing. To +disable the warning, either specify the file on the command line (so that it +will be subject to annotation processing) or use the [`-implicit`](#option-implicit) option to +specify whether or not class files should be generated for such source files. + +The way that `javac` locates the declarations of those types +depends on whether the reference exists within code for a module or not. + +### Searching Package Oriented Paths + +When searching for a source or class file on a path composed of package oriented +locations, `javac` will check each location on the path in turn for the +possible presence of the file. The first occurrence of a particular file +shadows (hides) any subsequent occurrences of like-named files. This shadowing +does not affect any search for any files with a different name. This can be +convenient when searching for source files, which may be grouped in different +locations, such as shared code, platform-specific code and generated code. +It can also be useful when injecting alternate versions of a class file into +a package, to debugging or other instrumentation reasons. But, it can also +be dangerous, such as when putting incompatible different versions of a library +on the class path. + +### Searching Module Oriented Paths + +Prior to scanning any module paths for any package or type declarations, +`javac` will lazily scan the following paths and locations to determine +the modules that will be used in the compilation. + +* The module source path (see the [`--module-source-path`](#option-module-source-path) option) +* The path for upgradeable modules (see the [`--upgrade-module-path`](#option-upgrade-module-path) option) +* The system modules (see the [`--system`](#option-system) option) +* The user module path ( see the [`--module-path`](#option-module-path) option) + +For any module, the first occurrence of the module during the scan completely +shadows (hides) any subsequent appearance of a like-named module. While locating +the modules, `javac` is able to determine the packages exported by the module +and to associate with each module a package oriented path for the contents of +the module. For any previously compiled module, this path will typically be a +single entry for either a directory or a file that provides an internal +directory-like hierarchy, such as a JAR file. Thus, when searching for a type +that is in a package that is known to be exported by a module, `javac` can +locate the declaration directly and efficiently. + +### Searching for the Declaration of a Module + +If the module has been previously compiled, the module declaration is +located in a file named `module-info.class` in the root of the package hierarchy +for the content of the module. + +If the module is one of those currently being compiled, the module declaration +will be either the file named `module-info.class` in the root of the +package hierarchy for the module in the class output directory, or the +file named `module-info.java` in one of the locations on the source path +or one the module source path for the module. + +### Searching for the Declaration of a Type When the Reference is not in a Module + +When searching for a type that is referenced in code that is not in a module, +`javac` will look in the following places: + +* The platform classes (or the types in exported packages of the platform modules) + (This is for compiled class files only.) + +* Types in exported packages of any modules on the module path, if applicable. + (This is for compiled class files only.) + +* Types in packages on the class path and/or source path: + + * If both are specified, `javac` looks for compiled class files on the class path + and for source files on the source path. + + * If the class path is specified, but not source path, `javac` looks for both + compiled class files and source files on the class path. + + * If the class path is not specified, it defaults to the current directory. + +When looking for a type on the class path and/or source path, if both a compiled +class file and a source file are found, the most recently modified file will +be used by default. +If the source file is newer, it will be compiled and will may override any +previously compiled version of the file. You can use the [`-Xprefer`](#option-Xprefer) option +to override the default behavior. + +### Searching for the Declaration of a Type When the Reference is in a Module + +When searching for a type that is referenced in code in a module, +`javac` will examine the declaration of the enclosing module to determine +if the type is in a package that is exported from another module that is +readable by the enclosing module. +If so, `javac` will simply and directly go to the definition of that module +to find the definition of the required type. +Unless the module is another of the modules being compiled, `javac` will +only look for compiled class files files. In other words, `javac` will +not look for source files in platform modules or modules on the module path. + +If the type being referenced is not in some other readable module, +`javac` will examine the module being compiled to try and find the +declaration of the type. +`javac` will look for the declaration of the type as follows: + +* Source files specified on the command line or on the source path or + module source path. + +* Previously compiled files in the output directory. + + +## Directory Hierarchies + +`javac` generally assumes that source files and compiled class files will be +organized in a file system directory hierarchy or in a type of file that +supports in an internal directory hierarchy, such as a JAR file. +Three different kinds of hierarchy are supported: a _package hierarchy_, +a _module hierarchy_, and a _module source hierarchy_. + +While `javac` is fairly relaxed about the organization of source code, +beyond the expectation that source will be organized in one or package +hierarchies, and can generally accommodate organizations prescribed by +development environments and build tools, Java tools in general, +and `javac` and the Java launcher in particular, are more stringent +regarding the organization of compiled class files, and will be +organized in package hierarchies or module hierarchies, as appropriate. + +The location of these hierarchies are specified to `javac` with command-line +options, whose names typically end in "path", like [`--source-path`](#option-source-path) or +[`--class-path`](#option-class-path). Also as a general rule, path options whose name includes the +word `module`, like [`--module-path`](#option-module-path), are used to specify module hierarchies, +although some module-related path options allow a package hierarchy to be +specified on a per-module basis. All other path options are used to specify +package hierarchies. + +### Package Hierarchy + +In a package hierarchy, directories and subdirectories are used +to represent the component parts of the package name, with the source +file or compiled class file for a type being stored as a file with an +extension of `.java` or `.class` in the most nested directory. + +For example, in a package hierarchy, the source file for a class +`com.example.MyClass` will be stored in the file _com/example/MyClass.java_ + +### Module Hierarchy + +In a module hierarchy, the first level of directories are named +for the modules in the hierarchy; within each of those directories +the contents of the module are organized in package hierarchies. + +For example, in a module hierarchy, the compiled class file for a type called +`com.example.MyClass` in a module called `my.library` will be stored in +_my.library/com/example/MyClass.class_. + +The various output directories used by `javac` (the class output directory, +the source output directory, and native header output directory) +will all be organized in a module hierarchy when multiple modules are being compiled. + +### Module Source Hierarchy + +Although the source for each individual module should always be +organized in a package hierarchy, it may be convenient to group +those hierarchies into a module source hierarchy. This is similar +to a module hierarchy, except that there may be intervening directories +between the directory for the module and the directory that is +the root of the package hierarchy for the source code of the module. + +For example, in a module source hierarchy, the source file for a type called +`com.example.MyClass` in a module called `my.library` may be stored in a +file such as +_my.library/src/main/java/com/example/MyClass.java_. + +## The Module Source Path Option + +The [`--module-source-path`](#option-module-source-path) option has two forms: a _module-specific form_, +in which a package path is given for each module containing code to be compiled, +and a _module-pattern_ form, in which the source path for each module is specified +by a pattern. +The module-specific form is generally simpler to use when only a small number of +modules are involved; the module-pattern form may be more convenient when the +number of modules is large and the modules are organized in a regular manner that +can be described by a pattern. + +Multiple instances of the `--module-source-path` option may be given, each one +using either the module-pattern form or the module-specific form, subject to the +following limitations: + +* the module-pattern form may be used at most once +* the module-specific form may be used at most once for any given module + +If the module-specific form is used for any module, the associated search path +overrides any path that might otherwise have been inferred from the module-pattern form. + +### Module-specific form + +The module-specific form allows an explicit search path to be given for any specific module. +This form is: + +* `--module-source-path` *module-name*`=`*file-path* (*path-separator* *file-path*)* + +The path separator character is `;` on Windows, and `:` otherwise. + +**Note:** this is similar to the form used for the [`--patch-module`](#option-patch-module) option. + +### Module-pattern form + +The module-pattern form allows a concise specification of the module source path +for any number of modules organized in regular manner. + +* `--module-source-path` *pattern* + +The pattern is defined by the following rules, which are applied in order: + +* The argument is considered to be a series of segments separated by the path + separator character (`;` on Windows, and `:` otherwise). + +* Each segment containing curly braces of the form + + string1{alt1 ( ,alt2 )* } string2 + + is considered to be replaced by a series of segments formed by "expanding" the braces: + + string1 alt1 string2 + string1 alt2 string2 + and so on... + + The braces may be nested. + + This rule is applied for all such usages of braces. + + * Each segment must have at most one asterisk (`*`). + If a segment does not contain an asterisk, it is considered to be as though the + file separator character and an asterisk are appended. + + For any module _M_, the source path for that module is formed from the series + of segments obtained by substituting the module name _M_ for the asterisk in + each segment. + + **Note**: in this context, the asterisk is just used as a special marker, to + denote the position in the path of the module name. It should not be confused + with the use of `*` as a file name wildcard character, as found on most + operating systems. + +## Patching Modules + +javac allows any content, whether in source or compiled form, to be patched +into any module using the [`--patch-module`](#option-patch-module) option. +You may want to do this to compile alternative implementations of a class +to be patched at runtime into a JVM, or to inject additional classes into +the module, such as when testing. + +The form of the option is: + +* `--patch-module` *module-name*`=`*file-path* (*path-separator* *file-path* )* + +The path separator character is `;` on Windows, and `:` otherwise. +The paths given for the module must specify the root of a +package hierarchy for the contents of the module + +The option may be given at most once for any given module. +Any content on the path will hide any like-named content later in the path +and in the patched module. + +When patching source code into more than one module, the [`--module-source-path`](#option-module-source-path) +must also be used, so that the output directory is organized in a module hierarchy, +and capable of holding the compiled class files for the modules being compiled. + +## Annotation Processing + +The `javac` command provides direct support for annotation processing. + +The API for annotation processors is defined in the +`javax.annotation.processing` and `javax.lang.model` packages and subpackages. + +### How Annotation Processing Works + +Annotation processing is requested by using an option to configure +annotation processing, such as [`-processor`](#option-processor), +[`--processor-path`](#option-processor-path), +[`--processor-module-path`](#option-processor-module-path) or by +explicitly enabling processing with the [`-proc:full`](#option-proc) +or [`-proc:only`](#option-proc) options. Annotation processing is +disabled using the [`-proc:none`](#option-proc) option. + +If annotation processing is requested, the compiler searches for any +annotation processors that are available. + +The search path can be specified with the +[`-processorpath`](#option-processor-path) option. If no path is +specified, then the user class path is used. Processors are located by +means of service provider-configuration files named +`META-INF/services/javax.annotation.processing.Processor` on the +search path. Such files should contain the names of any +annotationation processors to be used, listed one per +line. Alternatively, processors can be specified explicitly, using the +[`-processor`](#option-processor) option. + +After scanning the source files and classes on the command line to determine +what annotations are present, the compiler queries the processors to determine +what annotations they process. When a match is found, the processor is called. +A processor can claim the annotations it processes, in which case no further +attempt is made to find any processors for those annotations. After all of the +annotations are claimed, the compiler does not search for additional +processors. + +If any processors generate new source files, then another round of annotation +processing occurs: Any newly generated source files are scanned, and the +annotations processed as before. Any processors called on previous rounds are +also called on all subsequent rounds. This continues until no new source files +are generated. + +After a round occurs where no new source files are generated, the annotation +processors are called one last time, to give them a chance to complete any +remaining work. Finally, unless the [`-proc:only`](#option-proc) option is used, the compiler +compiles the original and all generated source files. + +If you use an annotation processor that generates additional source +files to be included in the compilation, you can specify a default +module to be used for the newly generated files, for use when a +module declaration is not also generated. In this case, use the +[`--default-module-for-created-files`](#option-default-module-for-created-files) option. + +### Compilation Environment and Runtime Environment. + +The declarations in source files and previously compiled class files are analyzed +by `javac` in a _compilation environment_ that is distinct from the +_runtime environment_ used to execute `javac` itself. Although there is a +deliberate similarity between many `javac` options and like-named options for the +Java [launcher](java.html), such as `--class-path`, `--module-path` and so +on, it is important to understand that in general the `javac` options just affect +the environment in which the source files are compiled, and do not affect +the operation of `javac` itself. + +The distinction between the compilation environment and runtime environment +is significant when it comes to using annotation processors. +Although annotations processors process elements (declarations) that exist +in the compilation environment, the annotation processor itself is executed +in the runtime environment. If an annotation processor has dependencies on +libraries that are not in modules, the libraries can be placed, along with the +annotation processor itself, on the processor path. +(See the [`--processor-path`](#option-processor-path) option.) +If the annotation processor and its dependencies are in modules, you should +use the processor module path instead. +(See the [`--processor-module-path`](#option-processor-module-path) option.) +When those are insufficient, it may be necessary to provide further +configuration of the runtime environment. This can be done in two ways: + +1. If `javac` is invoked from the command line, options can be passed to the + underlying runtime by prefixing the option with [`-J`](#option-J). + +2. You can start an instance of a Java Virtual Machine directly and use + command line options and API to configure an environment in which + `javac` can be invoked via one of its [APIs]. + +## Compiling for Earlier Releases of the Platform + +`javac` can compile code that is to be used on other releases of the platform, +using either the [`--release`](#option-release) option, or the [`--source`](#option-source)/`-source` and +[`--target`](#option-target)/`-target` options, together with additional options to specify the +platform classes. + +Depending on the desired platform release, there are some restrictions on some +of the options that can be used. + +* When compiling for JDK 8 and earlier releases, you cannot use any option + that is intended for use with the module system. + This includes all of the following options: + + * [`--module-source-path`](#option-module-source-path), + [`--upgrade-module-path`](#option-upgrade-module-path), + [`--system`](#option-system), + [`--module-path`](#option-module-path), + [`--add-modules`](#option-add-modules), + [`--add-exports`](#option-add-exports), + `--add-opens`, + [`--add-reads`](#option-add-reads), + [`--limit-modules`](#option-limit-modules), + [`--patch-module`](#option-patch-module) + + If you use the `--source`/`-source` or `--target`/`-target` options, + you should also set the appropriate platform classes using the + boot class path family of options. + +* When compiling for JDK 9 and later releases, you cannot use any option + that is intended to configure the boot class path. + This includes all of the following options: + + * [`-Xbootclasspath/p:`](#option-Xbootclasspath-p), + [`-Xbootclasspath`](#option-Xbootclasspath), + [`-Xbootclasspath/a:`](#option-Xbootclasspath-a), + [`-endorseddirs`](#option-endorseddirs), + [`-Djava.endorsed.dirs`](#option-Djava.endorsed.dirs), + [`-extdirs`](#option-extdirs), + [`-Djava.ext.dirs`](#option-Djava.ext.dirs), + [`-profile`](#option-profile) + + If you use the `--source`/`-source` or `--target`/`-target` options, + you should also set the appropriate platform classes using the `--system` + option to give the location of an appropriate installed release of JDK. + +When using the `--release` option, only the supported documented API for that +release may be used; you cannot use any options to break encapsulation to +access any internal classes. + +## APIs + +The `javac` compiler can be invoked using an API in three different ways: + +The [Java Compiler API](../../api/java.compiler/javax/tools/JavaCompiler.html) +: This provides the most flexible way to invoke the compiler, + including the ability to compile source files provided in + memory buffers or other non-standard file systems. + +The [ToolProvider API](../../api/java.base/java/util/spi/ToolProvider.html) +: A `ToolProvider` for `javac` can be obtained by calling + `ToolProvider.findFirst("javac")`. This returns an object + with the equivalent functionality of the command-line tool. + + **Note**: This API should not be confused with the like-named + API in the [`javax.tools`](../../api/java.compiler/javax/tools/ToolProvider.html) + package. + +The `javac` [Legacy API](../../api/jdk.compiler/com/sun/tools/javac/Main.html) +: This API is retained for backward compatibility only. + All new code should use either the Java Compiler API or the ToolProvider API. + +**Note:** All other classes and methods found in a package with names that start with +`com.sun.tools.javac` (subpackages of `com.sun.tools.javac`) are strictly +internal and subject to change at any time. + +## Examples of Using -Xlint keys + +`cast` +: Warns about unnecessary and redundant casts, for example: + + > `String s = (String) "Hello!"` + +`classfile` +: Warns about issues related to class file contents. + +`deprecation` +: Warns about the use of deprecated items. For example: + + ``` + java.util.Date myDate = new java.util.Date(); + int currentDay = myDate.getDay(); + ``` + + The method `java.util.Date.getDay` has been deprecated since JDK 1.1. + +`dep-ann` +: Warns about items that are documented with the `@deprecated` Javadoc + comment, but do not have the `@Deprecated` annotation, for example: + + ``` + /** + * @deprecated As of Java SE 7, replaced by {@link #newMethod()} + */ + public static void deprecatedMethod() { } + public static void newMethod() { } + ``` + +`divzero` +: Warns about division by the constant integer 0, for example: + + > `int divideByZero = 42 / 0;` + +`empty` +: Warns about empty statements after `if`statements, for example: + + ``` + class E { + void m() { + if (true) ; + } + } + ``` + +`fallthrough` +: Checks the switch blocks for fall-through cases and provides a warning + message for any that are found. Fall-through cases are cases in a switch + block, other than the last case in the block, whose code does not include a + `break` statement, allowing code execution to fall through from that case to + the next case. For example, the code following the case 1 label in this + switch block does not end with a `break` statement: + + ``` + switch (x) { + case 1: + System.out.println("1"); + // No break statement here. + case 2: + System.out.println("2"); + } + ``` + + If the `-Xlint:fallthrough` option was used when compiling this code, then + the compiler emits a warning about possible fall-through into case, with + the line number of the case in question. + +`finally` +: Warns about `finally` clauses that cannot be completed normally, for + example: + + ``` + public static int m() { + try { + throw new NullPointerException(); + } catch (NullPointerException(); { + System.err.println("Caught NullPointerException."); + return 1; + } finally { + return 0; + } + } + ``` + + The compiler generates a warning for the `finally` block in this example. + When the `int` method is called, it returns a value of 0. A `finally` block + executes when the `try` block exits. In this example, when control is + transferred to the `catch` block, the `int` method exits. However, the + `finally` block must execute, so it's executed, even though control was + transferred outside the method. + +`options` +: Warns about issues that related to the use of command-line options. See + [Compiling for Earlier Releases of the Platform]. + +`overrides` +: Warns about issues related to method overrides. For example, consider the + following two classes: + + ``` + public class ClassWithVarargsMethod { + void varargsMethod(String... s) { } + } + + public class ClassWithOverridingMethod extends ClassWithVarargsMethod { + @Override + void varargsMethod(String[] s) { } + } + ``` + + The compiler generates a warning similar to the following:. + + ``` + warning: [override] varargsMethod(String[]) in ClassWithOverridingMethod + overrides varargsMethod(String...) in ClassWithVarargsMethod; overriding + method is missing '...' + ``` + + When the compiler encounters a `varargs` method, it translates the + `varargs` formal parameter into an array. In the method + `ClassWithVarargsMethod.varargsMethod`, the compiler translates the + `varargs` formal parameter `String... s` to the formal parameter + `String[] s`, an array that matches the formal parameter of the method + `ClassWithOverridingMethod.varargsMethod`. Consequently, this example + compiles. + +`path` +: Warns about invalid path elements and nonexistent path directories on the + command line (with regard to the class path, the source path, and other + paths). Such warnings cannot be suppressed with the `@SuppressWarnings` + annotation. For example: + + - **Linux and macOS:** + `javac -Xlint:path -classpath /nonexistentpath Example.java` + + - **Windows:** + `javac -Xlint:path -classpath C:\nonexistentpath Example.java` + +`processing` +: Warns about issues related to annotation processing. The compiler generates + this warning when you have a class that has an annotation, and you use an + annotation processor that cannot handle that type of annotation. For example, + the following is a simple annotation processor: + + **Source file AnnoProc.java**: + + ``` + import java.util.*; + import javax.annotation.processing.*; + import javax.lang.model.*; + import javax.lang.model.element.*; + + @SupportedAnnotationTypes("NotAnno") + public class AnnoProc extends AbstractProcessor { + public boolean process(Set elems, RoundEnvironment renv){ + return true; + } + + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + } + ``` + + **Source file AnnosWithoutProcessors.java**: + + ``` + @interface Anno { } + + @Anno + class AnnosWithoutProcessors { } + ``` + + The following commands compile the annotation processor `AnnoProc`, then + run this annotation processor against the source file + `AnnosWithoutProcessors.java`: + + ``` + javac AnnoProc.java + javac -cp . -Xlint:processing -processor AnnoProc -proc:only AnnosWithoutProcessors.java + ``` + + When the compiler runs the annotation processor against the source file + `AnnosWithoutProcessors.java`, it generates the following warning: + + ``` + warning: [processing] No processor claimed any of these annotations: Anno + ``` + + To resolve this issue, you can rename the annotation defined and used in + the class `AnnosWithoutProcessors` from `Anno` to `NotAnno`. + +`rawtypes` +: Warns about unchecked operations on raw types. The following statement + generates a `rawtypes` warning: + + > `void countElements(List l) { ... }` + + The following example does not generate a `rawtypes` warning: + + > `void countElements(List l) { ... }` + + `List` is a raw type. However, `List` is an unbounded wildcard + parameterized type. Because `List` is a parameterized interface, always + specify its type argument. In this example, the `List` formal argument is + specified with an unbounded wildcard (`?`) as its formal type parameter, + which means that the `countElements` method can accept any instantiation of + the `List` interface. + +`serial` +: Warns about missing `serialVersionUID` definitions on serializable classes. + For example: + + ``` + public class PersistentTime implements Serializable + { + private Date time; + + public PersistentTime() { + time = Calendar.getInstance().getTime(); + } + + public Date getTime() { + return time; + } + } + ``` + + The compiler generates the following warning: + + ``` + warning: [serial] serializable class PersistentTime has no definition of + serialVersionUID + ``` + + If a serializable class does not explicitly declare a field named + `serialVersionUID`, then the serialization runtime environment calculates a + default `serialVersionUID` value for that class based on various aspects of + the class, as described in the Java Object Serialization Specification. + However, it's strongly recommended that all serializable classes explicitly + declare `serialVersionUID` values because the default process of computing + `serialVersionUID` values is highly sensitive to class details that can + vary depending on compiler implementations. As a result, this might cause + an unexpected `InvalidClassExceptions` during deserialization. To guarantee + a consistent `serialVersionUID` value across different Java compiler + implementations, a serializable class must declare an explicit + `serialVersionUID` value. + +`static` +: Warns about issues relating to the use of static variables, for example: + + ``` + class XLintStatic { + static void m1() { } + void m2() { this.m1(); } + } + ``` + + The compiler generates the following warning: + + ``` + warning: [static] static method should be qualified by type name, + XLintStatic, instead of by an expression + ``` + + To resolve this issue, you can call the `static` method `m1` as follows: + + > `XLintStatic.m1();` + + Alternately, you can remove the `static` keyword from the declaration of + the method `m1`. + +`this-escape` +: Warns about constructors leaking + `this` prior to subclass initialization. + For example, this class: + + ``` + public class MyClass { + public MyClass() { + System.out.println(this.hashCode()); + } + } + ``` + + generates the following warning: + + ``` + MyClass.java:3: warning: [this-escape] possible 'this' escape + before subclass is fully initialized + System.out.println(this.hashCode()); + ^ + ``` + + A 'this' escape warning is generated when a constructor does something + that might result in a subclass method being invoked before the + constructor returns. + In such cases the subclass method would be operating on an incompletely + initialized instance. + In the above example, a subclass of `MyClass` that overrides + `hashCode()` to incorporate its own fields would likely produce + an incorrect result when invoked as shown. + + Warnings are only generated if a subclass could exist that is outside + of the current module (or package, if no module) being compiled. + So, for example, constructors in final and non-public classes do not + generate warnings. + +`try` +: Warns about issues relating to the use of `try` blocks, including + try-with-resources statements. For example, a warning is generated for the + following statement because the resource `ac` declared in the `try` block + is not used: + + ``` + try ( AutoCloseable ac = getResource() ) { // do nothing} + ``` + +`unchecked` +: Gives more detail for unchecked conversion warnings that are mandated by + the Java Language Specification, for example: + + ``` + List l = new ArrayList(); + List ls = l; // unchecked warning + ``` + + During type erasure, the types `ArrayList` and `List` + become `ArrayList` and `List`, respectively. + + The `ls` command has the parameterized type `List`. When the `List` + referenced by `l` is assigned to `ls`, the compiler generates an unchecked + warning. At compile time, the compiler and JVM cannot determine whether `l` + refers to a `List` type. In this case, `l` does not refer to a + `List` type. As a result, heap pollution occurs. + + A heap pollution situation occurs when the `List` object `l`, whose static + type is `List`, is assigned to another `List` object, `ls`, that + has a different static type, `List`. However, the compiler still + allows this assignment. It must allow this assignment to preserve backward + compatibility with releases of Java SE that do not support generics. Because + of type erasure, `List` and `List` both become `List`. + Consequently, the compiler allows the assignment of the object `l`, which + has a raw type of `List`, to the object `ls`. + +`varargs` +: Warns about unsafe use of variable arguments (`varargs`) methods, in + particular, those that contain non-reifiable arguments, for example: + + ``` + public class ArrayBuilder { + public static void addToList (List listArg, T... elements) { + for (T x : elements) { + listArg.add(x); + } + } + } + ``` + + A non-reifiable type is a type whose type information is not fully available + at runtime. + + The compiler generates the following warning for the definition of the + method `ArrayBuilder.addToList`: + + ``` + warning: [varargs] Possible heap pollution from parameterized vararg type T + ``` + + When the compiler encounters a varargs method, it translates the `varargs` + formal parameter into an array. However, the Java programming language + does not permit the creation of arrays of parameterized types. In the method + `ArrayBuilder.addToList`, the compiler translates the `varargs` formal + parameter `T...` elements to the formal parameter `T[]` elements, an array. + However, because of type erasure, the compiler converts the `varargs` + formal parameter to `Object[]` elements. Consequently, there's a + possibility of heap pollution. diff --git a/src/jdk.compiler/share/man/serialver.1 b/src/jdk.compiler/share/man/serialver.1 deleted file mode 100644 index bad14872ee6..00000000000 --- a/src/jdk.compiler/share/man/serialver.1 +++ /dev/null @@ -1,90 +0,0 @@ -.\" Copyright (c) 1997, 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 -.\" 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "SERIALVER" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -serialver - return the \f[V]serialVersionUID\f[R] for one or more -classes in a form suitable for copying into an evolving class -.SH SYNOPSIS -.PP -\f[V]serialver\f[R] [\f[I]options\f[R]] [\f[I]classnames\f[R]] -.TP -\f[I]options\f[R] -This represents the command-line options for the \f[V]serialver\f[R] -command. -See \f[B]Options for serialver\f[R]. -.TP -\f[I]classnames\f[R] -The classes for which \f[V]serialVersionUID\f[R] is to be returned. -.SH DESCRIPTION -.PP -The \f[V]serialver\f[R] command returns the \f[V]serialVersionUID\f[R] -for one or more classes in a form suitable for copying into an evolving -class. -When called with no arguments, the \f[V]serialver\f[R] command prints a -usage line. -.SH OPTIONS FOR SERIALVER -.TP -\f[V]-classpath\f[R] \f[I]path-files\f[R] -Sets the search path for application classes and resources. -Separate classes and resources with a colon (:). -.TP -\f[V]-J\f[R]\f[I]option\f[R] -Passes the specified \f[I]option\f[R] to the Java Virtual Machine, where -\f[I]option\f[R] is one of the options described on the reference page -for the Java application launcher. -For example, \f[V]-J-Xms48m\f[R] sets the startup memory to 48 MB. -.SH NOTES -.PP -The \f[V]serialver\f[R] command loads and initializes the specified -classes in its virtual machine, and by default, it doesn\[aq]t set a -security manager. -If the \f[V]serialver\f[R] command is to be run with untrusted classes, -then a security manager can be set with the following option: -.RS -.PP -\f[V]-J-Djava.security.manager\f[R] -.RE -.PP -When necessary, a security policy can be specified with the following -option: -.RS -.PP -\f[V]-J-Djava.security.policy=\f[R]\f[I]policy_file\f[R] -.RE diff --git a/src/jdk.compiler/share/man/serialver.md b/src/jdk.compiler/share/man/serialver.md new file mode 100644 index 00000000000..5838f1c61a9 --- /dev/null +++ b/src/jdk.compiler/share/man/serialver.md @@ -0,0 +1,74 @@ +--- +# Copyright (c) 1997, 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 +# 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. +# + +title: 'SERIALVER(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +serialver - return the `serialVersionUID` for one or more classes in a form +suitable for copying into an evolving class + +## Synopsis + +`serialver` \[*options*\] \[*classnames*\] + +*options* +: This represents the command-line options for the `serialver` command. See + [Options for serialver]. + +*classnames* +: The classes for which `serialVersionUID` is to be returned. + +## Description + +The `serialver` command returns the `serialVersionUID` for one or more classes +in a form suitable for copying into an evolving class. When called with no +arguments, the `serialver` command prints a usage line. + +## Options for serialver + +`-classpath` *path-files* +: Sets the search path for application classes and resources. Separate + classes and resources with a colon (:). + +`-J`*option* +: Passes the specified *option* to the Java Virtual Machine, where *option* + is one of the options described on the reference page for the Java + application launcher. For example, `-J-Xms48m` sets the startup memory to + 48 MB. + +## Notes + +The `serialver` command loads and initializes the specified classes in its +virtual machine, and by default, it doesn't set a security manager. If the +`serialver` command is to be run with untrusted classes, then a security +manager can be set with the following option: + +> `-J-Djava.security.manager` + +When necessary, a security policy can be specified with the following option: + +> `-J-Djava.security.policy=`*policy\_file* diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java index 18ccda542a0..88a74e73eda 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java @@ -31,8 +31,6 @@ import java.nio.charset.StandardCharsets; import java.util.*; -import java.security.*; - import sun.security.util.PropertyExpander; import sun.security.pkcs11.wrapper.*; @@ -58,31 +56,16 @@ final class Config { // will accept single threaded modules regardless of the setting in their // config files. private static final boolean staticAllowSingleThreadedModules; - private static final String osName; - private static final String osArch; static { - @SuppressWarnings("removal") - List props = AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public List run() { - return List.of( - System.getProperty( - "sun.security.pkcs11.allowSingleThreadedModules", - "true"), - System.getProperty("os.name"), - System.getProperty("os.arch")); - } - } - ); - if ("false".equalsIgnoreCase(props.get(0))) { + String allowSingleThreadedModules = + System.getProperty( + "sun.security.pkcs11.allowSingleThreadedModules", "true"); + if ("false".equalsIgnoreCase(allowSingleThreadedModules)) { staticAllowSingleThreadedModules = false; } else { staticAllowSingleThreadedModules = true; } - osName = props.get(1); - osArch = props.get(2); } private static final boolean DEBUG = false; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java index 49718e254b3..5d83fa106fd 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java @@ -108,12 +108,9 @@ abstract class P11Key implements Key, Length { * */ static { - PrivilegedAction getKeyExtractionProp = - () -> System.getProperty( - "sun.security.pkcs11.disableKeyExtraction", "false"); - @SuppressWarnings("removal") String disableKeyExtraction = - AccessController.doPrivileged(getKeyExtractionProp); + System.getProperty( + "sun.security.pkcs11.disableKeyExtraction", "false"); DISABLE_NATIVE_KEYS_EXTRACTION = "true".equalsIgnoreCase(disableKeyExtraction); } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyAgreement.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyAgreement.java index 7a47f147bf4..6c010a4a513 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyAgreement.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyAgreement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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,14 +71,8 @@ final class P11KeyAgreement extends KeyAgreementSpi { private static class AllowKDF { - private static final boolean VALUE = getValue(); - - @SuppressWarnings("removal") - private static boolean getValue() { - return AccessController.doPrivileged( - (PrivilegedAction) - () -> Boolean.getBoolean("jdk.crypto.KeyAgreement.legacyKDF")); - } + private static final boolean VALUE = + Boolean.getBoolean("jdk.crypto.KeyAgreement.legacyKDF"); } P11KeyAgreement(Token token, String algorithm, long mechanism) { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java index 8a2b745fe38..5c95e381f5c 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -130,7 +130,7 @@ static Provider getSunJceProvider() { return p; } - @SuppressWarnings("removal") + @SuppressWarnings("deprecation") private static Provider getProvider(Provider p, String providerName, String className) { if (p != null) { @@ -140,22 +140,8 @@ private static Provider getProvider(Provider p, String providerName, if (p == null) { try { final Class c = Class.forName(className); - p = AccessController.doPrivileged( - new PrivilegedAction() { - public Provider run() { - try { - @SuppressWarnings("deprecation") - Object o = c.newInstance(); - return (Provider) o; - } catch (Exception e) { - throw new ProviderException( - "Could not find provider " + - providerName, e); - } - } - }, null, new RuntimePermission( - "accessClassInPackage." + c.getPackageName())); - } catch (ClassNotFoundException e) { + p = (Provider) c.newInstance(); + } catch (Exception e) { // Unexpected, as className is not a user but a // P11Util-internal value. throw new ProviderException("Could not find provider " + diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java index e77edc98399..19d56dec93c 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -117,19 +117,13 @@ public SunPKCS11() { poller = null; } - @SuppressWarnings("removal") @Override public Provider configure(String configArg) throws InvalidParameterException { final String newConfigName = checkNull(configArg); try { - return AccessController.doPrivileged(new PrivilegedExceptionAction<>() { - @Override - public SunPKCS11 run() throws Exception { - return new SunPKCS11(new Config(newConfigName)); - } - }); - } catch (PrivilegedActionException pae) { - throw new InvalidParameterException("Error configuring SunPKCS11 provider", pae.getException()); + return new SunPKCS11(new Config(newConfigName)); + } catch (IOException ioe) { + throw new InvalidParameterException("Error configuring SunPKCS11 provider", ioe); } } @@ -1117,7 +1111,6 @@ void disable() { } // create the poller thread, if not already active - @SuppressWarnings("removal") private void createPoller() { if (poller != null) { return; @@ -1197,7 +1190,6 @@ public void run() { } // create the cleaner thread, if not already active - @SuppressWarnings("removal") private void createCleaner() { cleaner = new NativeResourceCleaner(); Thread t = InnocuousThread.newSystemThread( @@ -1210,7 +1202,6 @@ private void createCleaner() { } // destroy the token. Called if we detect that it has been removed - @SuppressWarnings("removal") synchronized void uninitToken(Token token) { if (this.token != token) { // mismatch, our token must already be destroyed @@ -1219,12 +1210,7 @@ synchronized void uninitToken(Token token) { destroyPoller(); this.token = null; // unregister all algorithms - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - clear(); - return null; - } - }); + clear(); // keep polling for token insertion unless configured not to if (removable && !config.getDestroyTokenAfterLogout()) { createPoller(); @@ -1386,36 +1372,29 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception { } // register algorithms in provider - @SuppressWarnings("removal") - var dummy = AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - for (Map.Entry entry - : supportedAlgs.entrySet()) { - Descriptor d = entry.getKey(); - int mechanism = entry.getValue().intValue(); - Service s = d.service(token, mechanism); - putService(s); - } - if (((token.tokenInfo.flags & CKF_RNG) != 0) - && config.isEnabled(PCKM_SECURERANDOM) - && !token.sessionManager.lowMaxSessions()) { - // do not register SecureRandom if the token does - // not support many sessions. if we did, we might - // run out of sessions in the middle of a - // nextBytes() call where we cannot fail over. - putService(new P11Service(token, SR, "PKCS11", - "sun.security.pkcs11.P11SecureRandom", null, - PCKM_SECURERANDOM)); - } - if (config.isEnabled(PCKM_KEYSTORE)) { - putService(new P11Service(token, KS, "PKCS11", - "sun.security.pkcs11.P11KeyStore", - List.of("PKCS11-" + config.getName()), - PCKM_KEYSTORE)); - } - return null; - } - }); + for (Map.Entry entry : supportedAlgs.entrySet()) { + Descriptor d = entry.getKey(); + int mechanism = entry.getValue().intValue(); + Service s = d.service(token, mechanism); + putService(s); + } + if (((token.tokenInfo.flags & CKF_RNG) != 0) + && config.isEnabled(PCKM_SECURERANDOM) + && !token.sessionManager.lowMaxSessions()) { + // do not register SecureRandom if the token does + // not support many sessions. if we did, we might + // run out of sessions in the middle of a + // nextBytes() call where we cannot fail over. + putService(new P11Service(token, SR, "PKCS11", + "sun.security.pkcs11.P11SecureRandom", null, + PCKM_SECURERANDOM)); + } + if (config.isEnabled(PCKM_KEYSTORE)) { + putService(new P11Service(token, KS, "PKCS11", + "sun.security.pkcs11.P11KeyStore", + List.of("PKCS11-" + config.getName()), + PCKM_KEYSTORE)); + } this.token = token; if (cleaner == null) { @@ -1621,10 +1600,6 @@ public String toString() { * @throws IllegalStateException if the provider requires configuration * and Provider.configure has not been called * @throws LoginException if the login operation fails - * @throws SecurityException if the does not pass a security check for - * SecurityPermission("authProvider.name"), - * where name is the value returned by - * this provider's getName method */ public void login(Subject subject, CallbackHandler handler) throws LoginException { @@ -1633,17 +1608,6 @@ public void login(Subject subject, CallbackHandler handler) throw new IllegalStateException("Configuration is required"); } - // security check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (debug != null) { - debug.println("checking login permission"); - } - sm.checkPermission(new SecurityPermission - ("authProvider." + this.getName())); - } - if (!hasValidToken()) { throw new LoginException("No token present"); @@ -1753,24 +1717,12 @@ public void login(Subject subject, CallbackHandler handler) * @throws IllegalStateException if the provider requires configuration * and Provider.configure has not been called * @throws LoginException if the logout operation fails - * @throws SecurityException if the does not pass a security check for - * SecurityPermission("authProvider.name"), - * where name is the value returned by - * this provider's getName method */ public void logout() throws LoginException { if (!isConfigured()) { throw new IllegalStateException("Configuration is required"); } - // security check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission - (new SecurityPermission("authProvider." + this.getName())); - } - if (!hasValidToken()) { // app may call logout for cleanup, allow return; @@ -1844,11 +1796,6 @@ public void logout() throws LoginException { * * @throws IllegalStateException if the provider requires configuration * and Provider.configure has not been called - * @throws SecurityException if the caller does not pass a - * security check for - * SecurityPermission("authProvider.name"), - * where name is the value returned by - * this provider's getName method */ public void setCallbackHandler(CallbackHandler handler) { @@ -1856,14 +1803,6 @@ public void setCallbackHandler(CallbackHandler handler) { throw new IllegalStateException("Configuration is required"); } - // security check - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission - (new SecurityPermission("authProvider." + this.getName())); - } - synchronized (LOCK_HANDLER) { pHandler = handler; } @@ -1887,60 +1826,51 @@ private CallbackHandler getCallbackHandler(CallbackHandler handler) { return pHandler; } - try { - if (debug != null) { - debug.println("getting default callback handler"); - } - - @SuppressWarnings("removal") - CallbackHandler myHandler = AccessController.doPrivileged - (new PrivilegedExceptionAction() { - public CallbackHandler run() throws Exception { + if (debug != null) { + debug.println("getting default callback handler"); + } - String defaultHandler = - java.security.Security.getProperty - ("auth.login.defaultCallbackHandler"); + String defaultHandler = Security.getProperty + ("auth.login.defaultCallbackHandler"); - if (defaultHandler == null || - defaultHandler.length() == 0) { + if (defaultHandler == null || defaultHandler.length() == 0) { - // ok - if (debug != null) { - debug.println("no default handler set"); - } - return null; - } + // ok + if (debug != null) { + debug.println("no default handler set"); + } + return null; + } - Class c = Class.forName - (defaultHandler, - true, - Thread.currentThread().getContextClassLoader()); - if (!javax.security.auth.callback.CallbackHandler.class.isAssignableFrom(c)) { - // not the right subtype - if (debug != null) { - debug.println("default handler " + defaultHandler + - " is not a CallbackHandler"); - } - return null; - } - @SuppressWarnings("deprecation") - Object result = c.newInstance(); - return (CallbackHandler)result; + try { + Class c = Class.forName + (defaultHandler, + true, + Thread.currentThread().getContextClassLoader()); + if (!CallbackHandler.class.isAssignableFrom(c)) { + // not the right subtype + if (debug != null) { + debug.println("default handler " + defaultHandler + + " is not a CallbackHandler"); } - }); + return null; + } + @SuppressWarnings("deprecation") + Object result = c.newInstance(); + CallbackHandler myHandler = (CallbackHandler)result; // save it pHandler = myHandler; return myHandler; - } catch (PrivilegedActionException pae) { + } catch (ReflectiveOperationException roe) { // ok if (debug != null) { debug.println("Unable to load default callback handler"); - pae.printStackTrace(); + roe.printStackTrace(); } } + return null; } - return null; } private Object writeReplace() throws ObjectStreamException { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java index f7dfd055000..6ce50d9d695 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java @@ -51,9 +51,6 @@ import java.io.IOException; import java.util.*; -import java.security.AccessController; -import java.security.PrivilegedAction; - import sun.security.util.Debug; import sun.security.pkcs11.P11Util; @@ -80,16 +77,12 @@ public class PKCS11 { private static final String PKCS11_WRAPPER = "j2pkcs11"; static { - // cannot use LoadLibraryAction because that would make the native - // library available to the bootclassloader, but we run in the - // extension classloader. - @SuppressWarnings({"removal", "restricted"}) - var dummy = AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - System.loadLibrary(PKCS11_WRAPPER); - return null; - } - }); + loadAndInitializeLibrary(); + } + + @SuppressWarnings("restricted") + private static void loadAndInitializeLibrary() { + System.loadLibrary(PKCS11_WRAPPER); boolean enableDebug = Debug.getInstance("sunpkcs11") != null; initializeLibrary(enableDebug); } diff --git a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java index 4e352bf4950..41580151f2b 100644 --- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java +++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,15 +29,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.AccessController; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyStoreSpi; import java.security.KeyStoreException; -import java.security.PrivilegedAction; import java.security.UnrecoverableKeyException; import java.security.NoSuchAlgorithmException; -import java.security.SecurityPermission; import java.security.cert.X509Certificate; import java.security.cert.Certificate; import java.security.cert.CertificateException; @@ -242,9 +239,7 @@ public void delete() throws KeyStoreException { CKeyStore(String storeName, int storeLocation) { // Get the compatibility mode - @SuppressWarnings("removal") - String prop = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty(KEYSTORE_COMPATIBILITY_MODE_PROP)); + String prop = System.getProperty(KEYSTORE_COMPATIBILITY_MODE_PROP); if ("false".equalsIgnoreCase(prop)) { keyStoreCompatibilityMode = false; @@ -695,10 +690,6 @@ public void engineStore(OutputStream stream, char[] password) * the integrity of the keystore cannot be found * @exception CertificateException if any of the certificates in the * keystore could not be loaded - * @exception SecurityException if the security check for - * SecurityPermission("authProvider.name") does not - * pass, where name is the value returned by - * this provider's getName method. */ public void engineLoad(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException { @@ -710,16 +701,6 @@ public void engineLoad(InputStream stream, char[] password) throw new IOException("Keystore password must be null"); } - /* - * Use the same security check as AuthProvider.login - */ - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new SecurityPermission( - "authProvider.SunMSCAPI")); - } - // Clear all key entries entries.clear(); diff --git a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java index e57fe331f28..8ee16cf6bb8 100644 --- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java +++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package sun.security.mscapi; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.security.Provider; import java.security.NoSuchAlgorithmException; import java.security.InvalidParameterException; @@ -50,14 +48,14 @@ public final class SunMSCAPI extends Provider { private static final String INFO = "Sun's Microsoft Crypto API provider"; static { - @SuppressWarnings({"removal", "restricted"}) - var dummy = AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - System.loadLibrary("sunmscapi"); - return null; - } - }); + loadLibrary(); + } + + @SuppressWarnings("restricted") + private static void loadLibrary() { + System.loadLibrary("sunmscapi"); } + private static class ProviderServiceA extends ProviderService { ProviderServiceA(Provider p, String type, String algo, String cn, HashMap attrs) { @@ -148,119 +146,113 @@ public Object newInstance(Object ctrParamObj) } } - @SuppressWarnings("removal") public SunMSCAPI() { super("SunMSCAPI", PROVIDER_VER, INFO); final Provider p = this; - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - /* - * Secure random - */ - HashMap srattrs = new HashMap<>(1); - srattrs.put("ThreadSafe", "true"); - putService(new ProviderService(p, "SecureRandom", - "Windows-PRNG", "sun.security.mscapi.PRNG", - null, srattrs)); + /* + * Secure random + */ + HashMap srattrs = new HashMap<>(1); + srattrs.put("ThreadSafe", "true"); + putService(new ProviderService(p, "SecureRandom", + "Windows-PRNG", "sun.security.mscapi.PRNG", + null, srattrs)); - /* - * Key store - */ - putService(new ProviderService(p, "KeyStore", - "Windows-MY", "sun.security.mscapi.CKeyStore$MY")); - putService(new ProviderService(p, "KeyStore", - "Windows-MY-CURRENTUSER", "sun.security.mscapi.CKeyStore$MY")); - putService(new ProviderService(p, "KeyStore", - "Windows-ROOT", "sun.security.mscapi.CKeyStore$ROOT")); - putService(new ProviderService(p, "KeyStore", - "Windows-ROOT-CURRENTUSER", "sun.security.mscapi.CKeyStore$ROOT")); - putService(new ProviderService(p, "KeyStore", - "Windows-MY-LOCALMACHINE", "sun.security.mscapi.CKeyStore$MYLocalMachine")); - putService(new ProviderService(p, "KeyStore", - "Windows-ROOT-LOCALMACHINE", "sun.security.mscapi.CKeyStore$ROOTLocalMachine")); + /* + * Key store + */ + putService(new ProviderService(p, "KeyStore", + "Windows-MY", "sun.security.mscapi.CKeyStore$MY")); + putService(new ProviderService(p, "KeyStore", + "Windows-MY-CURRENTUSER", "sun.security.mscapi.CKeyStore$MY")); + putService(new ProviderService(p, "KeyStore", + "Windows-ROOT", "sun.security.mscapi.CKeyStore$ROOT")); + putService(new ProviderService(p, "KeyStore", + "Windows-ROOT-CURRENTUSER", "sun.security.mscapi.CKeyStore$ROOT")); + putService(new ProviderService(p, "KeyStore", + "Windows-MY-LOCALMACHINE", "sun.security.mscapi.CKeyStore$MYLocalMachine")); + putService(new ProviderService(p, "KeyStore", + "Windows-ROOT-LOCALMACHINE", "sun.security.mscapi.CKeyStore$ROOTLocalMachine")); - /* - * Signature engines - */ - HashMap attrs = new HashMap<>(1); - attrs.put("SupportedKeyClasses", "sun.security.mscapi.CKey"); + /* + * Signature engines + */ + HashMap attrs = new HashMap<>(1); + attrs.put("SupportedKeyClasses", "sun.security.mscapi.CKey"); - // NONEwithRSA must be supplied with a pre-computed message digest. - // Only the following digest algorithms are supported: MD5, SHA-1, - // SHA-256, SHA-384, SHA-512 and a special-purpose digest - // algorithm which is a concatenation of SHA-1 and MD5 digests. - putService(new ProviderService(p, "Signature", - "NONEwithRSA", "sun.security.mscapi.CSignature$NONEwithRSA", - null, attrs)); - putService(new ProviderService(p, "Signature", - "SHA1withRSA", "sun.security.mscapi.CSignature$SHA1withRSA", - null, attrs)); - putService(new ProviderServiceA(p, "Signature", - "SHA256withRSA", - "sun.security.mscapi.CSignature$SHA256withRSA", - attrs)); - putService(new ProviderServiceA(p, "Signature", - "SHA384withRSA", - "sun.security.mscapi.CSignature$SHA384withRSA", - attrs)); - putService(new ProviderServiceA(p, "Signature", - "SHA512withRSA", - "sun.security.mscapi.CSignature$SHA512withRSA", - attrs)); - putService(new ProviderServiceA(p, "Signature", - "RSASSA-PSS", "sun.security.mscapi.CSignature$PSS", - attrs)); - putService(new ProviderService(p, "Signature", - "MD5withRSA", "sun.security.mscapi.CSignature$MD5withRSA", - null, attrs)); - putService(new ProviderService(p, "Signature", - "MD2withRSA", "sun.security.mscapi.CSignature$MD2withRSA", - null, attrs)); - putService(new ProviderServiceA(p, "Signature", - "SHA1withECDSA", - "sun.security.mscapi.CSignature$SHA1withECDSA", - attrs)); - putService(new ProviderServiceA(p, "Signature", - "SHA224withECDSA", - "sun.security.mscapi.CSignature$SHA224withECDSA", - attrs)); - putService(new ProviderServiceA(p, "Signature", - "SHA256withECDSA", - "sun.security.mscapi.CSignature$SHA256withECDSA", - attrs)); - putService(new ProviderServiceA(p, "Signature", - "SHA384withECDSA", - "sun.security.mscapi.CSignature$SHA384withECDSA", - attrs)); - putService(new ProviderServiceA(p, "Signature", - "SHA512withECDSA", - "sun.security.mscapi.CSignature$SHA512withECDSA", - attrs)); - /* - * Key Pair Generator engines - */ - attrs.clear(); - attrs.put("KeySize", "16384"); - putService(new ProviderService(p, "KeyPairGenerator", - "RSA", "sun.security.mscapi.CKeyPairGenerator$RSA", - null, attrs)); + // NONEwithRSA must be supplied with a pre-computed message digest. + // Only the following digest algorithms are supported: MD5, SHA-1, + // SHA-256, SHA-384, SHA-512 and a special-purpose digest + // algorithm which is a concatenation of SHA-1 and MD5 digests. + putService(new ProviderService(p, "Signature", + "NONEwithRSA", "sun.security.mscapi.CSignature$NONEwithRSA", + null, attrs)); + putService(new ProviderService(p, "Signature", + "SHA1withRSA", "sun.security.mscapi.CSignature$SHA1withRSA", + null, attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA256withRSA", + "sun.security.mscapi.CSignature$SHA256withRSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA384withRSA", + "sun.security.mscapi.CSignature$SHA384withRSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA512withRSA", + "sun.security.mscapi.CSignature$SHA512withRSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "RSASSA-PSS", "sun.security.mscapi.CSignature$PSS", + attrs)); + putService(new ProviderService(p, "Signature", + "MD5withRSA", "sun.security.mscapi.CSignature$MD5withRSA", + null, attrs)); + putService(new ProviderService(p, "Signature", + "MD2withRSA", "sun.security.mscapi.CSignature$MD2withRSA", + null, attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA1withECDSA", + "sun.security.mscapi.CSignature$SHA1withECDSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA224withECDSA", + "sun.security.mscapi.CSignature$SHA224withECDSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA256withECDSA", + "sun.security.mscapi.CSignature$SHA256withECDSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA384withECDSA", + "sun.security.mscapi.CSignature$SHA384withECDSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA512withECDSA", + "sun.security.mscapi.CSignature$SHA512withECDSA", + attrs)); + /* + * Key Pair Generator engines + */ + attrs.clear(); + attrs.put("KeySize", "16384"); + putService(new ProviderService(p, "KeyPairGenerator", + "RSA", "sun.security.mscapi.CKeyPairGenerator$RSA", + null, attrs)); - /* - * Cipher engines - */ - attrs.clear(); - attrs.put("SupportedModes", "ECB"); - attrs.put("SupportedPaddings", "PKCS1PADDING"); - attrs.put("SupportedKeyClasses", "sun.security.mscapi.CKey"); - putService(new ProviderService(p, "Cipher", - "RSA", "sun.security.mscapi.CRSACipher", - null, attrs)); - putService(new ProviderService(p, "Cipher", - "RSA/ECB/PKCS1Padding", "sun.security.mscapi.CRSACipher", - null, attrs)); - return null; - } - }); + /* + * Cipher engines + */ + attrs.clear(); + attrs.put("SupportedModes", "ECB"); + attrs.put("SupportedPaddings", "PKCS1PADDING"); + attrs.put("SupportedKeyClasses", "sun.security.mscapi.CKey"); + putService(new ProviderService(p, "Cipher", + "RSA", "sun.security.mscapi.CRSACipher", + null, attrs)); + putService(new ProviderService(p, "Cipher", + "RSA/ECB/PKCS1Padding", "sun.security.mscapi.CRSACipher", + null, attrs)); } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncherLoader.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncherLoader.java index 6579ac26cfc..a67f0b00077 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncherLoader.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncherLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -76,14 +76,6 @@ public SALauncherLoader(ClassLoader parent) { */ public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - int i = name.lastIndexOf('.'); - if (i != -1) { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPackageAccess(name.substring(0, i)); - } - } Class clazz = findLoadedClass(name); if (clazz != null) return clazz; @@ -104,15 +96,6 @@ public synchronized Class loadClass(String name, boolean resolve) } } - /** - * allow any classes loaded from classpath to exit the VM. - */ - protected PermissionCollection getPermissions(CodeSource codesource) { - PermissionCollection perms = super.getPermissions(codesource); - perms.add(new RuntimePermission("exitVM")); - return perms; - } - //-- Internals only below this point private String[] libpaths; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java index 2ed2106c02d..95fa363c324 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,6 @@ package sun.jvm.hotspot.tools.jcore; -import java.security.AccessController; -import java.security.PrivilegedAction; - import sun.jvm.hotspot.interpreter.Bytecodes; import sun.jvm.hotspot.oops.ConstantPool; import sun.jvm.hotspot.oops.ConstantPoolCache; @@ -44,19 +41,7 @@ public class ByteCodeRewriter private Bytes bytes; private static final int jintSize = 4; - public static final boolean DEBUG; - - static { - @SuppressWarnings("removal") - String debug = AccessController.doPrivileged( - new PrivilegedAction<>() { - public String run() { - return System.getProperty("sun.jvm.hotspot.tools.jcore.ByteCodeRewriter.DEBUG"); - } - } - ); - DEBUG = (debug != null ? debug.equalsIgnoreCase("true") : false); - } + public static final boolean DEBUG = Boolean.getBoolean("sun.jvm.hotspot.tools.jcore.ByteCodeRewriter.DEBUG"); protected void debugMessage(String message) { diff --git a/src/jdk.hotspot.agent/share/man/jhsdb.1 b/src/jdk.hotspot.agent/share/man/jhsdb.1 deleted file mode 100644 index 93cc1fedb15..00000000000 --- a/src/jdk.hotspot.agent/share/man/jhsdb.1 +++ /dev/null @@ -1,218 +0,0 @@ -.\" Copyright (c) 2019, 2024, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JHSDB" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jhsdb - attach to a Java process or launch a postmortem debugger to -analyze the content of a core dump from a crashed Java Virtual Machine -(JVM) -.SH SYNOPSIS -.PP -\f[B]WARNING:\f[R] The \f[V]debugd\f[R] subcommand and -\f[V]--connect\f[R] options are deprecated. -They will be removed in a future release. -.PP -\f[V]jhsdb\f[R] \f[V]clhsdb\f[R] [\f[V]--pid\f[R] \f[I]pid\f[R] | -\f[V]--exe\f[R] \f[I]executable\f[R] \f[V]--core\f[R] -\f[I]coredump\f[R]] -.PP -\f[V]jhsdb\f[R] \f[V]hsdb\f[R] [\f[V]--pid\f[R] \f[I]pid\f[R] | -\f[V]--exe\f[R] \f[I]executable\f[R] \f[V]--core\f[R] -\f[I]coredump\f[R]] -.PP -\f[V]jhsdb\f[R] \f[V]debugd\f[R] (\f[V]--pid\f[R] \f[I]pid\f[R] | -\f[V]--exe\f[R] \f[I]executable\f[R] \f[V]--core\f[R] -\f[I]coredump\f[R]) [\f[I]options\f[R]] -.PP -\f[V]jhsdb\f[R] \f[V]jstack\f[R] (\f[V]--pid\f[R] \f[I]pid\f[R] | -\f[V]--exe\f[R] \f[I]executable\f[R] \f[V]--core\f[R] \f[I]coredump\f[R] -| \f[V]--connect\f[R] \f[I][server-id\[at]]debugd-host\f[R]) -[\f[I]options\f[R]] -.PP -\f[V]jhsdb\f[R] \f[V]jmap\f[R] (\f[V]--pid\f[R] \f[I]pid\f[R] | -\f[V]--exe\f[R] \f[I]executable\f[R] \f[V]--core\f[R] \f[I]coredump\f[R] -| \f[V]--connect\f[R] \f[I][server-id\[at]]debugd-host\f[R]) -[\f[I]options\f[R]] -.PP -\f[V]jhsdb\f[R] \f[V]jinfo\f[R] (\f[V]--pid\f[R] \f[I]pid\f[R] | -\f[V]--exe\f[R] \f[I]executable\f[R] \f[V]--core\f[R] \f[I]coredump\f[R] -| \f[V]--connect\f[R] \f[I][server-id\[at]]debugd-host\f[R]) -[\f[I]options\f[R]] -.PP -\f[V]jhsdb\f[R] \f[V]jsnap\f[R] (\f[V]--pid\f[R] \f[I]pid\f[R] | -\f[V]--exe\f[R] \f[I]executable\f[R] \f[V]--core\f[R] \f[I]coredump\f[R] -| \f[V]--connect\f[R] \f[I][server-id\[at]]debugd-host\f[R]) -[\f[I]options\f[R]] -.TP -\f[I]pid\f[R] -The process ID to which the \f[V]jhsdb\f[R] tool should attach. -The process must be a Java process. -To get a list of Java processes running on a machine, use the -\f[V]ps\f[R] command or, if the JVM processes are not running in a -separate docker instance, the \f[B]jps\f[R] command. -.TP -\f[I]executable\f[R] -The Java executable file from which the core dump was produced. -.TP -\f[I]coredump\f[R] -The core file to which the \f[V]jhsdb\f[R] tool should attach. -.TP -\f[I][server-id\[at]]debugd-host\f[R] -An optional server ID and the address of the remote debug server -(debugd). -.TP -\f[I]options\f[R] -The command-line options for a \f[V]jhsdb\f[R] mode. -See \f[B]Options for the debugd Mode\f[R], \f[B]Options for the jstack -Mode\f[R], \f[B]Options for the jmap Mode\f[R], \f[B]Options for the -jinfo Mode\f[R], and \f[B]Options for the jsnap Mode\f[R]. -.PP -\f[B]Note:\f[R] -.PP -Either the \f[I]pid\f[R] or the pair of \f[I]executable\f[R] and -\f[I]core\f[R] files or the \f[I][server-id\[at]]debugd-host\f[R] must -be provided for \f[V]debugd\f[R], \f[V]jstack\f[R], \f[V]jmap\f[R], -\f[V]jinfo\f[R] and \f[V]jsnap\f[R] modes. -.SH DESCRIPTION -.PP -You can use the \f[V]jhsdb\f[R] tool to attach to a Java process or to -launch a postmortem debugger to analyze the content of a core-dump from -a crashed Java Virtual Machine (JVM). -This command is experimental and unsupported. -.PP -\f[B]Note:\f[R] -.PP -Attaching the \f[V]jhsdb\f[R] tool to a live process will cause the -process to hang and the process will probably crash when the debugger -detaches. -.PP -The \f[V]jhsdb\f[R] tool can be launched in any one of the following -modes: -.TP -\f[V]jhsdb clhsdb\f[R] -Starts the interactive command-line debugger. -.TP -\f[V]jhsdb hsdb\f[R] -Starts the interactive GUI debugger. -.TP -\f[V]jhsdb debugd\f[R] -Starts the remote debug server. -.TP -\f[V]jhsdb jstack\f[R] -Prints stack and locks information. -.TP -\f[V]jhsdb jmap\f[R] -Prints heap information. -.TP -\f[V]jhsdb jinfo\f[R] -Prints basic JVM information. -.TP -\f[V]jhsdb jsnap\f[R] -Prints performance counter information. -.TP -\f[V]jhsdb\f[R] \f[I]command\f[R] \f[V]--help\f[R] -Displays the options available for the \f[I]command\f[R]. -.SH OPTIONS FOR THE DEBUGD MODE -.TP -\f[V]--serverid\f[R] \f[I]server-id\f[R] -An optional unique ID for this debug server. -This is required if multiple debug servers are run on the same machine. -.TP -\f[V]--rmiport\f[R] \f[I]port\f[R] -Sets the port number to which the RMI connector is bound. -If not specified a random available port is used. -.TP -\f[V]--registryport\f[R] \f[I]port\f[R] -Sets the RMI registry port. -This option overrides the system property -\[aq]sun.jvm.hotspot.rmi.port\[aq]. -If not specified, the system property is used. -If the system property is not set, the default port 1099 is used. -.TP -\f[V]--hostname\f[R] \f[I]hostname\f[R] -Sets the hostname the RMI connector is bound. -The value could be a hostname or an IPv4/IPv6 address. -This option overrides the system property -\[aq]java.rmi.server.hostname\[aq]. -If not specified, the system property is used. -If the system property is not set, a system hostname is used. -.SH OPTIONS FOR THE JINFO MODE -.TP -\f[V]--flags\f[R] -Prints the VM flags. -.TP -\f[V]--sysprops\f[R] -Prints the Java system properties. -.TP -no option -Prints the VM flags and the Java system properties. -.SH OPTIONS FOR THE JMAP MODE -.TP -no option -Prints the same information as Solaris \f[V]pmap\f[R]. -.TP -\f[V]--heap\f[R] -Prints the \f[V]java\f[R] heap summary. -.TP -\f[V]--binaryheap\f[R] -Dumps the \f[V]java\f[R] heap in \f[V]hprof\f[R] binary format. -.TP -\f[V]--dumpfile\f[R] \f[I]name\f[R] -The name of the dumpfile. -.TP -\f[V]--histo\f[R] -Prints the histogram of \f[V]java\f[R] object heap. -.TP -\f[V]--clstats\f[R] -Prints the class loader statistics. -.TP -\f[V]--finalizerinfo\f[R] -Prints the information on objects awaiting finalization. -.SH OPTIONS FOR THE JSTACK MODE -.TP -\f[V]--locks\f[R] -Prints the \f[V]java.util.concurrent\f[R] locks information. -.TP -\f[V]--mixed\f[R] -Attempts to print both \f[V]java\f[R] and native frames if the platform -allows it. -.SH OPTIONS FOR THE JSNAP MODE -.TP -\f[V]--all\f[R] -Prints all performance counters. diff --git a/src/jdk.hotspot.agent/share/man/jhsdb.md b/src/jdk.hotspot.agent/share/man/jhsdb.md new file mode 100644 index 00000000000..4c6be775ece --- /dev/null +++ b/src/jdk.hotspot.agent/share/man/jhsdb.md @@ -0,0 +1,186 @@ +--- +# Copyright (c) 2019, 2024, 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. +# + +title: 'JHSDB(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jhsdb - attach to a Java process or launch a postmortem debugger to analyze +the content of a core dump from a crashed Java Virtual Machine (JVM) + +## Synopsis + + **WARNING:** The `debugd` subcommand and `--connect` options are deprecated. They will be removed in a future release. + +`jhsdb` `clhsdb` \[`--pid` *pid* \| `--exe` *executable* `--core` *coredump*\] + +`jhsdb` `hsdb` \[`--pid` *pid* \| `--exe` *executable* `--core` *coredump*\] + +`jhsdb` `debugd` (`--pid` *pid* \| `--exe` *executable* `--core` *coredump*) +\[*options*\] + +`jhsdb` `jstack` (`--pid` *pid* \| `--exe` *executable* `--core` *coredump* \| +`--connect` *\[server-id@\]debugd-host*) \[*options*\] + +`jhsdb` `jmap` (`--pid` *pid* \| `--exe` *executable* `--core` *coredump* \| +`--connect` *\[server-id@\]debugd-host*) \[*options*\] + +`jhsdb` `jinfo` (`--pid` *pid* \| `--exe` *executable* `--core` *coredump* \| +`--connect` *\[server-id@\]debugd-host*) \[*options*\] + +`jhsdb` `jsnap` (`--pid` *pid* \| `--exe` *executable* `--core` *coredump* \| +`--connect` *\[server-id@\]debugd-host*) \[*options*\] + +*pid* +: The process ID to which the `jhsdb` tool should attach. The process must be + a Java process. To get a list of Java processes running on a machine, use + the `ps` command or, if the JVM processes are not running in a separate + docker instance, the [jps](jps.html) command. + +*executable* +: The Java executable file from which the core dump was produced. + +*coredump* +: The core file to which the `jhsdb` tool should attach. + +*\[server-id@\]debugd-host* +: An optional server ID and the address of the remote debug server (debugd). + +*options* +: The command-line options for a `jhsdb` mode. See [Options for the debugd Mode], + [Options for the jstack Mode], [Options for the jmap Mode], + [Options for the jinfo Mode], and [Options for the jsnap Mode]. + +**Note:** + +Either the *pid* or the pair of *executable* and *core* files or +the *\[server-id@\]debugd-host* must be provided for `debugd`, `jstack`, `jmap`, +`jinfo` and `jsnap` modes. + +## Description + +You can use the `jhsdb` tool to attach to a Java process or to launch a +postmortem debugger to analyze the content of a core-dump from a crashed Java +Virtual Machine (JVM). This command is experimental and unsupported. + +**Note:** + +Attaching the `jhsdb` tool to a live process will cause the process to hang and +the process will probably crash when the debugger detaches. + +The `jhsdb` tool can be launched in any one of the following modes: + +`jhsdb clhsdb` +: Starts the interactive command-line debugger. + +`jhsdb hsdb` +: Starts the interactive GUI debugger. + +`jhsdb debugd` +: Starts the remote debug server. + +`jhsdb jstack` +: Prints stack and locks information. + +`jhsdb jmap` +: Prints heap information. + +`jhsdb jinfo` +: Prints basic JVM information. + +`jhsdb jsnap` +: Prints performance counter information. + +`jhsdb` *command* `--help` +: Displays the options available for the *command*. + +## Options for the debugd Mode + +`--serverid` *server-id* +: An optional unique ID for this debug server. This is required if multiple + debug servers are run on the same machine. + +`--rmiport` *port* +: Sets the port number to which the RMI connector is bound. If not specified + a random available port is used. + +`--registryport` *port* +: Sets the RMI registry port. This option overrides the system property + 'sun.jvm.hotspot.rmi.port'. If not specified, the system property is used. + If the system property is not set, the default port 1099 is used. + +`--hostname` *hostname* +: Sets the hostname the RMI connector is bound. The value could be a hostname + or an IPv4/IPv6 address. This option overrides the system property + 'java.rmi.server.hostname'. If not specified, the system property is used. + If the system property is not set, a system hostname is used. + +## Options for the jinfo Mode + +`--flags` +: Prints the VM flags. + +`--sysprops` +: Prints the Java system properties. + +no option +: Prints the VM flags and the Java system properties. + +## Options for the jmap Mode + +no option +: Prints the same information as Solaris `pmap`. + +`--heap` +: Prints the `java` heap summary. + +`--binaryheap` +: Dumps the `java` heap in `hprof` binary format. + +`--dumpfile` *name* +: The name of the dumpfile. + +`--histo` +: Prints the histogram of `java` object heap. + +`--clstats` +: Prints the class loader statistics. + +`--finalizerinfo` +: Prints the information on objects awaiting finalization. + +## Options for the jstack Mode + +`--locks` +: Prints the `java.util.concurrent` locks information. + +`--mixed` +: Attempts to print both `java` and native frames if the platform allows it. + +## Options for the jsnap Mode + +`--all` +: Prints all performance counters. diff --git a/src/jdk.httpserver/share/man/jwebserver.1 b/src/jdk.httpserver/share/man/jwebserver.1 deleted file mode 100644 index 4fbaf9dd09d..00000000000 --- a/src/jdk.httpserver/share/man/jwebserver.1 +++ /dev/null @@ -1,193 +0,0 @@ -.\" Copyright (c) 2021, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JWEBSERVER" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jwebserver - launch the Java Simple Web Server -.SH SYNOPSIS -.PP -\f[V]jwebserver\f[R] [\f[I]options\f[R]] -.TP -\f[I]options\f[R] -Command-line options. -For a detailed description of the options, see \f[B]Options\f[R]. -.SH DESCRIPTION -.PP -The \f[V]jwebserver\f[R] tool provides a minimal HTTP server, designed -to be used for prototyping, testing, and debugging. -It serves a single directory hierarchy, and only serves static files. -Only HTTP/1.1 is supported; HTTP/2 and HTTPS are not supported. -.PP -Only idempotent HEAD and GET requests are served. -Any other requests receive a \f[V]501 - Not Implemented\f[R] or a -\f[V]405 - Not Allowed\f[R] response. -GET requests are mapped to the directory being served, as follows: -.IP \[bu] 2 -If the requested resource is a file, its content is served. -.IP \[bu] 2 -If the requested resource is a directory that contains an index file, -the content of the index file is served. -.IP \[bu] 2 -Otherwise, the names of all files and subdirectories of the directory -are listed. -Symbolic links and hidden files are not listed or served. -.PP -MIME types are configured automatically, using the built-in table. -For example, \f[V].html\f[R] files are served as \f[V]text/html\f[R] and -\f[V].java\f[R] files are served as \f[V]text/plain\f[R]. -.PP -\f[V]jwebserver\f[R] is located in the jdk.httpserver module, and can -alternatively be started with \f[V]java -m jdk.httpserver\f[R]. -It is based on the web server implementation in the -\f[V]com.sun.net.httpserver\f[R] package. -The \f[V]com.sun.net.httpserver.SimpleFileServer\f[R] class provides a -programmatic way to retrieve the server and its components for reuse and -extension. -.SH USAGE -.IP -.nf -\f[CB] -jwebserver [-b bind address] [-p port] [-d directory] - [-o none|info|verbose] [-h to show options] - [-version to show version information] -\f[R] -.fi -.SH OPTIONS -.TP -\f[V]-h\f[R] or \f[V]-?\f[R] or \f[V]--help\f[R] -Prints the help message and exits. -.TP -\f[V]-b\f[R] \f[I]addr\f[R] or \f[V]--bind-address\f[R] \f[I]addr\f[R] -Specifies the address to bind to. -Default: 127.0.0.1 or ::1 (loopback). -For all interfaces use \f[V]-b 0.0.0.0\f[R] or \f[V]-b ::\f[R]. -.TP -\f[V]-d\f[R] \f[I]dir\f[R] or \f[V]--directory\f[R] \f[I]dir\f[R] -Specifies the directory to serve. -Default: current directory. -.TP -\f[V]-o\f[R] \f[I]level\f[R] or \f[V]--output\f[R] \f[I]level\f[R] -Specifies the output format. -\f[V]none\f[R] | \f[V]info\f[R] | \f[V]verbose\f[R]. -Default: \f[V]info\f[R]. -.TP -\f[V]-p\f[R] \f[I]port\f[R] or \f[V]--port\f[R] \f[I]port\f[R] -Specifies the port to listen on. -Default: 8000. -.TP -\f[V]-version\f[R] or \f[V]--version\f[R] -Prints the version information and exits. -.PP -To stop the server, press \f[V]Ctrl + C\f[R]. -.SH STARTING THE SERVER -.PP -The following command starts the Simple Web Server: -.IP -.nf -\f[CB] -$ jwebserver -\f[R] -.fi -.PP -If startup is successful, the server prints a message to -\f[V]System.out\f[R] listing the local address and the absolute path of -the directory being served. -For example: -.IP -.nf -\f[CB] -$ jwebserver -Binding to loopback by default. For all interfaces use \[dq]-b 0.0.0.0\[dq] or \[dq]-b ::\[dq]. -Serving /cwd and subdirectories on 127.0.0.1 port 8000 -URL http://127.0.0.1:8000/ -\f[R] -.fi -.SH CONFIGURATION -.PP -By default, the server runs in the foreground and binds to the loopback -address and port 8000. -This can be changed with the \f[V]-b\f[R] and \f[V]-p\f[R] options. -For example, to bind the Simple Web Server to all interfaces, use: -.IP -.nf -\f[CB] -$ jwebserver -b 0.0.0.0 -Serving /cwd and subdirectories on 0.0.0.0 (all interfaces) port 8000 -URL http://123.456.7.891:8000/ -\f[R] -.fi -.PP -Note that this makes the web server accessible to all hosts on the -network. -\f[I]Do not do this unless you are sure the server cannot leak any -sensitive information.\f[R] -.PP -As another example, use the following command to run on port 9000: -.IP -.nf -\f[CB] -$ jwebserver -p 9000 -\f[R] -.fi -.PP -By default, the files of the current directory are served. -A different directory can be specified with the \f[V]-d\f[R] option. -.PP -By default, every request is logged on the console. -The output looks like this: -.IP -.nf -\f[CB] -127.0.0.1 - - [10/Feb/2021:14:34:11 +0000] \[dq]GET /some/subdirectory/ HTTP/1.1\[dq] 200 - -\f[R] -.fi -.PP -Logging output can be changed with the \f[V]-o\f[R] option. -The default setting is \f[V]info\f[R]. -The \f[V]verbose\f[R] setting additionally includes the request and -response headers as well as the absolute path of the requested resource. -.SH STOPPING THE SERVER -.PP -Once started successfully, the server runs until it is stopped. -On Unix platforms, the server can be stopped by sending it a -\f[V]SIGINT\f[R] signal (\f[V]Ctrl+C\f[R] in a terminal window). -.SH HELP OPTION -.PP -The \f[V]-h\f[R] option displays a help message describing the usage and -the options of the \f[V]jwebserver\f[R]. diff --git a/src/jdk.httpserver/share/man/jwebserver.md b/src/jdk.httpserver/share/man/jwebserver.md new file mode 100644 index 00000000000..352e982654d --- /dev/null +++ b/src/jdk.httpserver/share/man/jwebserver.md @@ -0,0 +1,152 @@ +--- +# Copyright (c) 2021, 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. +# + +title: 'JWEBSERVER(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jwebserver - launch the Java Simple Web Server + +## Synopsis + +`jwebserver` \[*options*\] + +*options* +: Command-line options. For a detailed description of the options, see [Options]. + +## Description +The `jwebserver` tool provides a minimal HTTP server, designed to be used +for prototyping, testing, and debugging. It serves a single directory hierarchy, +and only serves static files. Only HTTP/1.1 is supported; +HTTP/2 and HTTPS are not supported. + +Only idempotent HEAD and GET requests are served. Any other requests receive +a `501 - Not Implemented` or a `405 - Not Allowed` response. GET requests are +mapped to the directory being served, as follows: + +* If the requested resource is a file, its content is served. +* If the requested resource is a directory that contains an index file, +the content of the index file is served. +* Otherwise, the names of all files and subdirectories of the directory are +listed. Symbolic links and hidden files are not listed or served. + +MIME types are configured automatically, using the built-in table. For example, +`.html` files are served as `text/html` and `.java` files are served as +`text/plain`. + +`jwebserver` is located in the jdk.httpserver module, and can alternatively +be started with `java -m jdk.httpserver`. It is based on the web server +implementation in the `com.sun.net.httpserver` package. +The `com.sun.net.httpserver.SimpleFileServer` class provides a programmatic +way to retrieve the server and its components for reuse and extension. + +## Usage +``` +jwebserver [-b bind address] [-p port] [-d directory] + [-o none|info|verbose] [-h to show options] + [-version to show version information] +``` + +## Options + +`-h` or `-?` or `--help` +: Prints the help message and exits. + +`-b` *addr* or `--bind-address` *addr* +: Specifies the address to bind to. + Default: 127.0.0.1 or ::1 (loopback). + For all interfaces use `-b 0.0.0.0` or `-b ::`. + +`-d` *dir* or `--directory` *dir* +: Specifies the directory to serve. + Default: current directory. + +`-o` *level* or `--output` *level* +: Specifies the output format. `none` | `info` | `verbose`. + Default: `info`. + +`-p` *port* or `--port` *port* +: Specifies the port to listen on. + Default: 8000. + +`-version` or `--version` +: Prints the version information and exits. + +To stop the server, press `Ctrl + C`. + +## Starting the Server +The following command starts the Simple Web Server: +``` +$ jwebserver +``` +If startup is successful, the server prints a message to `System.out` +listing the local address and the absolute path of the directory being +served. For example: +``` +$ jwebserver +Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::". +Serving /cwd and subdirectories on 127.0.0.1 port 8000 +URL http://127.0.0.1:8000/ +``` + +## Configuration +By default, the server runs in the foreground and binds to the loopback +address and port 8000. This can be changed with the `-b` and `-p` options. +For example, to bind the Simple Web Server to all interfaces, use: +``` +$ jwebserver -b 0.0.0.0 +Serving /cwd and subdirectories on 0.0.0.0 (all interfaces) port 8000 +URL http://123.456.7.891:8000/ +``` +Note that this makes the web server accessible to all hosts on the network. +*Do not do this unless you are sure the server cannot leak any sensitive +information.* + +As another example, use the following command to run on port 9000: +``` +$ jwebserver -p 9000 +``` + +By default, the files of the current directory are served. A different +directory can be specified with the `-d` option. + +By default, every request is logged on the console. The output looks like +this: +``` +127.0.0.1 - - [10/Feb/2021:14:34:11 +0000] "GET /some/subdirectory/ HTTP/1.1" 200 - +``` +Logging output can be changed with the `-o` option. The default setting is +`info`. The `verbose` setting additionally includes the request and response +headers as well as the absolute path of the requested resource. + +## Stopping the Server +Once started successfully, the server runs until it is stopped. On Unix +platforms, the server can be stopped by sending it a `SIGINT` signal +(`Ctrl+C` in a terminal window). + +## Help Option +The `-h` option displays a help message describing the usage and the options +of the `jwebserver`. diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java index 5a7cdb89dde..f5f5a5a4e7e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java @@ -95,8 +95,7 @@ // Currently Float16 is a value-based class and in future it is // expected to be aligned with Value Classes and Object as described in // JEP-401 (https://openjdk.org/jeps/401). -// @jdk.internal.MigratedValueClass -// @jdk.internal.ValueBased +@jdk.internal.ValueBased public final class Float16 extends Number implements Comparable { @@ -323,7 +322,7 @@ public static Float16 valueOf(long value) { * @param f a {@code float} */ public static Float16 valueOf(float f) { - return new Float16(Float.floatToFloat16(f)); + return new Float16(floatToFloat16(f)); } /** diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java index f40b9662625..11de96b7fc3 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java @@ -98,6 +98,11 @@ public String readln(String prompt) { return getDelegate(true).readln(prompt); } + @Override + public String readln() { + return getDelegate(true).readln(); + } + @Override public JdkConsole format(Locale locale, String format, Object... args) { JdkConsole delegate = getDelegate(false); @@ -224,6 +229,11 @@ public String readln(String prompt) { } } + @Override + public String readln() { + return readLine(); + } + @Override public JdkConsole format(Locale locale, String format, Object ... args) { writer().format(locale, format, args).flush(); @@ -242,7 +252,12 @@ public String readLine(Locale locale, String format, Object ... args) { @Override public String readLine() { - return readLine(Locale.getDefault(Locale.Category.FORMAT), ""); + try { + initJLineIfNeeded(); + return jline.readLine(); + } catch (EndOfFileException eofe) { + return null; + } } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 3fd92f8dee5..616b5a23f64 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -959,7 +959,6 @@ public Map, JVMCIBackend> getJVMCIBackends() { return Collections.unmodifiableMap(backends); } - @SuppressWarnings("try") @VMEntryPoint private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long compileState, int id) { HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, compileState, id); @@ -981,13 +980,11 @@ private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod return hsResult; } - @SuppressWarnings("try") @VMEntryPoint private boolean isGCSupported(int gcIdentifier) { return getCompiler().isGCSupported(gcIdentifier); } - @SuppressWarnings("try") @VMEntryPoint private boolean isIntrinsicSupported(int intrinsicIdentifier) { return getCompiler().isIntrinsicSupported(intrinsicIdentifier); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java index fe268e90476..2b8f717840e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -70,7 +70,6 @@ private static class Audit { */ private Object rawAudit; - @SuppressWarnings("serial") @VMEntryPoint private IndirectHotSpotObjectConstantImpl(long objectHandle, boolean compressed, boolean skipRegister) { super(compressed); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java index f6d365f193b..9e7d7679cab 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java @@ -76,9 +76,6 @@ private static EnumSet computeFlags(RISCV64HotSpotVMConfig config) if (config.useZbb) { flags.add(RISCV64.Flag.UseZbb); } - if (config.useRVVForBigIntegerShiftIntrinsics) { - flags.add(RISCV64.Flag.UseRVVForBigIntegerShiftIntrinsics); - } return flags; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotVMConfig.java index 5af1a4b7796..7f19efc4566 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotVMConfig.java @@ -50,7 +50,6 @@ class RISCV64HotSpotVMConfig extends HotSpotVMConfigAccess { final boolean useRVC = getFlag("UseRVC", Boolean.class); final boolean useZba = getFlag("UseZba", Boolean.class); final boolean useZbb = getFlag("UseZbb", Boolean.class); - final boolean useRVVForBigIntegerShiftIntrinsics = getFlag("UseRVVForBigIntegerShiftIntrinsics", Boolean.class); final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t"); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/AnnotationData.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/AnnotationData.java index 17b6b714ba4..76edb8c83a7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/AnnotationData.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/AnnotationData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -69,7 +69,6 @@ public final class AnnotationData { * @throws NullPointerException if any of the above parameters is null or any entry in * {@code elements} is null */ - @SuppressWarnings({"rawtypes", "unchecked"}) public AnnotationData(JavaType type, Map.Entry[] elements) { this.type = Objects.requireNonNull(type); for (Map.Entry e : elements) { @@ -125,7 +124,6 @@ public JavaType getAnnotationType() { * there was an error parsing or creating the element value */ // @formatter:on - @SuppressWarnings("unchecked") public V get(String name, Class elementType) { Object val = elements.get(name); if (val == null) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/riscv64/RISCV64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/riscv64/RISCV64.java index 91d7b79aad4..2da9d51cca2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/riscv64/RISCV64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/riscv64/RISCV64.java @@ -170,8 +170,7 @@ public enum Flag { UseRVV, UseRVC, UseZba, - UseZbb, - UseRVVForBigIntegerShiftIntrinsics + UseZbb } private final EnumSet flags; diff --git a/src/jdk.jartool/share/man/jar.1 b/src/jdk.jartool/share/man/jar.1 deleted file mode 100644 index a88653753ee..00000000000 --- a/src/jdk.jartool/share/man/jar.1 +++ /dev/null @@ -1,379 +0,0 @@ -.\" Copyright (c) 1997, 2024, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JAR" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jar - create an archive for classes and resources, and manipulate or -restore individual classes or resources from an archive -.SH SYNOPSIS -.PP -\f[V]jar\f[R] [\f[I]OPTION\f[R] ...] -[ [\f[V]--release\f[R] \f[I]VERSION\f[R]] [\f[V]-C\f[R] \f[I]dir\f[R]] -\f[I]files\f[R]] ... -.SH DESCRIPTION -.PP -The \f[V]jar\f[R] command is a general-purpose archiving and compression -tool, based on the ZIP and ZLIB compression formats. -Initially, the \f[V]jar\f[R] command was designed to package Java -applets (not supported since JDK 11) or applications; however, beginning -with JDK 9, users can use the \f[V]jar\f[R] command to create modular -JARs. -For transportation and deployment, it\[aq]s usually more convenient to -package modules as modular JARs. -.PP -The syntax for the \f[V]jar\f[R] command resembles the syntax for the -\f[V]tar\f[R] command. -It has several main operation modes, defined by one of the mandatory -operation arguments. -Other arguments are either options that modify the behavior of the -operation or are required to perform the operation. -.PP -When modules or the components of an application (files, images and -sounds) are combined into a single archive, they can be downloaded by a -Java agent (such as a browser) in a single HTTP transaction, rather than -requiring a new connection for each piece. -This dramatically improves download times. -The \f[V]jar\f[R] command also compresses files, which further improves -download time. -The \f[V]jar\f[R] command also enables individual entries in a file to -be signed so that their origin can be authenticated. -A JAR file can be used as a class path entry, whether or not it\[aq]s -compressed. -.PP -An archive becomes a modular JAR when you include a module descriptor, -\f[V]module-info.class\f[R], in the root of the given directories or in -the root of the \f[V].jar\f[R] archive. -The following operations described in \f[B]Operation Modifiers Valid -Only in Create and Update Modes\f[R] are valid only when creating or -updating a modular jar or updating an existing non-modular jar: -.IP \[bu] 2 -\f[V]--module-version\f[R] -.IP \[bu] 2 -\f[V]--hash-modules\f[R] -.IP \[bu] 2 -\f[V]--module-path\f[R] -.PP -\f[B]Note:\f[R] -.PP -All mandatory or optional arguments for long options are also mandatory -or optional for any corresponding short options. -.SH MAIN OPERATION MODES -.PP -When using the \f[V]jar\f[R] command, you must specify the operation for -it to perform. -You specify the operation mode for the \f[V]jar\f[R] command by -including the appropriate operation arguments described in this section. -You can mix an operation argument with other one-letter options. -Generally the operation argument is the first argument specified on the -command line. -.TP -\f[V]-c\f[R] or \f[V]--create\f[R] -Creates the archive. -.TP -\f[V]-i\f[R] \f[I]FILE\f[R] or \f[V]--generate-index=\f[R]\f[I]FILE\f[R] -Generates index information for the specified JAR file. -This option is deprecated and may be removed in a future release. -.TP -\f[V]-t\f[R] or \f[V]--list\f[R] -Lists the table of contents for the archive. -.TP -\f[V]-u\f[R] or \f[V]--update\f[R] -Updates an existing JAR file. -.TP -\f[V]-x\f[R] or \f[V]--extract\f[R] -Extracts the named (or all) files from the archive. -If a file with the same name appears more than once in the archive, each -copy will be extracted, with later copies overwriting (replacing) -earlier copies unless -k is specified. -.TP -\f[V]-d\f[R] or \f[V]--describe-module\f[R] -Prints the module descriptor or automatic module name. -.SH OPERATION MODIFIERS VALID IN ANY MODE -.PP -You can use the following options to customize the actions of any -operation mode included in the \f[V]jar\f[R] command. -.TP -\f[V]-C\f[R] \f[I]DIR\f[R] -When used with the create operation mode, changes the specified -directory and includes the \f[I]files\f[R] specified at the end of the -command line. -.RS -.PP -\f[V]jar\f[R] [\f[I]OPTION\f[R] ...] -[ [\f[V]--release\f[R] \f[I]VERSION\f[R]] [\f[V]-C\f[R] \f[I]dir\f[R]] -\f[I]files\f[R]] -.PP -When used with the extract operation mode, specifies the destination -directory where the JAR file will be extracted. -Unlike with the create operation mode, this option can be specified only -once with the extract operation mode. -.RE -.TP -\f[V]-f\f[R] \f[I]FILE\f[R] or \f[V]--file=\f[R]\f[I]FILE\f[R] -Specifies the archive file name. -.TP -\f[V]--release\f[R] \f[I]VERSION\f[R] -Creates a multirelease JAR file. -Places all files specified after the option into a versioned directory -of the JAR file named -\f[V]META-INF/versions/\f[R]\f[I]VERSION\f[R]\f[V]/\f[R], where -\f[I]VERSION\f[R] must be must be a positive integer whose value is 9 or -greater. -.RS -.PP -At run time, where more than one version of a class exists in the JAR, -the JDK will use the first one it finds, searching initially in the -directory tree whose \f[I]VERSION\f[R] number matches the JDK\[aq]s -major version number. -It will then look in directories with successively lower -\f[I]VERSION\f[R] numbers, and finally look in the root of the JAR. -.RE -.TP -\f[V]-v\f[R] or \f[V]--verbose\f[R] -Sends or prints verbose output to standard output. -.SH OPERATION MODIFIERS VALID ONLY IN CREATE AND UPDATE MODES -.PP -You can use the following options to customize the actions of the create -and the update main operation modes: -.TP -\f[V]-e\f[R] \f[I]CLASSNAME\f[R] or \f[V]--main-class=\f[R]\f[I]CLASSNAME\f[R] -Specifies the application entry point for standalone applications -bundled into a modular or executable modular JAR file. -.TP -\f[V]-m\f[R] \f[I]FILE\f[R] or \f[V]--manifest=\f[R]\f[I]FILE\f[R] -Includes the manifest information from the given manifest file. -.TP -\f[V]-M\f[R] or \f[V]--no-manifest\f[R] -Doesn\[aq]t create a manifest file for the entries. -.TP -\f[V]--module-version=\f[R]\f[I]VERSION\f[R] -Specifies the module version, when creating or updating a modular JAR -file, or updating a non-modular JAR file. -.TP -\f[V]--hash-modules=\f[R]\f[I]PATTERN\f[R] -Computes and records the hashes of modules matched by the given pattern -and that depend upon directly or indirectly on a modular JAR file being -created or a non-modular JAR file being updated. -.TP -\f[V]-p\f[R] or \f[V]--module-path\f[R] -Specifies the location of module dependence for generating the hash. -.TP -\f[V]\[at]\f[R]\f[I]file\f[R] -Reads \f[V]jar\f[R] options and file names from a text file as if they -were supplied on the command line -.SH OPERATION MODIFIERS VALID ONLY IN CREATE, UPDATE, AND GENERATE-INDEX MODES -.PP -You can use the following options to customize the actions of the create -(\f[V]-c\f[R] or \f[V]--create\f[R]) the update (\f[V]-u\f[R] or -\f[V]--update\f[R] ) and the generate-index (\f[V]-i\f[R] or -\f[V]--generate-index=\f[R]\f[I]FILE\f[R]) main operation modes: -.TP -\f[V]-0\f[R] or \f[V]--no-compress\f[R] -Stores without using ZIP compression. -.TP -\f[V]--date=\f[R]\f[I]TIMESTAMP\f[R] -The timestamp in ISO-8601 extended offset date-time with optional -time-zone format, to use for the timestamp of the entries, e.g. -\[dq]2022-02-12T12:30:00-05:00\[dq]. -.SH OPERATION MODIFIERS VALID ONLY IN EXTRACT MODE -.TP -\f[V]--dir\f[R] \f[I]DIR\f[R] -Directory into which the JAR file will be extracted. -.TP -\f[V]-k\f[R] or \f[V]--keep-old-files\f[R] -Do not overwrite existing files. -If a Jar file entry with the same name exists in the target directory, -the existing file will not be overwritten. -As a result, if a file appears more than once in an archive, later -copies will not overwrite earlier copies. -Also note that some file system can be case insensitive. -.SH OTHER OPTIONS -.PP -The following options are recognized by the \f[V]jar\f[R] command and -not used with operation modes: -.TP -\f[V]-h\f[R] or \f[V]--help\f[R][\f[V]:compat\f[R]] -Displays the command-line help for the \f[V]jar\f[R] command or -optionally the compatibility help. -.TP -\f[V]--help-extra\f[R] -Displays help on extra options. -.TP -\f[V]--version\f[R] -Prints the program version. -.SH EXAMPLES OF JAR COMMAND SYNTAX -.IP \[bu] 2 -Create an archive, \f[V]classes.jar\f[R], that contains two class files, -\f[V]Foo.class\f[R] and \f[V]Bar.class\f[R]. -.RS 2 -.RS -.PP -\f[V]jar --create --file classes.jar Foo.class Bar.class\f[R] -.RE -.RE -.IP \[bu] 2 -Create an archive, \f[V]classes.jar\f[R], that contains two class files, -\f[V]Foo.class\f[R] and \f[V]Bar.class\f[R] setting the last modified -date and time to \f[V]2021 Jan 6 12:36:00\f[R]. -.RS 2 -.RS -.PP -\f[V]jar --create --date=\[dq]2021-01-06T14:36:00+02:00\[dq] --file=classes.jar Foo.class Bar.class\f[R] -.RE -.RE -.IP \[bu] 2 -Create an archive, \f[V]classes.jar\f[R], by using an existing manifest, -\f[V]mymanifest\f[R], that contains all of the files in the directory -\f[V]foo/\f[R]. -.RS 2 -.RS -.PP -\f[V]jar --create --file classes.jar --manifest mymanifest -C foo/\f[R] -.RE -.RE -.IP \[bu] 2 -Create a modular JAR archive,\f[V]foo.jar\f[R], where the module -descriptor is located in \f[V]classes/module-info.class\f[R]. -.RS 2 -.RS -.PP -\f[V]jar --create --file foo.jar --main-class com.foo.Main --module-version 1.0 -C foo/classes resources\f[R] -.RE -.RE -.IP \[bu] 2 -Update an existing non-modular JAR, \f[V]foo.jar\f[R], to a modular JAR -file. -.RS 2 -.RS -.PP -\f[V]jar --update --file foo.jar --main-class com.foo.Main --module-version 1.0 -C foo/module-info.class\f[R] -.RE -.RE -.IP \[bu] 2 -Create a versioned or multi-release JAR, \f[V]foo.jar\f[R], that places -the files in the \f[V]classes\f[R] directory at the root of the JAR, and -the files in the \f[V]classes-10\f[R] directory in the -\f[V]META-INF/versions/10\f[R] directory of the JAR. -.RS 2 -.PP -In this example, the \f[V]classes/com/foo\f[R] directory contains two -classes, \f[V]com.foo.Hello\f[R] (the entry point class) and -\f[V]com.foo.NameProvider\f[R], both compiled for JDK 8. -The \f[V]classes-10/com/foo\f[R] directory contains a different version -of the \f[V]com.foo.NameProvider\f[R] class, this one containing JDK 10 -specific code and compiled for JDK 10. -.PP -Given this setup, create a multirelease JAR file \f[V]foo.jar\f[R] by -running the following command from the directory containing the -directories \f[V]classes\f[R] and \f[V]classes-10\f[R] . -.RS -.PP -\f[V]jar --create --file foo.jar --main-class com.foo.Hello -C classes . --release 10 -C classes-10 .\f[R] -.RE -.PP -The JAR file \f[V]foo.jar\f[R] now contains: -.IP -.nf -\f[CB] -% jar -tf foo.jar - -META-INF/ -META-INF/MANIFEST.MF -com/ -com/foo/ -com/foo/Hello.class -com/foo/NameProvider.class -META-INF/versions/10/com/ -META-INF/versions/10/com/foo/ -META-INF/versions/10/com/foo/NameProvider.class -\f[R] -.fi -.PP -As well as other information, the file \f[V]META-INF/MANIFEST.MF\f[R], -will contain the following lines to indicate that this is a multirelease -JAR file with an entry point of \f[V]com.foo.Hello\f[R]. -.IP -.nf -\f[CB] -\&... -Main-Class: com.foo.Hello -Multi-Release: true -\f[R] -.fi -.PP -Assuming that the \f[V]com.foo.Hello\f[R] class calls a method on the -\f[V]com.foo.NameProvider\f[R] class, running the program using JDK 10 -will ensure that the \f[V]com.foo.NameProvider\f[R] class is the one in -\f[V]META-INF/versions/10/com/foo/\f[R]. -Running the program using JDK 8 will ensure that the -\f[V]com.foo.NameProvider\f[R] class is the one at the root of the JAR, -in \f[V]com/foo\f[R]. -.RE -.IP \[bu] 2 -Create an archive, \f[V]my.jar\f[R], by reading options and lists of -class files from the file \f[V]classes.list\f[R]. -.RS 2 -.PP -\f[B]Note:\f[R] -.PP -To shorten or simplify the \f[V]jar\f[R] command, you can provide an arg -file that lists the files to include in the JAR file and pass it to the -\f[V]jar\f[R] command with the at sign (\f[V]\[at]\f[R]) as a prefix. -.RS -.PP -\f[V]jar --create --file my.jar \[at]classes.list\f[R] -.RE -.PP -If one or more entries in the arg file cannot be found then the jar -command fails without creating the JAR file. -.RE -.IP \[bu] 2 -Extract the JAR file \f[V]foo.jar\f[R] to \f[V]/tmp/bar/\f[R] directory: -.RS 2 -.RS -.PP -\f[V]jar -xf foo.jar -C /tmp/bar/\f[R] -.RE -.PP -Alternatively, you can also do: -.RS -.PP -\f[V]jar --extract --file foo.jar --dir /tmp/bar/\f[R] -.RE -.RE diff --git a/src/jdk.jartool/share/man/jar.md b/src/jdk.jartool/share/man/jar.md new file mode 100644 index 00000000000..709786fe89b --- /dev/null +++ b/src/jdk.jartool/share/man/jar.md @@ -0,0 +1,313 @@ +--- +# Copyright (c) 1997, 2024, 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. +# + +title: 'JAR(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jar - create an archive for classes and resources, and manipulate or restore +individual classes or resources from an archive + +## Synopsis + +`jar` \[*OPTION* ...\] \[ \[`--release` *VERSION*\] \[`-C` *dir*\] *files*\] +... + +## Description + +The `jar` command is a general-purpose archiving and compression tool, based on +the ZIP and ZLIB compression formats. Initially, the `jar` command was designed +to package Java applets (not supported since JDK 11) or applications; however, +beginning with JDK 9, users can use the `jar` command to create modular JARs. +For transportation and deployment, it's usually more convenient to package +modules as modular JARs. + +The syntax for the `jar` command resembles the syntax for the `tar` command. It +has several main operation modes, defined by one of the mandatory operation +arguments. Other arguments are either options that modify the behavior of the +operation or are required to perform the operation. + +When modules or the components of an application (files, images and sounds) are +combined into a single archive, they can be downloaded by a Java agent (such as +a browser) in a single HTTP transaction, rather than requiring a new connection +for each piece. This dramatically improves download times. The `jar` command +also compresses files, which further improves download time. The `jar` command +also enables individual entries in a file to be signed so that their origin can +be authenticated. A JAR file can be used as a class path entry, whether or not +it's compressed. + +An archive becomes a modular JAR when you include a module descriptor, +`module-info.class`, in the root of the given directories or in the root of +the `.jar` archive. The following operations described in [Operation Modifiers +Valid Only in Create and Update Modes] are valid only when creating or +updating a modular jar or updating an existing non-modular jar: + +- `--module-version` + +- `--hash-modules` + +- `--module-path` + +**Note:** + +All mandatory or optional arguments for long options are also mandatory or +optional for any corresponding short options. + +## Main Operation Modes + +When using the `jar` command, you must specify the operation for it to perform. +You specify the operation mode for the `jar` command by including the +appropriate operation arguments described in this section. You can mix an +operation argument with other one-letter options. Generally the operation +argument is the first argument specified on the command line. + +`-c` or `--create` +: Creates the archive. + +`-i` *FILE* or `--generate-index=`*FILE* +: Generates index information for the specified JAR file. This option is deprecated + and may be removed in a future release. + +`-t` or `--list` +: Lists the table of contents for the archive. + +`-u` or `--update` +: Updates an existing JAR file. + +`-x` or `--extract` +: Extracts the named (or all) files from the archive. + If a file with the same name appears more than once in + the archive, each copy will be extracted, with later copies + overwriting (replacing) earlier copies unless -k is specified. + +`-d` or `--describe-module` +: Prints the module descriptor or automatic module name. + +## Operation Modifiers Valid in Any Mode + +You can use the following options to customize the actions of any operation +mode included in the `jar` command. + +`-C` *DIR* +: When used with the create operation mode, changes the specified directory + and includes the *files* specified at the end of the command line. + + `jar` \[*OPTION* ...\] \[ \[`--release` *VERSION*\] \[`-C` *dir*\] + *files*\] + + When used with the extract operation mode, specifies the destination directory + where the JAR file will be extracted. Unlike with the create operation mode, + this option can be specified only once with the extract operation mode. + +`-f` *FILE* or `--file=`*FILE* +: Specifies the archive file name. + +`--release` *VERSION* +: Creates a multirelease JAR file. Places all files specified after the + option into a versioned directory of the JAR file named + `META-INF/versions/`*VERSION*`/`, where *VERSION* must be must be a + positive integer whose value is 9 or greater. + + At run time, where more than one version of a class exists in the JAR, the + JDK will use the first one it finds, searching initially in the directory + tree whose *VERSION* number matches the JDK's major version number. It will + then look in directories with successively lower *VERSION* numbers, and + finally look in the root of the JAR. + +`-v` or `--verbose` +: Sends or prints verbose output to standard output. + +## Operation Modifiers Valid Only in Create and Update Modes + +You can use the following options to customize the actions of the create and +the update main operation modes: + +`-e` *CLASSNAME* or `--main-class=`*CLASSNAME* +: Specifies the application entry point for standalone applications bundled + into a modular or executable modular JAR file. + +`-m` *FILE* or `--manifest=`*FILE* +: Includes the manifest information from the given manifest file. + +`-M` or `--no-manifest` +: Doesn't create a manifest file for the entries. + +`--module-version=`*VERSION* +: Specifies the module version, when creating or updating a modular JAR file, + or updating a non-modular JAR file. + +`--hash-modules=`*PATTERN* +: Computes and records the hashes of modules matched by the given pattern and + that depend upon directly or indirectly on a modular JAR file being created + or a non-modular JAR file being updated. + +`-p` or `--module-path` +: Specifies the location of module dependence for generating the hash. + +`@`*file* +: Reads `jar` options and file names from a text file as if they were supplied +on the command line + +## Operation Modifiers Valid Only in Create, Update, and Generate-index Modes + +You can use the following options to customize the actions of the create (`-c` +or `--create`) the update (`-u` or `--update` ) and the generate-index (`-i` or +`--generate-index=`*FILE*) main operation modes: + +`-0` or `--no-compress` +: Stores without using ZIP compression. + +`--date=`*TIMESTAMP* +: The timestamp in ISO-8601 extended offset date-time with optional time-zone + format, to use for the timestamp of the entries, + e.g. "2022-02-12T12:30:00-05:00". + +## Operation Modifiers Valid Only in Extract Mode + +`--dir` *DIR* +: Directory into which the JAR file will be extracted. + +`-k` or `--keep-old-files` +: Do not overwrite existing files. + If a Jar file entry with the same name exists in the target directory, the + existing file will not be overwritten. + As a result, if a file appears more than once in an archive, later copies will not overwrite + earlier copies. + Also note that some file system can be case insensitive. + +## Other Options + +The following options are recognized by the `jar` command and not used with +operation modes: + +`-h` or `--help`\[`:compat`\] +: Displays the command-line help for the `jar` command or optionally the + compatibility help. + +`--help-extra` +: Displays help on extra options. + +`--version` +: Prints the program version. + +## Examples of jar Command Syntax + +- Create an archive, `classes.jar`, that contains two class files, + `Foo.class` and `Bar.class`. + + > `jar --create --file classes.jar Foo.class Bar.class` + +- Create an archive, `classes.jar`, that contains two class files, + `Foo.class` and `Bar.class` setting the last modified date and time to `2021 Jan 6 12:36:00`. + + > `jar --create --date="2021-01-06T14:36:00+02:00" --file=classes.jar Foo.class Bar.class` + +- Create an archive, `classes.jar`, by using an existing manifest, + `mymanifest`, that contains all of the files in the directory `foo/`. + + > `jar --create --file classes.jar --manifest mymanifest -C foo/` + +- Create a modular JAR archive,`foo.jar`, where the module descriptor is + located in `classes/module-info.class`. + + > `jar --create --file foo.jar --main-class com.foo.Main + --module-version 1.0 -C foo/classes resources` + +- Update an existing non-modular JAR, `foo.jar`, to a modular JAR file. + + > `jar --update --file foo.jar --main-class com.foo.Main + --module-version 1.0 -C foo/module-info.class` + +- Create a versioned or multi-release JAR, `foo.jar`, that places the files + in the `classes` directory at the root of the JAR, and the files in the + `classes-10` directory in the `META-INF/versions/10` directory of the JAR. + + In this example, the `classes/com/foo` directory contains two classes, + `com.foo.Hello` (the entry point class) and `com.foo.NameProvider`, both + compiled for JDK 8. The `classes-10/com/foo` directory contains a different + version of the `com.foo.NameProvider` class, this one containing JDK 10 + specific code and compiled for JDK 10. + + Given this setup, create a multirelease JAR file `foo.jar` by running the + following command from the directory containing the directories `classes` + and `classes-10` . + + > `jar --create --file foo.jar --main-class com.foo.Hello -C classes . + --release 10 -C classes-10 .` + + The JAR file `foo.jar` now contains: + + ``` + % jar -tf foo.jar + + META-INF/ + META-INF/MANIFEST.MF + com/ + com/foo/ + com/foo/Hello.class + com/foo/NameProvider.class + META-INF/versions/10/com/ + META-INF/versions/10/com/foo/ + META-INF/versions/10/com/foo/NameProvider.class + ``` + + As well as other information, the file `META-INF/MANIFEST.MF`, will contain + the following lines to indicate that this is a multirelease JAR file with + an entry point of `com.foo.Hello`. + + ``` + ... + Main-Class: com.foo.Hello + Multi-Release: true + ``` + + Assuming that the `com.foo.Hello` class calls a method on the + `com.foo.NameProvider` class, running the program using JDK 10 will ensure + that the `com.foo.NameProvider` class is the one in + `META-INF/versions/10/com/foo/`. Running the program using JDK 8 will + ensure that the `com.foo.NameProvider` class is the one at the root of the + JAR, in `com/foo`. + +- Create an archive, `my.jar`, by reading options and lists of class files + from the file `classes.list`. + + **Note:** + + To shorten or simplify the `jar` command, you can provide an arg file that lists + the files to include in the JAR file and pass it to the `jar` command with the at sign (`@`) + as a prefix. + + > `jar --create --file my.jar @classes.list` + + If one or more entries in the arg file cannot be found then the jar command fails without creating the JAR file. + +- Extract the JAR file `foo.jar` to `/tmp/bar/` directory: + + > `jar -xf foo.jar -C /tmp/bar/` + + Alternatively, you can also do: + + > `jar --extract --file foo.jar --dir /tmp/bar/` diff --git a/src/jdk.jartool/share/man/jarsigner.1 b/src/jdk.jartool/share/man/jarsigner.1 deleted file mode 100644 index d085efcfcd0..00000000000 --- a/src/jdk.jartool/share/man/jarsigner.1 +++ /dev/null @@ -1,1395 +0,0 @@ -.\" Copyright (c) 1998, 2023, 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. -.\" -'\" t -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JARSIGNER" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jarsigner - sign and verify Java Archive (JAR) files -.SH SYNOPSIS -.PP -\f[V]jarsigner\f[R] [\f[I]options\f[R]] \f[I]jar-file\f[R] -\f[I]alias\f[R] -.PP -\f[V]jarsigner\f[R] \f[V]-verify\f[R] [\f[I]options\f[R]] -\f[I]jar-file\f[R] [\f[I]alias\f[R] ...] -.PP -\f[V]jarsigner\f[R] \f[V]-version\f[R] -.TP -\f[I]options\f[R] -The command-line options. -See \f[B]Options for jarsigner\f[R]. -.TP -\f[V]-verify\f[R] -The \f[V]-verify\f[R] option can take zero or more keystore alias names -after the JAR file name. -When the \f[V]-verify\f[R] option is specified, the \f[V]jarsigner\f[R] -command checks that the certificate used to verify each signed entry in -the JAR file matches one of the keystore aliases. -The aliases are defined in the keystore specified by \f[V]-keystore\f[R] -or the default keystore. -.RS -.PP -If you also specify the \f[V]-strict\f[R] option, and the -\f[V]jarsigner\f[R] command detects severe warnings, the message, -\[dq]jar verified, with signer errors\[dq] is displayed. -.RE -.TP -\f[I]jar-file\f[R] -The JAR file to be signed. -.RS -.PP -If you also specified the \f[V]-strict\f[R] option, and the -\f[V]jarsigner\f[R] command detected severe warnings, the message, -\[dq]jar signed, with signer errors\[dq] is displayed. -.RE -.TP -\f[I]alias\f[R] -The aliases are defined in the keystore specified by \f[V]-keystore\f[R] -or the default keystore. -.TP -\f[V]-version\f[R] -The \f[V]-version\f[R] option prints the program version of -\f[V]jarsigner\f[R]. -.SH DESCRIPTION -.PP -The \f[V]jarsigner\f[R] tool has two purposes: -.IP \[bu] 2 -To sign Java Archive (JAR) files. -.IP \[bu] 2 -To verify the signatures and integrity of signed JAR files. -.PP -The JAR feature enables the packaging of class files, images, sounds, -and other digital data in a single file for faster and easier -distribution. -A tool named \f[V]jar\f[R] enables developers to produce JAR files. -(Technically, any ZIP file can also be considered a JAR file, although -when created by the \f[V]jar\f[R] command or processed by the -\f[V]jarsigner\f[R] command, JAR files also contain a -\f[V]META-INF/MANIFEST.MF\f[R] file.) -.PP -A digital signature is a string of bits that is computed from some data -(the data being signed) and the private key of an entity (a person, -company, and so on). -Similar to a handwritten signature, a digital signature has many useful -characteristics: -.IP \[bu] 2 -Its authenticity can be verified by a computation that uses the public -key corresponding to the private key used to generate the signature. -.IP \[bu] 2 -It can\[aq]t be forged, assuming the private key is kept secret. -.IP \[bu] 2 -It is a function of the data signed and thus can\[aq]t be claimed to be -the signature for other data as well. -.IP \[bu] 2 -The signed data can\[aq]t be changed. -If the data is changed, then the signature can\[aq]t be verified as -authentic. -.PP -To generate an entity\[aq]s signature for a file, the entity must first -have a public/private key pair associated with it and one or more -certificates that authenticate its public key. -A certificate is a digitally signed statement from one entity that says -that the public key of another entity has a particular value. -.PP -The \f[V]jarsigner\f[R] command uses key and certificate information -from a keystore to generate digital signatures for JAR files. -A keystore is a database of private keys and their associated X.509 -certificate chains that authenticate the corresponding public keys. -The \f[V]keytool\f[R] command is used to create and administer -keystores. -.PP -The \f[V]jarsigner\f[R] command uses an entity\[aq]s private key to -generate a signature. -The signed JAR file contains, among other things, a copy of the -certificate from the keystore for the public key corresponding to the -private key used to sign the file. -The \f[V]jarsigner\f[R] command can verify the digital signature of the -signed JAR file using the certificate inside it (in its signature block -file). -.PP -The \f[V]jarsigner\f[R] command can generate signatures that include a -time stamp that enables a systems or deployer to check whether the JAR -file was signed while the signing certificate was still valid. -.PP -In addition, APIs allow applications to obtain the timestamp -information. -.PP -At this time, the \f[V]jarsigner\f[R] command can only sign JAR files -created by the \f[V]jar\f[R] command or zip files. -JAR files are the same as zip files, except they also have a -\f[V]META-INF/MANIFEST.MF\f[R] file. -A \f[V]META-INF/MANIFEST.MF\f[R] file is created when the -\f[V]jarsigner\f[R] command signs a zip file. -.PP -The default \f[V]jarsigner\f[R] command behavior is to sign a JAR or zip -file. -Use the \f[V]-verify\f[R] option to verify a signed JAR file. -.PP -The \f[V]jarsigner\f[R] command also attempts to validate the -signer\[aq]s certificate after signing or verifying. -During validation, it checks the revocation status of each certificate -in the signer\[aq]s certificate chain when the \f[V]-revCheck\f[R] -option is specified. -If there is a validation error or any other problem, the command -generates warning messages. -If you specify the \f[V]-strict\f[R] option, then the command treats -severe warnings as errors. -See \f[B]Errors and Warnings\f[R]. -.SH KEYSTORE ALIASES -.PP -All keystore entities are accessed with unique aliases. -.PP -When you use the \f[V]jarsigner\f[R] command to sign a JAR file, you -must specify the alias for the keystore entry that contains the private -key needed to generate the signature. -If no output file is specified, it overwrites the original JAR file with -the signed JAR file. -.PP -Keystores are protected with a password, so the store password must be -specified. -You are prompted for it when you don\[aq]t specify it on the command -line. -Similarly, private keys are protected in a keystore with a password, so -the private key\[aq]s password must be specified, and you are prompted -for the password when you don\[aq]t specify it on the command line and -it isn\[aq]t the same as the store password. -.SH KEYSTORE LOCATION -.PP -The \f[V]jarsigner\f[R] command has a \f[V]-keystore\f[R] option for -specifying the URL of the keystore to be used. -The keystore is by default stored in a file named \f[V].keystore\f[R] in -the user\[aq]s home directory, as determined by the \f[V]user.home\f[R] -system property. -.PP -\f[B]Linux and macOS:\f[R] \f[V]user.home\f[R] defaults to the -user\[aq]s home directory. -.PP -The input stream from the \f[V]-keystore\f[R] option is passed to the -\f[V]KeyStore.load\f[R] method. -If \f[V]NONE\f[R] is specified as the URL, then a null stream is passed -to the \f[V]KeyStore.load\f[R] method. -\f[V]NONE\f[R] should be specified when the \f[V]KeyStore\f[R] class -isn\[aq]t file based, for example, when it resides on a hardware token -device. -.SH KEYSTORE IMPLEMENTATION -.PP -The \f[V]KeyStore\f[R] class provided in the \f[V]java.security\f[R] -package supplies a number of well-defined interfaces to access and -modify the information in a keystore. -You can have multiple different concrete implementations, where each -implementation is for a particular type of keystore. -.PP -Currently, there are two command-line tools that use keystore -implementations (\f[V]keytool\f[R] and \f[V]jarsigner\f[R]). -.PP -The default keystore implementation is \f[V]PKCS12\f[R]. -This is a cross platform keystore based on the RSA PKCS12 Personal -Information Exchange Syntax Standard. -This standard is primarily meant for storing or transporting a -user\[aq]s private keys, certificates, and miscellaneous secrets. -There is another built-in implementation, provided by Oracle. -It implements the keystore as a file with a proprietary keystore type -(format) named \f[V]JKS\f[R]. -It protects each private key with its individual password, and also -protects the integrity of the entire keystore with a (possibly -different) password. -.PP -Keystore implementations are provider-based, which means the application -interfaces supplied by the \f[V]KeyStore\f[R] class are implemented in -terms of a Service Provider Interface (SPI). -There is a corresponding abstract \f[V]KeystoreSpi\f[R] class, also in -the \f[V]java.security package\f[R], that defines the Service Provider -Interface methods that providers must implement. -The term provider refers to a package or a set of packages that supply a -concrete implementation of a subset of services that can be accessed by -the Java Security API. -To provide a keystore implementation, clients must implement a provider -and supply a \f[V]KeystoreSpi\f[R] subclass implementation, as described -in \f[B]How to Implement a Provider in the Java Cryptography -Architecture\f[R] -[https://www.oracle.com/pls/topic/lookup?ctx=en/java/javase&id=security_guide_implement_provider_jca]. -.PP -Applications can choose different types of keystore implementations from -different providers, with the \f[V]getInstance\f[R] factory method in -the \f[V]KeyStore\f[R] class. -A keystore type defines the storage and data format of the keystore -information and the algorithms used to protect private keys in the -keystore and the integrity of the keystore itself. -Keystore implementations of different types aren\[aq]t compatible. -.PP -The \f[V]jarsigner\f[R] commands can read file-based keystores from any -location that can be specified using a URL. -In addition, these commands can read non-file-based keystores such as -those provided by MSCAPI on Windows and PKCS11 on all platforms. -.PP -For the \f[V]jarsigner\f[R] and \f[V]keytool\f[R] commands, you can -specify a keystore type at the command line with the -\f[V]-storetype\f[R] option. -.PP -If you don\[aq]t explicitly specify a keystore type, then the tools -choose a keystore implementation based on the value of the -\f[V]keystore.type\f[R] property specified in the security properties -file. -The security properties file is called \f[V]java.security\f[R], and it -resides in the JDK security properties directory, -\f[V]java.home/conf/security\f[R]. -.PP -Each tool gets the \f[V]keystore.type\f[R] value and then examines all -the installed providers until it finds one that implements keystores of -that type. -It then uses the keystore implementation from that provider. -.PP -The \f[V]KeyStore\f[R] class defines a static method named -\f[V]getDefaultType\f[R] that lets applications retrieve the value of -the \f[V]keystore.type\f[R] property. -The following line of code creates an instance of the default keystore -type as specified in the \f[V]keystore.type\f[R] property: -.RS -.PP -\f[V]KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());\f[R] -.RE -.PP -The default keystore type is \f[V]pkcs12\f[R], which is a cross platform -keystore based on the RSA PKCS12 Personal Information Exchange Syntax -Standard. -This is specified by the following line in the security properties file: -.RS -.PP -\f[V]keystore.type=pkcs12\f[R] -.RE -.PP -Case doesn\[aq]t matter in keystore type designations. -For example, \f[V]JKS\f[R] is the same as \f[V]jks\f[R]. -.PP -To have the tools utilize a keystore implementation other than the -default, you can change that line to specify a different keystore type. -For example, if you want to use the Oracle\[aq]s \f[V]jks\f[R] keystore -implementation, then change the line to the following: -.RS -.PP -\f[V]keystore.type=jks\f[R] -.RE -.SH SUPPORTED ALGORITHMS -.PP -By default, the \f[V]jarsigner\f[R] command signs a JAR file using one -of the following algorithms and block file extensions depending on the -type and size of the private key: -.PP -Default Signature Algorithms and Block File Extensions -.TS -tab(@); -l l l l. -T{ -keyalg -T}@T{ -key size -T}@T{ -default sigalg -T}@T{ -block file extension -T} -_ -T{ -DSA -T}@T{ -any size -T}@T{ -SHA256withDSA -T}@T{ -\&.DSA -T} -T{ -RSA -T}@T{ -< 624 -T}@T{ -SHA256withRSA -T}@T{ -\&.RSA -T} -T{ -T}@T{ -<= 7680 -T}@T{ -SHA384withRSA -T}@T{ -T} -T{ -T}@T{ -> 7680 -T}@T{ -SHA512withRSA -T}@T{ -T} -T{ -EC -T}@T{ -< 512 -T}@T{ -SHA384withECDSA -T}@T{ -\&.EC -T} -T{ -T}@T{ ->= 512 -T}@T{ -SHA512withECDSA -T}@T{ -T} -T{ -RSASSA-PSS -T}@T{ -< 624 -T}@T{ -RSASSA-PSS (with SHA-256) -T}@T{ -\&.RSA -T} -T{ -T}@T{ -<= 7680 -T}@T{ -RSASSA-PSS (with SHA-384) -T}@T{ -T} -T{ -T}@T{ -> 7680 -T}@T{ -RSASSA-PSS (with SHA-512) -T}@T{ -T} -T{ -EdDSA -T}@T{ -255 -T}@T{ -Ed25519 -T}@T{ -\&.EC -T} -T{ -T}@T{ -448 -T}@T{ -Ed448 -T}@T{ -T} -.TE -.IP \[bu] 2 -If an RSASSA-PSS key is encoded with parameters, then jarsigner will use -the same parameters in the signature. -Otherwise, jarsigner will use parameters that are determined by the size -of the key as specified in the table above. -For example, an 3072-bit RSASSA-PSS key will use RSASSA-PSS as the -signature algorithm and SHA-384 as the hash and MGF1 algorithms. -.IP \[bu] 2 -If a key algorithm is not listed in this table, the \f[V].DSA\f[R] -extension is used when signing a JAR file. -.PP -These default signature algorithms can be overridden by using the -\f[V]-sigalg\f[R] option. -.PP -The \f[V]jarsigner\f[R] command uses the -\f[V]jdk.jar.disabledAlgorithms\f[R] and -\f[V]jdk.security.legacyAlgorithms\f[R] security properties to determine -which algorithms are considered a security risk. -If the JAR file was signed with any algorithms that are disabled, it -will be treated as an unsigned JAR file. -If the JAR file was signed with any legacy algorithms, it will be -treated as signed with an informational warning to inform users that the -legacy algorithm will be disabled in a future update. -For detailed verification output, include -\f[V]-J-Djava.security.debug=jar\f[R]. -The \f[V]jdk.jar.disabledAlgorithms\f[R] and -\f[V]jdk.security.legacyAlgorithms\f[R] security properties are defined -in the \f[V]java.security\f[R] file (located in the JDK\[aq]s -\f[V]$JAVA_HOME/conf/security\f[R] directory). -.PP -\f[B]Note:\f[R] -.PP -In order to improve out of the box security, default key size and -signature algorithm names are periodically updated to stronger values -with each release of the JDK. -If interoperability with older releases of the JDK is important, please -make sure the defaults are supported by those releases, or alternatively -use the \f[V]-sigalg\f[R] option to override the default values at your -own risk. -.SH THE SIGNED JAR FILE -.PP -When the \f[V]jarsigner\f[R] command is used to sign a JAR file, the -output signed JAR file is exactly the same as the input JAR file, except -that it has two additional files placed in the META-INF directory: -.IP \[bu] 2 -A signature file with an \f[V].SF\f[R] extension -.IP \[bu] 2 -A signature block file with a \f[V].DSA\f[R], \f[V].RSA\f[R], or -\f[V].EC\f[R] extension -.PP -The base file names for these two files come from the value of the -\f[V]-sigfile\f[R] option. -For example, when the option is \f[V]-sigfile MKSIGN\f[R], the files are -named \f[V]MKSIGN.SF\f[R] and \f[V]MKSIGN.RSA\f[R]. -In this document, we assume the signer always uses an RSA key. -.PP -If no \f[V]-sigfile\f[R] option appears on the command line, then the -base file name for the \f[V].SF\f[R] and the signature block files is -the first 8 characters of the alias name specified on the command line, -all converted to uppercase. -If the alias name has fewer than 8 characters, then the full alias name -is used. -If the alias name contains any characters that aren\[aq]t allowed in a -signature file name, then each such character is converted to an -underscore (_) character in forming the file name. -Valid characters include letters, digits, underscores, and hyphens. -.SH SIGNATURE FILE -.PP -A signature file (\f[V].SF\f[R] file) looks similar to the manifest file -that is always included in a JAR file when the \f[V]jarsigner\f[R] -command is used to sign the file. -For each source file included in the JAR file, the \f[V].SF\f[R] file -has two lines, such as in the manifest file, that list the following: -.IP \[bu] 2 -File name -.IP \[bu] 2 -Name of the digest algorithm (SHA) -.IP \[bu] 2 -SHA digest value -.PP -\f[B]Note:\f[R] -.PP -The name of the digest algorithm (SHA) and the SHA digest value are on -the same line. -.PP -In the manifest file, the SHA digest value for each source file is the -digest (hash) of the binary data in the source file. -In the \f[V].SF\f[R] file, the digest value for a specified source file -is the hash of the two lines in the manifest file for the source file. -.PP -The signature file, by default, includes a header with a hash of the -whole manifest file. -The header also contains a hash of the manifest header. -The presence of the header enables verification optimization. -See \f[B]JAR File Verification\f[R]. -.SH SIGNATURE BLOCK FILE -.PP -The \f[V].SF\f[R] file is signed and the signature is placed in the -signature block file. -This file also contains, encoded inside it, the certificate or -certificate chain from the keystore that authenticates the public key -corresponding to the private key used for signing. -The file has the extension \f[V].DSA\f[R], \f[V].RSA\f[R], or -\f[V].EC\f[R], depending on the key algorithm used. -See the table in \f[B]Supported Algorithms\f[R]. -.SH SIGNATURE TIME STAMP -.PP -The \f[V]jarsigner\f[R] command used with the following options -generates and stores a signature time stamp when signing a JAR file: -.IP \[bu] 2 -\f[V]-tsa\f[R] \f[I]url\f[R] -.IP \[bu] 2 -\f[V]-tsacert\f[R] \f[I]alias\f[R] -.IP \[bu] 2 -\f[V]-tsapolicyid\f[R] \f[I]policyid\f[R] -.IP \[bu] 2 -\f[V]-tsadigestalg\f[R] \f[I]algorithm\f[R] -.PP -See \f[B]Options for jarsigner\f[R]. -.SH JAR FILE VERIFICATION -.PP -A successful JAR file verification occurs when the signatures are valid, -and none of the files that were in the JAR file when the signatures were -generated have changed since then. -JAR file verification involves the following steps: -.IP "1." 3 -Verify the signature of the \f[V].SF\f[R] file. -.RS 4 -.PP -The verification ensures that the signature stored in each signature -block file was generated using the private key corresponding to the -public key whose certificate (or certificate chain) also appears in the -signature block file. -It also ensures that the signature is a valid signature of the -corresponding signature (\f[V].SF\f[R]) file, and thus the \f[V].SF\f[R] -file wasn\[aq]t tampered with. -.RE -.IP "2." 3 -Verify the digest listed in each entry in the \f[V].SF\f[R] file with -each corresponding section in the manifest. -.RS 4 -.PP -The \f[V].SF\f[R] file by default includes a header that contains a hash -of the entire manifest file. -When the header is present, the verification can check to see whether or -not the hash in the header matches the hash of the manifest file. -If there is a match, then verification proceeds to the next step. -.PP -If there is no match, then a less optimized verification is required to -ensure that the hash in each source file information section in the -\f[V].SF\f[R] file equals the hash of its corresponding section in the -manifest file. -See Signature File. -.PP -One reason the hash of the manifest file that is stored in the -\f[V].SF\f[R] file header might not equal the hash of the current -manifest file is that it might contain sections for newly added files -after the file was signed. -For example, suppose one or more files were added to the signed JAR file -(using the \f[V]jar\f[R] tool) that already contains a signature and a -\f[V].SF\f[R] file. -If the JAR file is signed again by a different signer, then the manifest -file is changed (sections are added to it for the new files by the -\f[V]jarsigner\f[R] tool) and a new \f[V].SF\f[R] file is created, but -the original \f[V].SF\f[R] file is unchanged. -A verification is still considered successful if none of the files that -were in the JAR file when the original signature was generated have been -changed since then. -This is because the hashes in the non-header sections of the -\f[V].SF\f[R] file equal the hashes of the corresponding sections in the -manifest file. -.RE -.IP "3." 3 -Read each file in the JAR file that has an entry in the \f[V].SF\f[R] -file. -While reading, compute the file\[aq]s digest and compare the result with -the digest for this file in the manifest section. -The digests should be the same or verification fails. -.RS 4 -.PP -If any serious verification failures occur during the verification -process, then the process is stopped and a security exception is thrown. -The \f[V]jarsigner\f[R] command catches and displays the exception. -.RE -.IP "4." 3 -Check for disabled algorithm usage. -See \f[B]Supported Algorithms\f[R]. -.PP -\f[B]Note:\f[R] -.PP -You should read any addition warnings (or errors if you specified the -\f[V]-strict\f[R] option), as well as the content of the certificate (by -specifying the \f[V]-verbose\f[R] and \f[V]-certs\f[R] options) to -determine if the signature can be trusted. -.SH MULTIPLE SIGNATURES FOR A JAR FILE -.PP -A JAR file can be signed by multiple people by running the -\f[V]jarsigner\f[R] command on the file multiple times and specifying -the alias for a different person each time, as follows: -.IP -.nf -\f[CB] -jarsigner myBundle.jar susan -jarsigner myBundle.jar kevin -\f[R] -.fi -.PP -When a JAR file is signed multiple times, there are multiple -\f[V].SF\f[R] and signature block files in the resulting JAR file, one -pair for each signature. -In the previous example, the output JAR file includes files with the -following names: -.IP -.nf -\f[CB] -SUSAN.SF -SUSAN.RSA -KEVIN.SF -KEVIN.RSA -\f[R] -.fi -.SH OPTIONS FOR JARSIGNER -.PP -The following sections describe the options for the \f[V]jarsigner\f[R]. -Be aware of the following standards: -.IP \[bu] 2 -All option names are preceded by a hyphen sign (-). -.IP \[bu] 2 -The options can be provided in any order. -.IP \[bu] 2 -Items that are in italics or underlined (option values) represent the -actual values that must be supplied. -.IP \[bu] 2 -The \f[V]-storepass\f[R], \f[V]-keypass\f[R], \f[V]-sigfile\f[R], -\f[V]-sigalg\f[R], \f[V]-digestalg\f[R], \f[V]-signedjar\f[R], and -TSA-related options are only relevant when signing a JAR file; they -aren\[aq]t relevant when verifying a signed JAR file. -The \f[V]-keystore\f[R] option is relevant for signing and verifying a -JAR file. -In addition, aliases are specified when signing and verifying a JAR -file. -.TP -\f[V]-keystore\f[R] \f[I]url\f[R] -Specifies the URL that tells the keystore location. -This defaults to the file \f[V].keystore\f[R] in the user\[aq]s home -directory, as determined by the \f[V]user.home\f[R] system property. -.RS -.PP -A keystore is required when signing. -You must explicitly specify a keystore when the default keystore -doesn\[aq]t exist or if you want to use one other than the default. -.PP -A keystore isn\[aq]t required when verifying, but if one is specified or -the default exists and the \f[V]-verbose\f[R] option was also specified, -then additional information is output regarding whether or not any of -the certificates used to verify the JAR file are contained in that -keystore. -.PP -The \f[V]-keystore\f[R] argument can be a file name and path -specification rather than a URL, in which case it is treated the same as -a file: URL, for example, the following are equivalent: -.IP \[bu] 2 -\f[V]-keystore\f[R] \f[I]filePathAndName\f[R] -.IP \[bu] 2 -\f[V]-keystore file:\f[R]\f[I]filePathAndName\f[R] -.PP -If the Sun PKCS #11 provider was configured in the -\f[V]java.security\f[R] security properties file (located in the -JDK\[aq]s \f[V]$JAVA_HOME/conf/security\f[R] directory), then the -\f[V]keytool\f[R] and \f[V]jarsigner\f[R] tools can operate on the PKCS -#11 token by specifying these options: -.RS -.PP -\f[V]-keystore NONE -storetype PKCS11\f[R] -.RE -.PP -For example, the following command lists the contents of the configured -PKCS#11 token: -.RS -.PP -\f[V]keytool -keystore NONE -storetype PKCS11 -list\f[R] -.RE -.RE -.TP -\f[V]-storepass\f[R] [\f[V]:env\f[R] | \f[V]:file\f[R]] \f[I]argument\f[R] -Specifies the password that is required to access the keystore. -This is only needed when signing (not verifying) a JAR file. -In that case, if a \f[V]-storepass\f[R] option isn\[aq]t provided at the -command line, then the user is prompted for the password. -.RS -.PP -If the modifier \f[V]env\f[R] or \f[V]file\f[R] isn\[aq]t specified, -then the password has the value \f[V]argument\f[R]. -Otherwise, the password is retrieved as follows: -.IP \[bu] 2 -\f[V]env\f[R]: Retrieve the password from the environment variable named -\f[I]argument\f[R]. -.IP \[bu] 2 -\f[V]file\f[R]: Retrieve the password from the file named -\f[I]argument\f[R]. -.PP -\f[B]Note:\f[R] -.PP -The password shouldn\[aq]t be specified on the command line or in a -script unless it is for testing purposes, or you are on a secure system. -.RE -.TP -\f[V]-storetype\f[R] \f[I]storetype\f[R] -Specifies the type of keystore to be instantiated. -The default keystore type is the one that is specified as the value of -the \f[V]keystore.type\f[R] property in the security properties file, -which is returned by the static \f[V]getDefaultType\f[R] method in -\f[V]java.security.KeyStore\f[R]. -.RS -.PP -The PIN for a PKCS #11 token can also be specified with the -\f[V]-storepass\f[R] option. -If none is specified, then the \f[V]keytool\f[R] and \f[V]jarsigner\f[R] -commands prompt for the token PIN. -If the token has a protected authentication path (such as a dedicated -PIN-pad or a biometric reader), then the \f[V]-protected\f[R] option -must be specified and no password options can be specified. -.RE -.TP -\f[V]-keypass\f[R] [\f[V]:env\f[R] | \f[V]:file\f[R]] \f[I]argument\f[R] \f[V]-certchain\f[R] \f[I]file\f[R] -Specifies the password used to protect the private key of the keystore -entry addressed by the alias specified on the command line. -The password is required when using \f[V]jarsigner\f[R] to sign a JAR -file. -If no password is provided on the command line, and the required -password is different from the store password, then the user is prompted -for it. -.RS -.PP -If the modifier \f[V]env\f[R] or \f[V]file\f[R] isn\[aq]t specified, -then the password has the value \f[V]argument\f[R]. -Otherwise, the password is retrieved as follows: -.IP \[bu] 2 -\f[V]env\f[R]: Retrieve the password from the environment variable named -\f[I]argument\f[R]. -.IP \[bu] 2 -\f[V]file\f[R]: Retrieve the password from the file named -\f[I]argument\f[R]. -.PP -\f[B]Note:\f[R] -.PP -The password shouldn\[aq]t be specified on the command line or in a -script unless it is for testing purposes, or you are on a secure system. -.RE -.TP -\f[V]-certchain\f[R] \f[I]file\f[R] -Specifies the certificate chain to be used when the certificate chain -associated with the private key of the keystore entry that is addressed -by the alias specified on the command line isn\[aq]t complete. -This can happen when the keystore is located on a hardware token where -there isn\[aq]t enough capacity to hold a complete certificate chain. -The file can be a sequence of concatenated X.509 certificates, or a -single PKCS#7 formatted data block, either in binary encoding format or -in printable encoding format (also known as Base64 encoding) as defined -by \f[B]Internet RFC 1421 Certificate Encoding Standard\f[R] -[http://tools.ietf.org/html/rfc1421]. -.TP -\f[V]-sigfile\f[R] \f[I]file\f[R] -Specifies the base file name to be used for the generated \f[V].SF\f[R] -and signature block files. -For example, if file is \f[V]DUKESIGN\f[R], then the generated -\f[V].SF\f[R] and signature block files are named \f[V]DUKESIGN.SF\f[R] -and \f[V]DUKESIGN.RSA\f[R], and placed in the \f[V]META-INF\f[R] -directory of the signed JAR file. -.RS -.PP -The characters in the file must come from the set \f[V]a-zA-Z0-9_-\f[R]. -Only letters, numbers, underscore, and hyphen characters are allowed. -All lowercase characters are converted to uppercase for the -\f[V].SF\f[R] and signature block file names. -.PP -If no \f[V]-sigfile\f[R] option appears on the command line, then the -base file name for the \f[V].SF\f[R] and signature block files is the -first 8 characters of the alias name specified on the command line, all -converted to upper case. -If the alias name has fewer than 8 characters, then the full alias name -is used. -If the alias name contains any characters that aren\[aq]t valid in a -signature file name, then each such character is converted to an -underscore (_) character to form the file name. -.RE -.TP -\f[V]-signedjar\f[R] \f[I]file\f[R] -Specifies the name of signed JAR file. -.TP -\f[V]-digestalg\f[R] \f[I]algorithm\f[R] -Specifies the name of the message digest algorithm to use when digesting -the entries of a JAR file. -.RS -.PP -For a list of standard message digest algorithm names, see the Java -Security Standard Algorithm Names Specification. -.PP -If this option isn\[aq]t specified, then \f[V]SHA-384\f[R] is used. -There must either be a statically installed provider supplying an -implementation of the specified algorithm or the user must specify one -with the \f[V]-addprovider\f[R] or \f[V]-providerClass\f[R] options; -otherwise, the command will not succeed. -.RE -.TP -\f[V]-sigalg\f[R] \f[I]algorithm\f[R] -Specifies the name of the signature algorithm to use to sign the JAR -file. -.RS -.PP -This algorithm must be compatible with the private key used to sign the -JAR file. -If this option isn\[aq]t specified, then use a default algorithm -matching the private key as described in the \f[B]Supported -Algorithms\f[R] section. -There must either be a statically installed provider supplying an -implementation of the specified algorithm or you must specify one with -the \f[V]-addprovider\f[R] or \f[V]-providerClass\f[R] option; -otherwise, the command doesn\[aq]t succeed. -.PP -For a list of standard signature algorithm names, see the Java Security -Standard Algorithm Names Specification. -.RE -.TP -\f[V]-verify\f[R] -Verifies a signed JAR file. -.TP -\f[V]-verbose\f[R][\f[V]:\f[R]\f[I]suboptions\f[R]] -When the \f[V]-verbose\f[R] option appears on the command line, it -indicates that the \f[V]jarsigner\f[R] use the verbose mode when signing -or verifying with the suboptions determining how much information is -shown. -This causes the , which causes \f[V]jarsigner\f[R] to output extra -information about the progress of the JAR signing or verification. -The \f[I]suboptions\f[R] can be \f[V]all\f[R], \f[V]grouped\f[R], or -\f[V]summary\f[R]. -.RS -.PP -If the \f[V]-certs\f[R] option is also specified, then the default mode -(or suboption \f[V]all\f[R]) displays each entry as it is being -processed, and after that, the certificate information for each signer -of the JAR file. -.PP -If the \f[V]-certs\f[R] and the \f[V]-verbose:grouped\f[R] suboptions -are specified, then entries with the same signer info are grouped and -displayed together with their certificate information. -.PP -If \f[V]-certs\f[R] and the \f[V]-verbose:summary\f[R] suboptions are -specified, then entries with the same signer information are grouped and -displayed together with their certificate information. -.PP -Details about each entry are summarized and displayed as \f[I]one entry -(and more)\f[R]. -See \f[B]Example of Verifying a Signed JAR File\f[R] and \f[B]Example of -Verification with Certificate Information\f[R]. -.RE -.TP -\f[V]-certs\f[R] -If the \f[V]-certs\f[R] option appears on the command line with the -\f[V]-verify\f[R] and \f[V]-verbose\f[R] options, then the output -includes certificate information for each signer of the JAR file. -This information includes the name of the type of certificate (stored in -the signature block file) that certifies the signer\[aq]s public key, -and if the certificate is an X.509 certificate (an instance of the -\f[V]java.security.cert.X509Certificate\f[R]), then the distinguished -name of the signer. -.RS -.PP -The keystore is also examined. -If no keystore value is specified on the command line, then the default -keystore file (if any) is checked. -If the public key certificate for a signer matches an entry in the -keystore, then the alias name for the keystore entry for that signer is -displayed in parentheses. -.RE -.TP -\f[V]-revCheck\f[R] -This option enables revocation checking of certificates when signing or -verifying a JAR file. -The \f[V]jarsigner\f[R] command attempts to make network connections to -fetch OCSP responses and CRLs if the \f[V]-revCheck\f[R] option is -specified on the command line. -Note that revocation checks are not enabled unless this option is -specified. -.TP -\f[V]-tsa\f[R] \f[I]url\f[R] -If \f[V]-tsa http://example.tsa.url\f[R] appears on the command line -when signing a JAR file then a time stamp is generated for the -signature. -The URL, \f[V]http://example.tsa.url\f[R], identifies the location of -the Time Stamping Authority (TSA) and overrides any URL found with the -\f[V]-tsacert\f[R] option. -The \f[V]-tsa\f[R] option doesn\[aq]t require the TSA public key -certificate to be present in the keystore. -.RS -.PP -To generate the time stamp, \f[V]jarsigner\f[R] communicates with the -TSA with the Time-Stamp Protocol (TSP) defined in RFC 3161. -When successful, the time stamp token returned by the TSA is stored with -the signature in the signature block file. -.RE -.TP -\f[V]-tsacert\f[R] \f[I]alias\f[R] -When \f[V]-tsacert\f[R] \f[I]alias\f[R] appears on the command line when -signing a JAR file, a time stamp is generated for the signature. -The alias identifies the TSA public key certificate in the keystore that -is in effect. -The entry\[aq]s certificate is examined for a Subject Information Access -extension that contains a URL identifying the location of the TSA. -.RS -.PP -The TSA public key certificate must be present in the keystore when -using the \f[V]-tsacert\f[R] option. -.RE -.TP -\f[V]-tsapolicyid\f[R] \f[I]policyid\f[R] -Specifies the object identifier (OID) that identifies the policy ID to -be sent to the TSA server. -If this option isn\[aq]t specified, no policy ID is sent and the TSA -server will choose a default policy ID. -.RS -.PP -Object identifiers are defined by X.696, which is an ITU -Telecommunication Standardization Sector (ITU-T) standard. -These identifiers are typically period-separated sets of non-negative -digits like \f[V]1.2.3.4\f[R], for example. -.RE -.TP -\f[V]-tsadigestalg\f[R] \f[I]algorithm\f[R] -Specifies the message digest algorithm that is used to generate the -message imprint to be sent to the TSA server. -If this option isn\[aq]t specified, SHA-384 will be used. -.RS -.PP -See \f[B]Supported Algorithms\f[R]. -.PP -For a list of standard message digest algorithm names, see the Java -Security Standard Algorithm Names Specification. -.RE -.TP -\f[V]-internalsf\f[R] -In the past, the signature block file generated when a JAR file was -signed included a complete encoded copy of the \f[V].SF\f[R] file -(signature file) also generated. -This behavior has been changed. -To reduce the overall size of the output JAR file, the signature block -file by default doesn\[aq]t contain a copy of the \f[V].SF\f[R] file -anymore. -If \f[V]-internalsf\f[R] appears on the command line, then the old -behavior is utilized. -This option is useful for testing. -In practice, don\[aq]t use the \f[V]-internalsf\f[R] option because it -incurs higher overhead. -.TP -\f[V]-sectionsonly\f[R] -If the \f[V]-sectionsonly\f[R] option appears on the command line, then -the \f[V].SF\f[R] file (signature file) generated when a JAR file is -signed doesn\[aq]t include a header that contains a hash of the whole -manifest file. -It contains only the information and hashes related to each individual -source file included in the JAR file. -See Signature File. -.RS -.PP -By default, this header is added, as an optimization. -When the header is present, whenever the JAR file is verified, the -verification can first check to see whether the hash in the header -matches the hash of the whole manifest file. -When there is a match, verification proceeds to the next step. -When there is no match, it is necessary to do a less optimized -verification that the hash in each source file information section in -the \f[V].SF\f[R] file equals the hash of its corresponding section in -the manifest file. -See \f[B]JAR File Verification\f[R]. -.PP -The \f[V]-sectionsonly\f[R] option is primarily used for testing. -It shouldn\[aq]t be used other than for testing because using it incurs -higher overhead. -.RE -.TP -\f[V]-protected\f[R] -Values can be either \f[V]true\f[R] or \f[V]false\f[R]. -Specify \f[V]true\f[R] when a password must be specified through a -protected authentication path such as a dedicated PIN reader. -.TP -\f[V]-providerName\f[R] \f[I]providerName\f[R] -If more than one provider was configured in the \f[V]java.security\f[R] -security properties file, then you can use the \f[V]-providerName\f[R] -option to target a specific provider instance. -The argument to this option is the name of the provider. -.RS -.PP -For the Oracle PKCS #11 provider, \f[I]providerName\f[R] is of the form -\f[V]SunPKCS11-\f[R]\f[I]TokenName\f[R], where \f[I]TokenName\f[R] is -the name suffix that the provider instance has been configured with, as -detailed in the configuration attributes table. -For example, the following command lists the contents of the -\f[V]PKCS #11\f[R] keystore provider instance with name suffix -\f[V]SmartCard\f[R]: -.RS -.PP -\f[V]jarsigner -keystore NONE -storetype PKCS11 -providerName SunPKCS11-SmartCard -list\f[R] -.RE -.RE -.TP -\f[V]-addprovider\f[R] \f[I]name\f[R] [\f[V]-providerArg\f[R] \f[I]arg\f[R]] -Adds a security provider by name (such as SunPKCS11) and an optional -configure argument. -The value of the security provider is the name of a security provider -that is defined in a module. -.RS -.PP -Used with the \f[V]-providerArg ConfigFilePath\f[R] option, the -\f[V]keytool\f[R] and \f[V]jarsigner\f[R] tools install the provider -dynamically and use \f[V]ConfigFilePath\f[R] for the path to the token -configuration file. -The following example shows a command to list a \f[V]PKCS #11\f[R] -keystore when the Oracle PKCS #11 provider wasn\[aq]t configured in the -security properties file. -.RS -.PP -\f[V]jarsigner -keystore NONE -storetype PKCS11 -addprovider SunPKCS11 -providerArg /mydir1/mydir2/token.config\f[R] -.RE -.RE -.TP -\f[V]-providerClass\f[R] \f[I]provider-class-name\f[R] [\f[V]-providerArg\f[R] \f[I]arg\f[R]] -Used to specify the name of cryptographic service provider\[aq]s master -class file when the service provider isn\[aq]t listed in the -\f[V]java.security\f[R] security properties file. -Adds a security provider by fully-qualified class name and an optional -configure argument. -.RS -.PP -\f[B]Note:\f[R] -.PP -The preferred way to load PKCS11 is by using modules. -See \f[V]-addprovider\f[R]. -.RE -.TP -\f[V]-providerPath\f[R] \f[I]classpath\f[R] -Used to specify the classpath for providers specified by the -\f[V]-providerClass\f[R] option. -Multiple paths should be separated by the system-dependent -path-separator character. -.TP -\f[V]-J\f[R]\f[I]javaoption\f[R] -Passes through the specified \f[I]javaoption\f[R] string directly to the -Java interpreter. -The \f[V]jarsigner\f[R] command is a wrapper around the interpreter. -This option shouldn\[aq]t contain any spaces. -It is useful for adjusting the execution environment or memory usage. -For a list of possible interpreter options, type \f[V]java -h\f[R] or -\f[V]java -X\f[R] at the command line. -.TP -\f[V]-strict\f[R] -During the signing or verifying process, the command may issue warning -messages. -If you specify this option, the exit code of the tool reflects the -severe warning messages that this command found. -See \f[B]Errors and Warnings\f[R]. -.TP -\f[V]-conf\f[R] \f[I]url\f[R] -Specifies a pre-configured options file. -Read the \f[B]keytool documentation\f[R] for details. -The property keys supported are \[dq]jarsigner.all\[dq] for all actions, -\[dq]jarsigner.sign\[dq] for signing, and \[dq]jarsigner.verify\[dq] for -verification. -\f[V]jarsigner\f[R] arguments including the JAR file name and alias -name(s) cannot be set in this file. -.TP -\f[V]-version\f[R] -Prints the program version. -.SH ERRORS AND WARNINGS -.PP -During the signing or verifying process, the \f[V]jarsigner\f[R] command -may issue various errors or warnings. -.PP -If there is a failure, the \f[V]jarsigner\f[R] command exits with code -1. -If there is no failure, but there are one or more severe warnings, the -\f[V]jarsigner\f[R] command exits with code 0 when the \f[V]-strict\f[R] -option is \f[B]not\f[R] specified, or exits with the OR-value of the -warning codes when the \f[V]-strict\f[R] is specified. -If there is only informational warnings or no warning at all, the -command always exits with code 0. -.PP -For example, if a certificate used to sign an entry is expired and has a -KeyUsage extension that doesn\[aq]t allow it to sign a file, the -\f[V]jarsigner\f[R] command exits with code 12 (=4+8) when the -\f[V]-strict\f[R] option is specified. -.PP -\f[B]Note:\f[R] Exit codes are reused because only the values from 0 to -255 are legal on Linux and macOS. -.PP -The following sections describes the names, codes, and descriptions of -the errors and warnings that the \f[V]jarsigner\f[R] command can issue. -.SH FAILURE -.PP -Reasons why the \f[V]jarsigner\f[R] command fails include (but -aren\[aq]t limited to) a command line parsing error, the inability to -find a keypair to sign the JAR file, or the verification of a signed JAR -fails. -.TP -failure -Code 1. -The signing or verifying fails. -.SH SEVERE WARNINGS -.PP -\f[B]Note:\f[R] -.PP -Severe warnings are reported as errors if you specify the -\f[V]-strict\f[R] option. -.PP -Reasons why the \f[V]jarsigner\f[R] command issues a severe warning -include the certificate used to sign the JAR file has an error or the -signed JAR file has other problems. -.TP -hasExpiredCert -Code 4. -This JAR contains entries whose signer certificate has expired. -.TP -hasExpiredTsaCert -Code 4. -The timestamp has expired. -.TP -notYetValidCert -Code 4. -This JAR contains entries whose signer certificate isn\[aq]t yet valid. -.TP -chainNotValidated -Code 4. -This JAR contains entries whose certificate chain isn\[aq]t validated. -.TP -tsaChainNotValidated -Code 64. -The timestamp is invalid. -.TP -signerSelfSigned -Code 4. -This JAR contains entries whose signer certificate is self signed. -.TP -disabledAlg -Code 4. -An algorithm used is considered a security risk and is disabled. -.TP -badKeyUsage -Code 8. -This JAR contains entries whose signer certificate\[aq]s KeyUsage -extension doesn\[aq]t allow code signing. -.TP -badExtendedKeyUsage -Code 8. -This JAR contains entries whose signer certificate\[aq]s -ExtendedKeyUsage extension doesn\[aq]t allow code signing. -.TP -badNetscapeCertType -Code 8. -This JAR contains entries whose signer certificate\[aq]s -NetscapeCertType extension doesn\[aq]t allow code signing. -.TP -hasUnsignedEntry -Code 16. -This JAR contains unsigned entries which haven\[aq]t been -integrity-checked. -.TP -notSignedByAlias -Code 32. -This JAR contains signed entries which aren\[aq]t signed by the -specified alias(es). -.TP -aliasNotInStore -Code 32. -This JAR contains signed entries that aren\[aq]t signed by alias in this -keystore. -.TP -tsaChainNotValidated -Code 64. -This JAR contains entries whose TSA certificate chain is invalid. -.SH INFORMATIONAL WARNINGS -.PP -Informational warnings include those that aren\[aq]t errors but regarded -as bad practice. -They don\[aq]t have a code. -.TP -extraAttributesDetected -The POSIX file permissions and/or symlink attributes are detected during -signing or verifying a JAR file. -The \f[V]jarsigner\f[R] tool preserves these attributes in the newly -signed file but warns that these attributes are unsigned and not -protected by the signature. -.TP -hasExpiringCert -This JAR contains entries whose signer certificate expires within six -months. -.TP -hasExpiringTsaCert -The timestamp will expire within one year on \f[V]YYYY-MM-DD\f[R]. -.TP -legacyAlg -An algorithm used is considered a security risk but not disabled. -.TP -noTimestamp -This JAR contains signatures that doesn\[aq]t include a timestamp. -Without a timestamp, users may not be able to validate this JAR file -after the signer certificate\[aq]s expiration date -(\f[V]YYYY-MM-DD\f[R]) or after any future revocation date. -.SH EXAMPLE OF SIGNING A JAR FILE -.PP -Use the following command to sign \f[V]bundle.jar\f[R] with the private -key of a user whose keystore alias is \f[V]jane\f[R] in a keystore named -\f[V]mystore\f[R] in the \f[V]working\f[R] directory and name the signed -JAR file \f[V]sbundle.jar\f[R]: -.RS -.PP -\f[V]jarsigner -keystore /working/mystore -storepass\f[R] -\f[I]keystore_password\f[R] \f[V]-keypass\f[R] -\f[I]private_key_password\f[R] -\f[V]-signedjar sbundle.jar bundle.jar jane\f[R] -.RE -.PP -There is no \f[V]-sigfile\f[R] specified in the previous command so the -generated \f[V].SF\f[R] and signature block files to be placed in the -signed JAR file have default names based on the alias name. -They are named \f[V]JANE.SF\f[R] and \f[V]JANE.RSA\f[R]. -.PP -If you want to be prompted for the store password and the private key -password, then you could shorten the previous command to the following: -.RS -.PP -\f[V]jarsigner -keystore /working/mystore -signedjar sbundle.jar bundle.jar jane\f[R] -.RE -.PP -If the \f[V]keystore\f[R] is the default \f[V]keystore\f[R] -(\f[V].keystore\f[R] in your home directory), then you don\[aq]t need to -specify a \f[V]keystore\f[R], as follows: -.RS -.PP -\f[V]jarsigner -signedjar sbundle.jar bundle.jar jane\f[R] -.RE -.PP -If you want the signed JAR file to overwrite the input JAR file -(\f[V]bundle.jar\f[R]), then you don\[aq]t need to specify a -\f[V]-signedjar\f[R] option, as follows: -.RS -.PP -\f[V]jarsigner bundle.jar jane\f[R] -.RE -.SH EXAMPLE OF VERIFYING A SIGNED JAR FILE -.PP -To verify a signed JAR file to ensure that the signature is valid and -the JAR file wasn\[aq]t been tampered with, use a command such as the -following: -.RS -.PP -\f[V]jarsigner -verify ButtonDemo.jar\f[R] -.RE -.PP -When the verification is successful, \f[V]jar verified\f[R] is -displayed. -Otherwise, an error message is displayed. -You can get more information when you use the \f[V]-verbose\f[R] option. -A sample use of \f[V]jarsigner\f[R] with the \f[V]-verbose\f[R] option -follows: -.IP -.nf -\f[CB] -jarsigner -verify -verbose ButtonDemo.jar - -s 866 Tue Sep 12 20:08:48 EDT 2017 META-INF/MANIFEST.MF - 825 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.SF - 7475 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.RSA - 0 Tue Sep 12 20:07:54 EDT 2017 META-INF/ - 0 Tue Sep 12 20:07:16 EDT 2017 components/ - 0 Tue Sep 12 20:07:16 EDT 2017 components/images/ -sm 523 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo$1.class -sm 3440 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.class -sm 2346 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.jnlp -sm 172 Tue Sep 12 20:07:16 EDT 2017 components/images/left.gif -sm 235 Tue Sep 12 20:07:16 EDT 2017 components/images/middle.gif -sm 172 Tue Sep 12 20:07:16 EDT 2017 components/images/right.gif - - s = signature was verified - m = entry is listed in manifest - k = at least one certificate was found in keystore - -- Signed by \[dq]CN=\[dq]Oracle America, Inc.\[dq], OU=Software Engineering, O=\[dq]Oracle America, Inc.\[dq], L=Redwood City, ST=California, C=US\[dq] - Digest algorithm: SHA-256 - Signature algorithm: SHA256withRSA, 2048-bit key - Timestamped by \[dq]CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US\[dq] on Tue Sep 12 20:08:49 UTC 2017 - Timestamp digest algorithm: SHA-1 - Timestamp signature algorithm: SHA1withRSA, 2048-bit key - -jar verified. - -The signer certificate expired on 2018-02-01. However, the JAR will be valid until the timestamp expires on 2020-12-29. -\f[R] -.fi -.SH EXAMPLE OF VERIFICATION WITH CERTIFICATE INFORMATION -.PP -If you specify the \f[V]-certs\f[R] option with the \f[V]-verify\f[R] -and \f[V]-verbose\f[R] options, then the output includes certificate -information for each signer of the JAR file. -The information includes the certificate type, the signer distinguished -name information (when it is an X.509 certificate), and in parentheses, -the keystore alias for the signer when the public key certificate in the -JAR file matches the one in a keystore entry, for example: -.IP -.nf -\f[CB] -jarsigner -keystore $JAVA_HOME/lib/security/cacerts -verify -verbose -certs ButtonDemo.jar - -s k 866 Tue Sep 12 20:08:48 EDT 2017 META-INF/MANIFEST.MF - - >>> Signer - X.509, CN=\[dq]Oracle America, Inc.\[dq], OU=Software Engineering, O=\[dq]Oracle America, Inc.\[dq], L=Redwood City, ST=California, C=US - [certificate is valid from 2017-01-30, 7:00 PM to 2018-02-01, 6:59 PM] - X.509, CN=Symantec Class 3 SHA256 Code Signing CA, OU=Symantec Trust Network, O=Symantec Corporation, C=US - [certificate is valid from 2013-12-09, 7:00 PM to 2023-12-09, 6:59 PM] - X.509, CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU=\[dq](c) 2006 VeriSign, Inc. - For authorized use only\[dq], OU=VeriSign Trust Network, O=\[dq]VeriSign, Inc.\[dq], C=US (verisignclass3g5ca [jdk]) - [trusted certificate] - >>> TSA - X.509, CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US - [certificate is valid from 2012-10-17, 8:00 PM to 2020-12-29, 6:59 PM] - X.509, CN=Symantec Time Stamping Services CA - G2, O=Symantec Corporation, C=US - [certificate is valid from 2012-12-20, 7:00 PM to 2020-12-30, 6:59 PM] - - 825 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.SF - 7475 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.RSA - 0 Tue Sep 12 20:07:54 EDT 2017 META-INF/ - 0 Tue Sep 12 20:07:16 EDT 2017 components/ - 0 Tue Sep 12 20:07:16 EDT 2017 components/images/ -smk 523 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo$1.class - - [entry was signed on 2017-09-12, 4:08 PM] - >>> Signer - X.509, CN=\[dq]Oracle America, Inc.\[dq], OU=Software Engineering, O=\[dq]Oracle America, Inc.\[dq], L=Redwood City, ST=California, C=US - [certificate is valid from 2017-01-30, 7:00 PM to 2018-02-01, 6:59 PM] - X.509, CN=Symantec Class 3 SHA256 Code Signing CA, OU=Symantec Trust Network, O=Symantec Corporation, C=US - [certificate is valid from 2013-12-09, 7:00 PM to 2023-12-09, 6:59 PM] - X.509, CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU=\[dq](c) 2006 VeriSign, Inc. - For authorized use only\[dq], OU=VeriSign Trust Network, O=\[dq]VeriSign, Inc.\[dq], C=US (verisignclass3g5ca [jdk]) - [trusted certificate] - >>> TSA - X.509, CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US - [certificate is valid from 2012-10-17, 8:00 PM to 2020-12-29, 6:59 PM] - X.509, CN=Symantec Time Stamping Services CA - G2, O=Symantec Corporation, C=US - [certificate is valid from 2012-12-20, 7:00 PM to 2020-12-30, 6:59 PM] - -smk 3440 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.class -\&... -smk 2346 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.jnlp -\&... -smk 172 Tue Sep 12 20:07:16 EDT 2017 components/images/left.gif -\&... -smk 235 Tue Sep 12 20:07:16 EDT 2017 components/images/middle.gif -\&... -smk 172 Tue Sep 12 20:07:16 EDT 2017 components/images/right.gif -\&... - - s = signature was verified - m = entry is listed in manifest - k = at least one certificate was found in keystore - -- Signed by \[dq]CN=\[dq]Oracle America, Inc.\[dq], OU=Software Engineering, O=\[dq]Oracle America, Inc.\[dq], L=Redwood City, ST=California, C=US\[dq] - Digest algorithm: SHA-256 - Signature algorithm: SHA256withRSA, 2048-bit key - Timestamped by \[dq]CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US\[dq] on Tue Sep 12 20:08:49 UTC 2017 - Timestamp digest algorithm: SHA-1 - Timestamp signature algorithm: SHA1withRSA, 2048-bit key - -jar verified. - -The signer certificate expired on 2018-02-01. However, the JAR will be valid until the timestamp expires on 2020-12-29. -\f[R] -.fi -.PP -If the certificate for a signer isn\[aq]t an X.509 certificate, then -there is no distinguished name information. -In that case, just the certificate type and the alias are shown. -For example, if the certificate is a PGP certificate, and the alias is -\f[V]bob\f[R], then you would get: \f[V]PGP, (bob)\f[R]. diff --git a/src/jdk.jartool/share/man/jarsigner.md b/src/jdk.jartool/share/man/jarsigner.md new file mode 100644 index 00000000000..9542c0fda60 --- /dev/null +++ b/src/jdk.jartool/share/man/jarsigner.md @@ -0,0 +1,1089 @@ +--- +# Copyright (c) 1998, 2024, 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. +# + +title: 'JARSIGNER(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jarsigner - sign and verify Java Archive (JAR) files + +## Synopsis + +`jarsigner` \[*options*\] *jar-file* *alias* + +`jarsigner` `-verify` \[*options*\] *jar-file* \[*alias* ...\] + +`jarsigner` `-version` + +*options* +: The command-line options. See [Options for jarsigner]. + +`-verify` +: The `-verify` option can take zero or more keystore alias names after the + JAR file name. When the `-verify` option is specified, the `jarsigner` + command checks that the certificate used to verify each signed entry in the + JAR file matches one of the keystore aliases. The aliases are defined in + the keystore specified by `-keystore` or the default keystore. + + If you also specify the `-strict` option, and the `jarsigner` command + detects severe warnings, the message, "jar verified, with signer errors" is + displayed. + +*jar-file* +: The JAR file to be signed. + + If you also specified the `-strict` option, and the `jarsigner` command + detected severe warnings, the message, "jar signed, with signer errors" is + displayed. + +*alias* +: The aliases are defined in the keystore specified by `-keystore` or the + default keystore. + +`-version` +: The `-version` option prints the program version of `jarsigner`. + +## Description + +The `jarsigner` tool has two purposes: + +- To sign Java Archive (JAR) files. + +- To verify the signatures and integrity of signed JAR files. + +The JAR feature enables the packaging of class files, images, sounds, and other +digital data in a single file for faster and easier distribution. A tool named +`jar` enables developers to produce JAR files. (Technically, any ZIP file can +also be considered a JAR file, although when created by the `jar` command or +processed by the `jarsigner` command, JAR files also contain a +`META-INF/MANIFEST.MF` file.) + +A digital signature is a string of bits that is computed from some data (the +data being signed) and the private key of an entity (a person, company, and so +on). Similar to a handwritten signature, a digital signature has many useful +characteristics: + +- Its authenticity can be verified by a computation that uses the public key + corresponding to the private key used to generate the signature. + +- It can't be forged, assuming the private key is kept secret. + +- It is a function of the data signed and thus can't be claimed to be the + signature for other data as well. + +- The signed data can't be changed. If the data is changed, then the + signature can't be verified as authentic. + +To generate an entity's signature for a file, the entity must first have a +public/private key pair associated with it and one or more certificates that +authenticate its public key. A certificate is a digitally signed statement from +one entity that says that the public key of another entity has a particular +value. + +The `jarsigner` command uses key and certificate information from a keystore to +generate digital signatures for JAR files. A keystore is a database of private +keys and their associated X.509 certificate chains that authenticate the +corresponding public keys. The `keytool` command is used to create and +administer keystores. + +The `jarsigner` command uses an entity's private key to generate a signature. +The signed JAR file contains, among other things, a copy of the certificate +from the keystore for the public key corresponding to the private key used to +sign the file. The `jarsigner` command can verify the digital signature of the +signed JAR file using the certificate inside it (in its signature block file). + +The `jarsigner` command can generate signatures that include a time stamp that +enables a systems or deployer to check whether the JAR file was signed while +the signing certificate was still valid. + +In addition, APIs allow applications to obtain the timestamp information. + +At this time, the `jarsigner` command can only sign JAR files created by the +`jar` command or zip files. JAR files are the same as zip files, except they +also have a `META-INF/MANIFEST.MF` file. A `META-INF/MANIFEST.MF` file is +created when the `jarsigner` command signs a zip file. + +The default `jarsigner` command behavior is to sign a JAR or zip file. Use the +`-verify` option to verify a signed JAR file. + +The `jarsigner` command also attempts to validate the signer's certificate +after signing or verifying. During validation, it checks the revocation +status of each certificate in the signer's certificate chain when the +`-revCheck` option is specified. If there is a validation error or any other +problem, the command generates warning messages. If you specify the `-strict` +option, then the command treats severe warnings as errors. See [Errors and +Warnings]. + +## Keystore Aliases + +All keystore entities are accessed with unique aliases. + +When you use the `jarsigner` command to sign a JAR file, you must specify the +alias for the keystore entry that contains the private key needed to generate +the signature. If no output file is specified, it overwrites the original JAR +file with the signed JAR file. + +Keystores are protected with a password, so the store password must be +specified. You are prompted for it when you don't specify it on the command +line. Similarly, private keys are protected in a keystore with a password, so +the private key's password must be specified, and you are prompted for the +password when you don't specify it on the command line and it isn't the same as +the store password. + +## Keystore Location + +The `jarsigner` command has a `-keystore` option for specifying the URL of the +keystore to be used. The keystore is by default stored in a file named +`.keystore` in the user's home directory, as determined by the `user.home` +system property. + +**Linux and macOS:** `user.home` defaults to the user's home +directory. + +The input stream from the `-keystore` option is passed to the `KeyStore.load` +method. If `NONE` is specified as the URL, then a null stream is passed to the +`KeyStore.load` method. `NONE` should be specified when the `KeyStore` class +isn't file based, for example, when it resides on a hardware token device. + +## Keystore Implementation + +The `KeyStore` class provided in the `java.security` package supplies a number +of well-defined interfaces to access and modify the information in a keystore. +You can have multiple different concrete implementations, where each +implementation is for a particular type of keystore. + +Currently, there are two command-line tools that use keystore implementations +(`keytool` and `jarsigner`). + +The default keystore implementation is `PKCS12`. This is a cross platform +keystore based on the RSA PKCS12 Personal Information Exchange Syntax Standard. +This standard is primarily meant for storing or transporting a user's private +keys, certificates, and miscellaneous secrets. There is another built-in +implementation, provided by Oracle. It implements the keystore as a file with a +proprietary keystore type (format) named `JKS`. It protects each private key +with its individual password, and also protects the integrity of the entire +keystore with a (possibly different) password. + +Keystore implementations are provider-based, which means the application +interfaces supplied by the `KeyStore` class are implemented in terms of a +Service Provider Interface (SPI). There is a corresponding abstract +`KeystoreSpi` class, also in the `java.security package`, that defines the +Service Provider Interface methods that providers must implement. The term +provider refers to a package or a set of packages that supply a concrete +implementation of a subset of services that can be accessed by the Java +Security API. To provide a keystore implementation, clients must implement a +provider and supply a `KeystoreSpi` subclass implementation, as described in +[How to Implement a Provider in the Java Cryptography Architecture]( +https://www.oracle.com/pls/topic/lookup?ctx=en/java/javase&id=security_guide_implement_provider_jca). + +Applications can choose different types of keystore implementations from +different providers, with the `getInstance` factory method in the `KeyStore` +class. A keystore type defines the storage and data format of the keystore +information and the algorithms used to protect private keys in the keystore and +the integrity of the keystore itself. Keystore implementations of different +types aren't compatible. + +The `jarsigner` commands can read file-based keystores from any location that +can be specified using a URL. In addition, these commands can read +non-file-based keystores such as those provided by MSCAPI on Windows and PKCS11 +on all platforms. + +For the `jarsigner` and `keytool` commands, you can specify a keystore type at +the command line with the `-storetype` option. + +If you don't explicitly specify a keystore type, then the tools choose a +keystore implementation based on the value of the `keystore.type` property +specified in the security properties file. The security properties file is +called `java.security`, and it resides in the JDK security properties +directory, `java.home/conf/security`. + +Each tool gets the `keystore.type` value and then examines all the installed +providers until it finds one that implements keystores of that type. It then +uses the keystore implementation from that provider. + +The `KeyStore` class defines a static method named `getDefaultType` that lets +applications retrieve the value of the `keystore.type` property. The following +line of code creates an instance of the default keystore type as specified in +the `keystore.type` property: + +> `KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());` + +The default keystore type is `pkcs12`, which is a cross platform keystore based +on the RSA PKCS12 Personal Information Exchange Syntax Standard. This is +specified by the following line in the security properties file: + +> `keystore.type=pkcs12` + +Case doesn't matter in keystore type designations. For example, `JKS` is the +same as `jks`. + +To have the tools utilize a keystore implementation other than the default, you +can change that line to specify a different keystore type. For example, if you +want to use the Oracle's `jks` keystore implementation, then change the line to +the following: + +> `keystore.type=jks` + +## Supported Algorithms + +By default, the `jarsigner` command signs a JAR file using one of the following +algorithms and block file extensions depending on the type and size of +the private key: + +Table: Default Signature Algorithms and Block File Extensions + +keyalg key size default sigalg block file extension +------- -------- -------------- -------------------- +DSA any size SHA256withDSA .DSA +RSA \< 624 SHA256withRSA .RSA + \<= 7680 SHA384withRSA + \> 7680 SHA512withRSA +EC \< 512 SHA384withECDSA .EC + \>= 512 SHA512withECDSA +RSASSA-PSS \< 624 RSASSA-PSS (with SHA-256) .RSA + \<= 7680 RSASSA-PSS (with SHA-384) + \> 7680 RSASSA-PSS (with SHA-512) +EdDSA 255 Ed25519 .EC + 448 Ed448 +------- -------- -------------- ------ + +* If an RSASSA-PSS key is encoded with parameters, then jarsigner will use the +same parameters in the signature. Otherwise, jarsigner will use parameters that +are determined by the size of the key as specified in the table above. +For example, an 3072-bit RSASSA-PSS key will use RSASSA-PSS as the signature +algorithm and SHA-384 as the hash and MGF1 algorithms. + +* If a key algorithm is not listed in this table, the `.DSA` extension +is used when signing a JAR file. + +These default signature algorithms can be overridden by using the `-sigalg` +option. + +The `jarsigner` command uses the `jdk.jar.disabledAlgorithms` and +`jdk.security.legacyAlgorithms` security properties to determine which +algorithms are considered a security risk. If the JAR file was signed +with any algorithms that are disabled, it will be treated as an unsigned JAR +file. If the JAR file was signed with any legacy algorithms, it will be treated +as signed with an informational warning to inform users that the legacy +algorithm will be disabled in a future update. +For detailed verification output, include `-J-Djava.security.debug=jar`. +The `jdk.jar.disabledAlgorithms` and `jdk.security.legacyAlgorithms` +security properties are defined in the `java.security` file (located in +the JDK's `$JAVA_HOME/conf/security` directory). + +**Note:** + +In order to improve out of the box security, default key size and signature +algorithm names are periodically updated to stronger values with each release +of the JDK. If interoperability with older releases of the JDK is important, +please make sure the defaults are supported by those releases, or alternatively +use the `-sigalg` option to override the default values at your own risk. + +## The Signed JAR File + +When the `jarsigner` command is used to sign a JAR file, the output signed JAR +file is exactly the same as the input JAR file, except that it has two +additional files placed in the META-INF directory: + +- A signature file with an `.SF` extension + +- A signature block file with a `.DSA`, `.RSA`, or `.EC` extension + +The base file names for these two files come from the value of the `-sigfile` +option. For example, when the option is `-sigfile MKSIGN`, the files are named +`MKSIGN.SF` and `MKSIGN.RSA`. In this document, we assume the signer always +uses an RSA key. + +If no `-sigfile` option appears on the command line, then the base file name +for the `.SF` and the signature block files is the first 8 characters of the alias name +specified on the command line, all converted to uppercase. If the alias name +has fewer than 8 characters, then the full alias name is used. If the alias +name contains any characters that aren't allowed in a signature file name, then +each such character is converted to an underscore (\_) character in forming the +file name. Valid characters include letters, digits, underscores, and hyphens. + +## Signature File + +A signature file (`.SF` file) looks similar to the manifest file that is always +included in a JAR file when the `jarsigner` command is used to sign the file. +For each source file included in the JAR file, the `.SF` file has two lines, +such as in the manifest file, that list the following: + +- File name + +- Name of the digest algorithm (SHA) + +- SHA digest value + +**Note:** + +The name of the digest algorithm (SHA) and the SHA digest value are on the same +line. + +In the manifest file, the SHA digest value for each source file is the digest +(hash) of the binary data in the source file. In the `.SF` file, the digest +value for a specified source file is the hash of the two lines in the manifest +file for the source file. + +The signature file, by default, includes a header with a hash of the whole +manifest file. The header also contains a hash of the manifest header. The +presence of the header enables verification optimization. See [JAR File +Verification]. + +## Signature Block File + +The `.SF` file is signed and the signature is placed in the signature block +file. This file also contains, encoded inside it, the certificate or +certificate chain from the keystore that authenticates the public key +corresponding to the private key used for signing. The file has the extension +`.DSA`, `.RSA`, or `.EC`, depending on the key algorithm used. See the table +in [Supported Algorithms]. + +## Signature Time Stamp + +The `jarsigner` command used with the following options generates and stores a +signature time stamp when signing a JAR file: + +- `-tsa` *url* + +- `-tsacert` *alias* + +- `-tsapolicyid` *policyid* + +- `-tsadigestalg` *algorithm* + +See [Options for jarsigner]. + +## JAR File Verification + +A successful JAR file verification occurs when the signatures are valid, and +none of the files that were in the JAR file when the signatures were generated +have changed since then. JAR file verification involves the following steps: + +1. Verify the signature of the `.SF` file. + + The verification ensures that the signature stored in each signature block + file was generated using the private key corresponding to the + public key whose certificate (or certificate chain) also appears in the + signature block file. It also ensures that the signature is a valid signature of the + corresponding signature (`.SF`) file, and thus the `.SF` file wasn't + tampered with. + +2. Verify the digest listed in each entry in the `.SF` file with each + corresponding section in the manifest. + + The `.SF` file by default includes a header that contains a hash of the + entire manifest file. When the header is present, the verification can + check to see whether or not the hash in the header matches the hash of the + manifest file. If there is a match, then verification proceeds to the next + step. + + If there is no match, then a less optimized verification is required to + ensure that the hash in each source file information section in the `.SF` + file equals the hash of its corresponding section in the manifest file. See + Signature File. + + One reason the hash of the manifest file that is stored in the `.SF` file + header might not equal the hash of the current manifest file is that it + might contain sections for newly added files after the file was signed. For + example, suppose one or more files were added to the signed JAR file (using + the `jar` tool) that already contains a signature and a `.SF` file. If the + JAR file is signed again by a different signer, then the manifest file is + changed (sections are added to it for the new files by the `jarsigner` tool) + and a new `.SF` file is created, but the original `.SF` file is unchanged. A + verification is still considered successful if none of the files that were + in the JAR file when the original signature was generated have been changed + since then. This is because the hashes in the non-header sections of the + `.SF` file equal the hashes of the corresponding sections in the manifest + file. + +3. Read each file in the JAR file that has an entry in the `.SF` file. While + reading, compute the file's digest and compare the result with the digest + for this file in the manifest section. The digests should be the same or + verification fails. + + If any serious verification failures occur during the verification process, + then the process is stopped and a security exception is thrown. The + `jarsigner` command catches and displays the exception. + +4. Check for disabled algorithm usage. See [Supported Algorithms]. + +**Note:** + +You should read any addition warnings (or errors if you specified the `-strict` +option), as well as the content of the certificate (by specifying the +`-verbose` and `-certs` options) to determine if the signature can be trusted. + +## Multiple Signatures for a JAR File + +A JAR file can be signed by multiple people by running the `jarsigner` command +on the file multiple times and specifying the alias for a different person each +time, as follows: + +``` +jarsigner myBundle.jar susan +jarsigner myBundle.jar kevin +``` + +When a JAR file is signed multiple times, there are multiple `.SF` and signature +block files in the resulting JAR file, one pair for each signature. In the previous +example, the output JAR file includes files with the following names: + +``` +SUSAN.SF +SUSAN.RSA +KEVIN.SF +KEVIN.RSA +``` + +## Options for jarsigner + +The following sections describe the options for the `jarsigner`. Be aware of +the following standards: + +- All option names are preceded by a hyphen sign (-). + +- The options can be provided in any order. + +- Items that are in italics or underlined (option values) represent the + actual values that must be supplied. + +- The `-storepass`, `-keypass`, `-sigfile`, `-sigalg`, `-digestalg`, + `-signedjar`, and TSA-related options are only relevant when signing a JAR + file; they aren't relevant when verifying a signed JAR file. The + `-keystore` option is relevant for signing and verifying a JAR file. In + addition, aliases are specified when signing and verifying a JAR file. + +`-keystore` *url* +: Specifies the URL that tells the keystore location. This defaults to the + file `.keystore` in the user's home directory, as determined by the + `user.home` system property. + + A keystore is required when signing. You must explicitly specify a keystore + when the default keystore doesn't exist or if you want to use one other + than the default. + + A keystore isn't required when verifying, but if one is specified or the + default exists and the `-verbose` option was also specified, then + additional information is output regarding whether or not any of the + certificates used to verify the JAR file are contained in that keystore. + + The `-keystore` argument can be a file name and path specification rather + than a URL, in which case it is treated the same as a file: URL, for + example, the following are equivalent: + + - `-keystore` *filePathAndName* + + - `-keystore file:`*filePathAndName* + + If the Sun PKCS \#11 provider was configured in the `java.security` + security properties file (located in the JDK's `$JAVA_HOME/conf/security` + directory), then the `keytool` and `jarsigner` tools can operate on the + PKCS \#11 token by specifying these options: + + > `-keystore NONE -storetype PKCS11` + + For example, the following command lists the contents of the configured + PKCS\#11 token: + + > `keytool -keystore NONE -storetype PKCS11 -list` + +`-storepass` \[`:env` \| `:file`\] *argument* +: Specifies the password that is required to access the keystore. This is + only needed when signing (not verifying) a JAR file. In that case, if a + `-storepass` option isn't provided at the command line, then the user is + prompted for the password. + + If the modifier `env` or `file` isn't specified, then the password has the + value `argument`. Otherwise, the password is retrieved as follows: + + - `env`: Retrieve the password from the environment variable named + *argument*. + + - `file`: Retrieve the password from the file named *argument*. + + **Note:** + + The password shouldn't be specified on the command line or in a script + unless it is for testing purposes, or you are on a secure system. + +`-storetype` *storetype* +: Specifies the type of keystore to be instantiated. The default keystore + type is the one that is specified as the value of the `keystore.type` + property in the security properties file, which is returned by the static + `getDefaultType` method in `java.security.KeyStore`. + + The PIN for a PKCS \#11 token can also be specified with the `-storepass` + option. If none is specified, then the `keytool` and `jarsigner` commands + prompt for the token PIN. If the token has a protected authentication path + (such as a dedicated PIN-pad or a biometric reader), then the `-protected` + option must be specified and no password options can be specified. + +`-keypass` \[`:env` \| `:file`\] *argument* `-certchain` *file* +: Specifies the password used to protect the private key of the keystore + entry addressed by the alias specified on the command line. The password is + required when using `jarsigner` to sign a JAR file. If no password is + provided on the command line, and the required password is different from + the store password, then the user is prompted for it. + + If the modifier `env` or `file` isn't specified, then the password has the + value `argument`. Otherwise, the password is retrieved as follows: + + - `env`: Retrieve the password from the environment variable named + *argument*. + + - `file`: Retrieve the password from the file named *argument*. + + **Note:** + + The password shouldn't be specified on the command line or in a script + unless it is for testing purposes, or you are on a secure system. + +`-certchain` *file* +: Specifies the certificate chain to be used when the certificate chain + associated with the private key of the keystore entry that is addressed by + the alias specified on the command line isn't complete. This can happen + when the keystore is located on a hardware token where there isn't enough + capacity to hold a complete certificate chain. The file can be a sequence + of concatenated X.509 certificates, or a single PKCS\#7 formatted data + block, either in binary encoding format or in printable encoding format + (also known as Base64 encoding) as defined by [Internet RFC 1421 + Certificate Encoding Standard](http://tools.ietf.org/html/rfc1421). + +`-sigfile` *file* +: Specifies the base file name to be used for the generated `.SF` and signature block + files. For example, if file is `DUKESIGN`, then the generated `.SF` and + signature block files are named `DUKESIGN.SF` and `DUKESIGN.RSA`, and placed in the + `META-INF` directory of the signed JAR file. + + The characters in the file must come from the set `a-zA-Z0-9_-`. Only + letters, numbers, underscore, and hyphen characters are allowed. All + lowercase characters are converted to uppercase for the `.SF` and signature block + file names. + + If no `-sigfile` option appears on the command line, then the base file + name for the `.SF` and signature block files is the first 8 characters of the alias + name specified on the command line, all converted to upper case. If the + alias name has fewer than 8 characters, then the full alias name is used. + If the alias name contains any characters that aren't valid in a signature + file name, then each such character is converted to an underscore (\_) + character to form the file name. + +`-signedjar` *file* +: Specifies the name of signed JAR file. + +`-digestalg` *algorithm* +: Specifies the name of the message digest algorithm to use when digesting + the entries of a JAR file. + + For a list of standard message digest algorithm names, see the Java Security + Standard Algorithm Names Specification. + + If this option isn't specified, then `SHA-384` is used. There must either be + a statically installed provider supplying an implementation of the + specified algorithm or the user must specify one with the `-addprovider` or + `-providerClass` options; otherwise, the command will not succeed. + +`-sigalg` *algorithm* +: Specifies the name of the signature algorithm to use to sign the JAR file. + + This algorithm must be compatible with the private key used to sign the + JAR file. If this option isn't specified, then use a default algorithm + matching the private key as described in the [Supported Algorithms] + section. There must either be a statically installed provider supplying an + implementation of the specified algorithm or you must specify one with the + `-addprovider` or `-providerClass` option; otherwise, the command doesn't + succeed. + + For a list of standard signature algorithm names, see the Java Security + Standard Algorithm Names Specification. + +`-verify` +: Verifies a signed JAR file. + +`-verbose`\[`:`*suboptions*\] +: When the `-verbose` option appears on the command line, it indicates that + the `jarsigner` use the verbose mode when signing or verifying with the + suboptions determining how much information is shown. This causes the , + which causes `jarsigner` to output extra information about the progress of + the JAR signing or verification. The *suboptions* can be `all`, `grouped`, + or `summary`. + + If the `-certs` option is also specified, then the default mode (or + suboption `all`) displays each entry as it is being processed, and after + that, the certificate information for each signer of the JAR file. + + If the `-certs` and the `-verbose:grouped` suboptions are specified, then + entries with the same signer info are grouped and displayed together with + their certificate information. + + If `-certs` and the `-verbose:summary` suboptions are specified, then + entries with the same signer information are grouped and displayed together + with their certificate information. + + Details about each entry are summarized and displayed as *one entry (and + more)*. See [Example of Verifying a Signed JAR File] and [Example of + Verification with Certificate Information]. + +`-certs` +: If the `-certs` option appears on the command line with the `-verify` and + `-verbose` options, then the output includes certificate information for + each signer of the JAR file. This information includes the name of the type + of certificate (stored in the signature block file) that certifies the signer's + public key, and if the certificate is an X.509 certificate (an instance of + the `java.security.cert.X509Certificate`), then the distinguished name of + the signer. + + The keystore is also examined. If no keystore value is specified on the + command line, then the default keystore file (if any) is checked. If the + public key certificate for a signer matches an entry in the keystore, then + the alias name for the keystore entry for that signer is displayed in + parentheses. + +`-revCheck` +: This option enables revocation checking of certificates when signing or + verifying a JAR file. The `jarsigner` command attempts to make network + connections to fetch OCSP responses and CRLs if the `-revCheck` option + is specified on the command line. Note that revocation checks are not + enabled unless this option is specified. + +`-tsa` *url* +: If `-tsa http://example.tsa.url` appears on the command line when signing a + JAR file then a time stamp is generated for the signature. The URL, + `http://example.tsa.url`, identifies the location of the Time Stamping + Authority (TSA) and overrides any URL found with the `-tsacert` option. The + `-tsa` option doesn't require the TSA public key certificate to be present + in the keystore. + + To generate the time stamp, `jarsigner` communicates with the TSA with the + Time-Stamp Protocol (TSP) defined in RFC 3161. When successful, the time + stamp token returned by the TSA is stored with the signature in the + signature block file. + +`-tsacert` *alias* +: When `-tsacert` *alias* appears on the command line when signing a JAR + file, a time stamp is generated for the signature. The alias identifies the + TSA public key certificate in the keystore that is in effect. The entry's + certificate is examined for a Subject Information Access extension that + contains a URL identifying the location of the TSA. + + The TSA public key certificate must be present in the keystore when using + the `-tsacert` option. + +`-tsapolicyid` *policyid* +: Specifies the object identifier (OID) that identifies the policy ID to be + sent to the TSA server. If this option isn't specified, no policy ID is + sent and the TSA server will choose a default policy ID. + + Object identifiers are defined by X.696, which is an ITU Telecommunication + Standardization Sector (ITU-T) standard. These identifiers are typically + period-separated sets of non-negative digits like `1.2.3.4`, for example. + +`-tsadigestalg` *algorithm* +: Specifies the message digest algorithm that is used to generate the message + imprint to be sent to the TSA server. If this option isn't specified, + SHA-384 will be used. + + See [Supported Algorithms]. + + For a list of standard message digest algorithm names, see the Java Security + Standard Algorithm Names Specification. + +`-internalsf` +: In the past, the signature block file generated when a JAR file + was signed included a complete encoded copy of the `.SF` file (signature + file) also generated. This behavior has been changed. To reduce the overall + size of the output JAR file, the signature block file by default doesn't contain a + copy of the `.SF` file anymore. If `-internalsf` appears on the command + line, then the old behavior is utilized. This option is useful for testing. + In practice, don't use the `-internalsf` option because it incurs higher + overhead. + +`-sectionsonly` +: If the `-sectionsonly` option appears on the command line, then the `.SF` + file (signature file) generated when a JAR file is signed doesn't include a + header that contains a hash of the whole manifest file. It contains only + the information and hashes related to each individual source file included + in the JAR file. See Signature File. + + By default, this header is added, as an optimization. When the header is + present, whenever the JAR file is verified, the verification can first + check to see whether the hash in the header matches the hash of the whole + manifest file. When there is a match, verification proceeds to the next + step. When there is no match, it is necessary to do a less optimized + verification that the hash in each source file information section in the + `.SF` file equals the hash of its corresponding section in the manifest + file. See [JAR File Verification]. + + The `-sectionsonly` option is primarily used for testing. It shouldn't be + used other than for testing because using it incurs higher overhead. + +`-protected` +: Values can be either `true` or `false`. Specify `true` when a password must + be specified through a protected authentication path such as a dedicated + PIN reader. + +`-providerName` *providerName* +: If more than one provider was configured in the `java.security` security + properties file, then you can use the `-providerName` option to target a + specific provider instance. The argument to this option is the name of the + provider. + + For the Oracle PKCS \#11 provider, *providerName* is of the form + `SunPKCS11-`*TokenName*, where *TokenName* is the name suffix that the + provider instance has been configured with, as detailed in the + configuration attributes table. For example, the following command lists + the contents of the `PKCS #11` keystore provider instance with name suffix + `SmartCard`: + + > `jarsigner -keystore NONE -storetype PKCS11 -providerName + SunPKCS11-SmartCard -list` + +`-addprovider` *name* \[`-providerArg` *arg*\] +: Adds a security provider by name (such as SunPKCS11) and an optional + configure argument. The value of the security provider is the name of a + security provider that is defined in a module. + + Used with the `-providerArg ConfigFilePath` option, the `keytool` and + `jarsigner` tools install the provider dynamically and use `ConfigFilePath` + for the path to the token configuration file. The following example shows a + command to list a `PKCS #11` keystore when the Oracle PKCS \#11 provider + wasn't configured in the security properties file. + + > `jarsigner -keystore NONE -storetype PKCS11 -addprovider SunPKCS11 + -providerArg /mydir1/mydir2/token.config` + +`-providerClass` *provider-class-name* \[`-providerArg` *arg*\] +: Used to specify the name of cryptographic service provider's master class + file when the service provider isn't listed in the `java.security` security + properties file. Adds a security provider by fully-qualified class name and + an optional configure argument. + + **Note:** + + The preferred way to load PKCS11 is by using modules. See `-addprovider`. + +`-providerPath` *classpath* +: Used to specify the classpath for providers specified by the `-providerClass` + option. Multiple paths should be separated by the system-dependent + path-separator character. + +`-J`*javaoption* +: Passes through the specified *javaoption* string directly to the Java + interpreter. The `jarsigner` command is a wrapper around the interpreter. + This option shouldn't contain any spaces. It is useful for adjusting the + execution environment or memory usage. For a list of possible interpreter + options, type `java -h` or `java -X` at the command line. + +`-strict` +: During the signing or verifying process, the command may issue warning + messages. If you specify this option, the exit code of the tool reflects + the severe warning messages that this command found. See [Errors and + Warnings]. + +`-conf` *url* +: Specifies a pre-configured options file. Read the + [keytool documentation](keytool.html#pre-configured-options-file) for + details. The property keys supported are "jarsigner.all" for all actions, + "jarsigner.sign" for signing, and "jarsigner.verify" for verification. + `jarsigner` arguments including the JAR file name and alias name(s) cannot + be set in this file. + +`-version` +: Prints the program version. + +## Errors and Warnings + +During the signing or verifying process, the `jarsigner` command may issue +various errors or warnings. + +If there is a failure, the `jarsigner` command exits with code 1. If there is +no failure, but there are one or more severe warnings, the `jarsigner` command +exits with code 0 when the `-strict` option is **not** specified, or exits with +the OR-value of the warning codes when the `-strict` is specified. If there is +only informational warnings or no warning at all, the command always exits with +code 0. + +For example, if a certificate used to sign an entry is expired and has a +KeyUsage extension that doesn't allow it to sign a file, the `jarsigner` +command exits with code 12 (=4+8) when the `-strict` option is specified. + +**Note:** Exit codes are reused because only the values from 0 to 255 are legal +on Linux and macOS. + +The following sections describes the names, codes, and descriptions of the +errors and warnings that the `jarsigner` command can issue. + +## Failure + +Reasons why the `jarsigner` command fails include (but aren't limited to) a +command line parsing error, the inability to find a keypair to sign the JAR +file, or the verification of a signed JAR fails. + +failure +: Code 1. The signing or verifying fails. + +## Severe Warnings + +**Note:** + +Severe warnings are reported as errors if you specify the `-strict` option. + +Reasons why the `jarsigner` command issues a severe warning include the +certificate used to sign the JAR file has an error or the signed JAR file has +other problems. + +hasExpiredCert +: Code 4. This JAR contains entries whose signer certificate has expired. + +hasExpiredTsaCert +: Code 4. The timestamp has expired. + +notYetValidCert +: Code 4. This JAR contains entries whose signer certificate isn't yet valid. + +chainNotValidated +: Code 4. This JAR contains entries whose certificate chain isn't validated. + +tsaChainNotValidated +: Code 64. The timestamp is invalid. + +signerSelfSigned +: Code 4. This JAR contains entries whose signer certificate is self signed. + +disabledAlg +: Code 4. An algorithm used is considered a security risk and is disabled. + +badKeyUsage +: Code 8. This JAR contains entries whose signer certificate's KeyUsage + extension doesn't allow code signing. + +badExtendedKeyUsage +: Code 8. This JAR contains entries whose signer certificate's + ExtendedKeyUsage extension doesn't allow code signing. + +badNetscapeCertType +: Code 8. This JAR contains entries whose signer certificate's + NetscapeCertType extension doesn't allow code signing. + +hasUnsignedEntry +: Code 16. This JAR contains unsigned entries which haven't been + integrity-checked. + +notSignedByAlias +: Code 32. This JAR contains signed entries which aren't signed by the + specified alias(es). + +aliasNotInStore +: Code 32. This JAR contains signed entries that aren't signed by alias in + this keystore. + +tsaChainNotValidated +: Code 64. This JAR contains entries whose TSA certificate chain is invalid. + +## Informational Warnings + +Informational warnings include those that aren't errors but regarded as bad +practice. They don't have a code. + +extraAttributesDetected +: The POSIX file permissions and/or symlink attributes are detected during + signing or verifying a JAR file. The `jarsigner` tool preserves these + attributes in the newly signed file but warns that these attributes are + unsigned and not protected by the signature. + +hasExpiringCert +: This JAR contains entries whose signer certificate expires within six + months. + +hasExpiringTsaCert +: The timestamp will expire within one year on `YYYY-MM-DD`. + +hasNonexistentEntries +: This JAR contains signed entries for files that do not exist. + +legacyAlg +: An algorithm used is considered a security risk but not disabled. + +noTimestamp +: This JAR contains signatures that doesn't include a timestamp. Without a + timestamp, users may not be able to validate this JAR file after the signer + certificate's expiration date (`YYYY-MM-DD`) or after any future revocation + date. + +## Example of Signing a JAR File + +Use the following command to sign `bundle.jar` with the private key of a user +whose keystore alias is `jane` in a keystore named `mystore` in the `working` +directory and name the signed JAR file `sbundle.jar`: + +> `jarsigner -keystore /working/mystore -storepass` *keystore\_password* + `-keypass` *private\_key\_password* `-signedjar sbundle.jar bundle.jar + jane` + +There is no `-sigfile` specified in the previous command so the generated `.SF` +and signature block files to be placed in the signed JAR file have default names based +on the alias name. They are named `JANE.SF` and `JANE.RSA`. + +If you want to be prompted for the store password and the private key password, +then you could shorten the previous command to the following: + +> `jarsigner -keystore /working/mystore -signedjar sbundle.jar bundle.jar + jane` + +If the `keystore` is the default `keystore` (`.keystore` in your home +directory), then you don't need to specify a `keystore`, as follows: + +> `jarsigner -signedjar sbundle.jar bundle.jar jane` + +If you want the signed JAR file to overwrite the input JAR file (`bundle.jar`), +then you don't need to specify a `-signedjar` option, as follows: + +> `jarsigner bundle.jar jane` + +## Example of Verifying a Signed JAR File + +To verify a signed JAR file to ensure that the signature is valid and the JAR +file wasn't been tampered with, use a command such as the following: + +> `jarsigner -verify ButtonDemo.jar` + +When the verification is successful, `jar verified` is displayed. Otherwise, an +error message is displayed. You can get more information when you use the +`-verbose` option. A sample use of `jarsigner` with the `-verbose` option +follows: + +``` +jarsigner -verify -verbose ButtonDemo.jar + +s 866 Tue Sep 12 20:08:48 EDT 2017 META-INF/MANIFEST.MF + 825 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.SF + 7475 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.RSA + 0 Tue Sep 12 20:07:54 EDT 2017 META-INF/ + 0 Tue Sep 12 20:07:16 EDT 2017 components/ + 0 Tue Sep 12 20:07:16 EDT 2017 components/images/ +sm 523 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo$1.class +sm 3440 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.class +sm 2346 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.jnlp +sm 172 Tue Sep 12 20:07:16 EDT 2017 components/images/left.gif +sm 235 Tue Sep 12 20:07:16 EDT 2017 components/images/middle.gif +sm 172 Tue Sep 12 20:07:16 EDT 2017 components/images/right.gif + + s = signature was verified + m = entry is listed in manifest + k = at least one certificate was found in keystore + +- Signed by "CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US" + Digest algorithm: SHA-256 + Signature algorithm: SHA256withRSA, 2048-bit key + Timestamped by "CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US" on Tue Sep 12 20:08:49 UTC 2017 + Timestamp digest algorithm: SHA-1 + Timestamp signature algorithm: SHA1withRSA, 2048-bit key + +jar verified. + +The signer certificate expired on 2018-02-01. However, the JAR will be valid until the timestamp expires on 2020-12-29. +``` + +## Example of Verification with Certificate Information + +If you specify the `-certs` option with the `-verify` and `-verbose` options, +then the output includes certificate information for each signer of the JAR +file. The information includes the certificate type, the signer distinguished +name information (when it is an X.509 certificate), and in parentheses, the +keystore alias for the signer when the public key certificate in the JAR file +matches the one in a keystore entry, for example: + +``` +jarsigner -keystore $JAVA_HOME/lib/security/cacerts -verify -verbose -certs ButtonDemo.jar + +s k 866 Tue Sep 12 20:08:48 EDT 2017 META-INF/MANIFEST.MF + + >>> Signer + X.509, CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US + [certificate is valid from 2017-01-30, 7:00 PM to 2018-02-01, 6:59 PM] + X.509, CN=Symantec Class 3 SHA256 Code Signing CA, OU=Symantec Trust Network, O=Symantec Corporation, C=US + [certificate is valid from 2013-12-09, 7:00 PM to 2023-12-09, 6:59 PM] + X.509, CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US (verisignclass3g5ca [jdk]) + [trusted certificate] + >>> TSA + X.509, CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US + [certificate is valid from 2012-10-17, 8:00 PM to 2020-12-29, 6:59 PM] + X.509, CN=Symantec Time Stamping Services CA - G2, O=Symantec Corporation, C=US + [certificate is valid from 2012-12-20, 7:00 PM to 2020-12-30, 6:59 PM] + + 825 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.SF + 7475 Tue Sep 12 20:08:48 EDT 2017 META-INF/ORACLE_C.RSA + 0 Tue Sep 12 20:07:54 EDT 2017 META-INF/ + 0 Tue Sep 12 20:07:16 EDT 2017 components/ + 0 Tue Sep 12 20:07:16 EDT 2017 components/images/ +smk 523 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo$1.class + + [entry was signed on 2017-09-12, 4:08 PM] + >>> Signer + X.509, CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US + [certificate is valid from 2017-01-30, 7:00 PM to 2018-02-01, 6:59 PM] + X.509, CN=Symantec Class 3 SHA256 Code Signing CA, OU=Symantec Trust Network, O=Symantec Corporation, C=US + [certificate is valid from 2013-12-09, 7:00 PM to 2023-12-09, 6:59 PM] + X.509, CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US (verisignclass3g5ca [jdk]) + [trusted certificate] + >>> TSA + X.509, CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US + [certificate is valid from 2012-10-17, 8:00 PM to 2020-12-29, 6:59 PM] + X.509, CN=Symantec Time Stamping Services CA - G2, O=Symantec Corporation, C=US + [certificate is valid from 2012-12-20, 7:00 PM to 2020-12-30, 6:59 PM] + +smk 3440 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.class +... +smk 2346 Tue Sep 12 20:07:16 EDT 2017 components/ButtonDemo.jnlp +... +smk 172 Tue Sep 12 20:07:16 EDT 2017 components/images/left.gif +... +smk 235 Tue Sep 12 20:07:16 EDT 2017 components/images/middle.gif +... +smk 172 Tue Sep 12 20:07:16 EDT 2017 components/images/right.gif +... + + s = signature was verified + m = entry is listed in manifest + k = at least one certificate was found in keystore + +- Signed by "CN="Oracle America, Inc.", OU=Software Engineering, O="Oracle America, Inc.", L=Redwood City, ST=California, C=US" + Digest algorithm: SHA-256 + Signature algorithm: SHA256withRSA, 2048-bit key + Timestamped by "CN=Symantec Time Stamping Services Signer - G4, O=Symantec Corporation, C=US" on Tue Sep 12 20:08:49 UTC 2017 + Timestamp digest algorithm: SHA-1 + Timestamp signature algorithm: SHA1withRSA, 2048-bit key + +jar verified. + +The signer certificate expired on 2018-02-01. However, the JAR will be valid until the timestamp expires on 2020-12-29. +``` + +If the certificate for a signer isn't an X.509 certificate, then there is no +distinguished name information. In that case, just the certificate type and the +alias are shown. For example, if the certificate is a PGP certificate, and the +alias is `bob`, then you would get: `PGP, (bob)`. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java index b688420681f..793f619035a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java @@ -41,6 +41,8 @@ import com.sun.source.doctree.DeprecatedTree; import com.sun.source.doctree.DocTree; +import java.util.function.Predicate; +import java.util.stream.Collectors; import jdk.javadoc.doclet.DocletEnvironment.ModuleMode; import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode; @@ -52,9 +54,10 @@ import jdk.javadoc.internal.html.Content; import jdk.javadoc.internal.html.ContentBuilder; import jdk.javadoc.internal.html.Entity; +import jdk.javadoc.internal.html.HtmlId; import jdk.javadoc.internal.html.HtmlStyle; -import jdk.javadoc.internal.html.HtmlTag; import jdk.javadoc.internal.html.HtmlTree; +import jdk.javadoc.internal.html.RawHtml; import jdk.javadoc.internal.html.Text; /** @@ -582,15 +585,52 @@ protected void addPackagesSummary(Content summariesList) { TableHeader indirectPackagesHeader = new TableHeader(contents.fromLabel, contents.packagesLabel); if (display(indirectPackages)) { - String aepText = resources.getText("doclet.Indirect_Exports_Summary"); - var aepTable = getTable2(Text.of(aepText), indirectPackagesHeader); - addIndirectPackages(aepTable, indirectPackages); - section.add(aepTable); + ModuleElement javaBase = this.utils.elementUtils.getModuleElement("java.base"); + boolean hasRequiresTransitiveJavaBase = + ElementFilter.requiresIn(mdle.getDirectives()) + .stream() + .anyMatch(rd -> rd.isTransitive() && + javaBase.equals(rd.getDependency())); + if (hasRequiresTransitiveJavaBase) { + String aepText = resources.getText("doclet.Indirect_Exports_Summary"); + var aepTable = getTable2(Text.of(aepText), indirectPackagesHeader); + addIndirectPackages(aepTable, indirectPackages, + m -> !m.equals(javaBase)); + section.add(aepTable); + //add the preview box: + section.add(HtmlTree.BR()); + section.add(HtmlTree.BR()); + HtmlId previewRequiresTransitiveId = HtmlId.of("preview-requires-transitive-java.base"); + var previewDiv = HtmlTree.DIV(HtmlStyles.previewBlock); + previewDiv.setId(previewRequiresTransitiveId); + + Content note = + RawHtml.of(resources.getText("doclet.PreviewJavaSERequiresTransitiveJavaBase")); + + previewDiv.add(HtmlTree.DIV(HtmlStyles.previewComment, note)); + section.add(previewDiv); + + //add the Indirect Exports + String aepPreviewText = resources.getText("doclet.Indirect_Exports_Summary"); + ContentBuilder tableCaption = new ContentBuilder( + Text.of(aepPreviewText), + HtmlTree.SUP(links.createLink(previewRequiresTransitiveId, + contents.previewMark))); + var aepPreviewTable = getTable2(tableCaption, indirectPackagesHeader); + addIndirectPackages(aepPreviewTable, indirectPackages, + m -> m.equals(javaBase)); + section.add(aepPreviewTable); + } else { + String aepText = resources.getText("doclet.Indirect_Exports_Summary"); + var aepTable = getTable2(Text.of(aepText), indirectPackagesHeader); + addIndirectPackages(aepTable, indirectPackages, _ -> true); + section.add(aepTable); + } } if (display(indirectOpenPackages)) { String aopText = resources.getText("doclet.Indirect_Opens_Summary"); var aopTable = getTable2(Text.of(aopText), indirectPackagesHeader); - addIndirectPackages(aopTable, indirectOpenPackages); + addIndirectPackages(aopTable, indirectOpenPackages, _ -> true); section.add(aopTable); } summariesList.add(HtmlTree.LI(section)); @@ -721,9 +761,14 @@ private Content getPackageExportOpensTo(Set modules) { * @param table the table to which the content rows will be added * @param ip indirect packages to be added */ - public void addIndirectPackages(Table table, Map> ip) { + public void addIndirectPackages(Table table, + Map> ip, + Predicate acceptModule) { for (Map.Entry> entry : ip.entrySet()) { ModuleElement m = entry.getKey(); + if (!acceptModule.test(m)) { + continue; + } SortedSet pkgList = entry.getValue(); Content moduleLinkContent = getModuleLink(m, Text.of(m.getQualifiedName())); Content list = new ContentBuilder(); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index e6faa7bbe19..44f285f21db 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -431,6 +431,14 @@ doclet.ReflectivePreviewAPI={0} refers to one or more reflective preview APIs: doclet.UsesDeclaredUsingPreview={0} refers to one or more types which are declared using a preview feature of the Java language: {1}. doclet.PreviewTrailingNote1=Programs can only use {0} when preview features are enabled. doclet.PreviewTrailingNote2=Preview features may be removed in a future release, or upgraded to permanent features of the Java platform. +doclet.PreviewJavaSERequiresTransitiveJavaBase=\ +Indirect exports from the java.base module are associated \ +with the requires transitive java.base directive, which is \ +a preview feature of the Java language.
\ +Programs can only use requires transitive java.base when \ +preview features are enabled.
\ +Preview features may be removed in a future release, or upgraded \ +to permanent features of the Java Platform.
doclet.RestrictedMethod=restricted method doclet.RestrictedLeadingNote={0} is a {1} of the Java platform. doclet.RestrictedTrailingNote1=Programs can only use {0} when access to restricted methods is enabled. diff --git a/src/jdk.javadoc/share/man/javadoc.1 b/src/jdk.javadoc/share/man/javadoc.1 deleted file mode 100644 index 4e256a7ce38..00000000000 --- a/src/jdk.javadoc/share/man/javadoc.1 +++ /dev/null @@ -1,1526 +0,0 @@ -.\" Copyright (c) 1994, 2024, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JAVADOC" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -javadoc - generate HTML pages of API documentation from Java source -files -.SH SYNOPSIS -.PP -\f[V]javadoc\f[R] [\f[I]options\f[R]] [\f[I]packagenames\f[R]] -[\f[I]sourcefiles\f[R]] [\f[V]\[at]\f[R]\f[I]files\f[R]] -.TP -\f[I]options\f[R] -Specifies command-line options, separated by spaces. -See \f[B]Standard \f[VB]javadoc\f[B] Options\f[R], \f[B]Extra -\f[VB]javadoc\f[B] Options\f[R], \f[B]Standard Options for the Standard -Doclet\f[R], and \f[B]Extra Options for the Standard Doclet\f[R]. -.TP -\f[I]packagenames\f[R] -Specifies names of packages that you want to document, separated by -spaces, for example \f[V]java.lang java.lang.reflect java.awt\f[R]. -If you want to also document the subpackages, then use the -\f[V]-subpackages\f[R] option to specify the packages. -.RS -.PP -By default, \f[V]javadoc\f[R] looks for the specified packages in the -current directory and subdirectories. -Use the \f[V]-sourcepath\f[R] option to specify the list of directories -where to look for packages. -.RE -.TP -\f[I]sourcefiles\f[R] -Specifies names of Java source files that you want to document, -separated by spaces, for example -\f[V]Class.java Object.java Button.java\f[R]. -By default, \f[V]javadoc\f[R] looks for the specified classes in the -current directory. -However, you can specify the full path to the class file and use -wildcard characters, for example -\f[V]/home/src/java/awt/Graphics*.java\f[R]. -You can also specify the path relative to the current directory. -.TP -\f[V]\[at]\f[R]\f[I]files\f[R] -Specifies names of files that contain a list of \f[V]javadoc\f[R] tool -options, package names, and source file names in any order. -.SH DESCRIPTION -.PP -The \f[V]javadoc\f[R] tool parses the declarations and documentation -comments in a set of Java source files and produces corresponding HTML -pages that describe (by default) the public and protected classes, -nested and implicitly declared classes (but not anonymous inner -classes), interfaces, constructors, methods, and fields. -You can use the \f[V]javadoc\f[R] tool to generate the API documentation -or the implementation documentation for a set of source files. -.PP -You can run the \f[V]javadoc\f[R] tool on entire packages, individual -source files, or both. -When documenting entire packages, you can use the \f[V]-subpackages\f[R] -option either to recursively traverse a directory and its -subdirectories, or to pass in an explicit list of package names. -When you document individual source files, pass in a list of Java source -file names. -.SS Documentation Comments -.PP -The \f[V]javadoc\f[R] tool uses the documentation comment, if any, that -immediately precedes the beginning of the declaration, whether that is -an annotation, modifier, or the name being declared. -If there are multiple documentation comments before the declaration, -only the last one (closest to the declaration) will be used. -If there are any documentation comments after the beginning of the -declaration, they will be ignored. -To check for any extra or misplaced documentation comments, compile your -source code with the \f[V]javac\f[R] option \f[V]-Xlint\f[R], or more -specifically, \f[V]-Xlint:dangling-doc-comments\f[R]. -Within a source file, you may suppress any warnings generated by these -options by using -\f[V]\[at]SuppressWarnings(\[dq]dangling-doc-comments\[dq])\f[R] on a -suitable enclosing declaration. -.SS Conformance -.PP -The standard doclet does not validate the content of documentation -comments for conformance, nor does it attempt to correct any errors in -documentation comments. -Anyone running javadoc is advised to be aware of the problems that may -arise when generating non-conformant output or output containing -executable content, such as JavaScript. -The standard doclet does provide the \f[B]DocLint\f[R] feature to help -developers detect common problems in documentation comments; but it is -also recommended to check the generated output with any appropriate -conformance and other checking tools. -.PP -For more details on the conformance requirements for HTML5 documents, -see \f[B]Conformance requirements for authors\f[R] -[https://html.spec.whatwg.org/multipage/introduction.html#conformance-requirements-for-authors] -in the HTML5 Specification. -For more details on security issues related to web pages, see the -\f[B]Open Web Application Security Project (OWASP)\f[R] -[https://www.owasp.org] page. -.SH OPTIONS -.PP -\f[V]javadoc\f[R] supports command-line options for both the main -\f[V]javadoc\f[R] tool and the currently selected doclet. -The standard doclet is used if no other doclet is specified. -.PP -GNU-style options (that is, those beginning with \f[V]--\f[R]) can use -an equal sign (\f[V]=\f[R]) instead of whitespace characters to separate -the name of an option from its value. -.SS Standard \f[V]javadoc\f[R] Options -.PP -The following core \f[V]javadoc\f[R] options are equivalent to -corresponding \f[V]javac\f[R] options. -See \f[I]Standard Options\f[R] in \f[B]javac\f[R] for the detailed -descriptions of using these options: -.IP \[bu] 2 -\f[V]--add-modules\f[R] -.IP \[bu] 2 -\f[V]-bootclasspath\f[R] -.IP \[bu] 2 -\f[V]--class-path\f[R], \f[V]-classpath\f[R], or \f[V]-cp\f[R] -.IP \[bu] 2 -\f[V]--disable-line-doc-comments\f[R] -.IP \[bu] 2 -\f[V]--enable-preview\f[R] -.IP \[bu] 2 -\f[V]-encoding\f[R] -.IP \[bu] 2 -\f[V]-extdirs\f[R] -.IP \[bu] 2 -\f[V]--limit-modules\f[R] -.IP \[bu] 2 -\f[V]--module\f[R] -.IP \[bu] 2 -\f[V]--module-path\f[R] or \f[V]-p\f[R] -.IP \[bu] 2 -\f[V]--module-source-path\f[R] -.IP \[bu] 2 -\f[V]--release\f[R] -.IP \[bu] 2 -\f[V]--source\f[R] or \f[V]-source\f[R] -.IP \[bu] 2 -\f[V]--source-path\f[R] or \f[V]-sourcepath\f[R] -.IP \[bu] 2 -\f[V]--system\f[R] -.IP \[bu] 2 -\f[V]--upgrade-module-path\f[R] -.PP -The following options are the core \f[V]javadoc\f[R] options that are -not equivalent to a corresponding \f[V]javac\f[R] option: -.TP -\f[V]-breakiterator\f[R] -Computes the first sentence of the description in a documentation -comment using an instance of \f[V]java.text.BreakIterator\f[R] to detect -\f[I]sentence breaks\f[R]. -The rules that are used depend on the \f[B]current locale\f[R]: for -example, for English, a sentence break occurs after a period, question -mark, or exclamation point followed by a space when the next word starts -with a capital letter. -(This is meant to handle most abbreviations, such as \[dq]The serial no. -is valid\[dq], but will not handle \[dq]Mr. -Smith\[dq].) -.RS -.PP -The option is enabled by default if the language of the current locale -is not English. -If the language of the current locale is English, and the -\f[V]-breakiterator\f[R] option is not given, a simple default algorithm -is used, which just looks for a period followed by a space. -.PP -In a traditional \f[V]/**...*/\f[R] comment, the search for the end of -the first sentence is terminated by an HTML block tag, such as -\f[V]

\f[R], \f[V]

\f[R], or the tag for a heading.
-.PP
-In a Markdown \f[V]///\f[R] comment, the search for the end of the first
-sentence skips over any characters enclosed in code spans and links, and
-is terminated by the end of the initial block, as indicated by a blank
-line or the beginning of the next block, such as a list, thematic break,
-or an HTML block.
-.PP
-The first sentence of the description in a documentation comment is used
-in summary tables, index pages, and other situations where a short
-summary is required.
-For more explicit control in any individual documentation comment,
-enclose the contents of the first sentence in a
-\f[V]{\[at]summary ...}\f[R] tag, or when applicable, in a
-\f[V]{\[at]return ...}\f[R] tag.
-.RE
-.TP
-\f[V]-doclet\f[R] \f[I]class\f[R]
-Generates output by using an alternate doclet.
-Use the fully qualified name.
-This doclet defines the content and formats the output.
-If the \f[V]-doclet\f[R] option isn\[aq]t used, then the
-\f[V]javadoc\f[R] tool uses the standard doclet for generating the
-default HTML format.
-This class must implement the \f[V]jdk.javadoc.doclet.Doclet\f[R]
-interface.
-The path to this class is defined by the \f[V]-docletpath\f[R] option.
-.TP
-\f[V]-docletpath\f[R] \f[I]path\f[R]
-Specifies where to find doclet class files (specified with the
-\f[V]-doclet\f[R] option) and any JAR files it depends on.
-If the starting class file is in a JAR file, then this option specifies
-the path to that JAR file.
-You can specify an absolute path or a path relative to the current
-directory.
-If \f[V]path\f[R] contains multiple paths or JAR files, then they should
-be separated with a colon (\f[V]:\f[R]) on Linux and macOS, and a
-semicolon (\f[V];\f[R]) on Windows.
-This option isn\[aq]t necessary when the \f[V]doclet\f[R] starting class
-is already in the search path.
-.TP
-\f[V]-exclude\f[R] \f[I]pkglist\f[R]
-Unconditionally, excludes the specified packages and their subpackages
-from the list formed by \f[V]-subpackages\f[R].
-It excludes those packages even when they would otherwise be included by
-some earlier or later \f[V]-subpackages\f[R] option.
-.RS
-.PP
-The following example would include \f[V]java.io\f[R],
-\f[V]java.util\f[R], and \f[V]java.math\f[R] (among others), but would
-exclude packages rooted at \f[V]java.net\f[R] and \f[V]java.lang\f[R].
-Notice that these examples exclude \f[V]java.lang.ref\f[R], which is a
-subpackage of \f[V]java.lang\f[R].
-Arguments are separated by colons on all operating systems.
-.IP \[bu] 2
-\f[B]Linux and macOS:\f[R]
-.RS 2
-.IP
-.nf
-\f[CB]
-javadoc -sourcepath /home/user/src -subpackages java -exclude java.net:java.lang
-\f[R]
-.fi
-.RE
-.IP \[bu] 2
-\f[B]Windows:\f[R]
-.RS 2
-.IP
-.nf
-\f[CB]
-javadoc -sourcepath \[rs]user\[rs]src -subpackages java -exclude java.net:java.lang
-\f[R]
-.fi
-.RE
-.RE
-.TP
-\f[V]--expand-requires\f[R] (\f[V]transitive\f[R]|\f[V]all\f[R])
-Instructs the javadoc tool to expand the set of modules to be
-documented.
-By default, only the modules given explicitly on the command line are
-documented.
-Supports the following values:
-.RS
-.IP \[bu] 2
-\f[V]transitive\f[R]: additionally includes all the required transitive
-dependencies of those modules.
-.IP \[bu] 2
-\f[V]all\f[R]: includes all dependencies.
-.RE
-.TP
-\f[V]--help\f[R], \f[V]-help\f[R], \f[V]-h\f[R], or \f[V]-?\f[R]
-Prints a synopsis of the standard options.
-.TP
-\f[V]--help-extra\f[R] or \f[V]-X\f[R]
-Prints a synopsis of the set of extra options.
-.TP
-\f[V]-J\f[R]\f[I]flag\f[R]
-Passes \f[I]flag\f[R] directly to the Java Runtime Environment (JRE)
-that runs the \f[V]javadoc\f[R] tool.
-For example, if you must ensure that the system sets aside 32 MB of
-memory in which to process the generated documentation, then you would
-call the \f[V]-Xmx\f[R] option as follows:
-\f[V]javadoc -J-Xmx32m -J-Xms32m com.mypackage\f[R].
-Be aware that \f[V]-Xms\f[R] is optional because it only sets the size
-of initial memory, which is useful when you know the minimum amount of
-memory required.
-.RS
-.PP
-There is no space between the \f[V]J\f[R] and the \f[V]flag\f[R].
-.PP
-Use the \f[V]-version\f[R] option to report the version of the JRE being
-used to run the \f[V]javadoc\f[R] tool.
-.IP
-.nf
-\f[CB]
-javadoc -J-version
-java version \[dq]17\[dq] 2021-09-14 LTS
-Java(TM) SE Runtime Environment (build 17+35-LTS-2724)
-Java HotSpot(TM) 64-Bit Server VM (build 17+35-LTS-2724, mixed mode, sharing)
-\f[R]
-.fi
-.RE
-.TP
-\f[V]-locale\f[R] \f[I]name\f[R]
-Specifies the locale that the \f[V]javadoc\f[R] tool uses when it
-generates documentation.
-The argument is the name of the locale, as described in
-\f[V]java.util.Locale\f[R] documentation, such as \f[V]en_US\f[R]
-(English, United States) or \f[V]en_US_WIN\f[R] (Windows variant).
-.RS
-.PP
-Specifying a locale causes the \f[V]javadoc\f[R] tool to choose the
-resource files of that locale for messages such as strings in the
-navigation bar, headings for lists and tables, help file contents,
-comments in the \f[V]stylesheet.css\f[R] file, and so on.
-It also specifies the sorting order for lists sorted alphabetically, and
-the sentence separator to determine the end of the first sentence.
-The \f[V]-locale\f[R] option doesn\[aq]t determine the locale of the
-documentation comment text specified in the source files of the
-documented classes.
-.RE
-.TP
-\f[V]-package\f[R]
-Shows only package, protected, and public classes and members.
-.TP
-\f[V]-private\f[R]
-Shows all classes and members.
-.TP
-\f[V]-protected\f[R]
-Shows only protected and public classes and members.
-This is the default.
-.TP
-\f[V]-public\f[R]
-Shows only the public classes and members.
-.TP
-\f[V]-quiet\f[R]
-Shuts off messages so that only the warnings and errors appear to make
-them easier to view.
-It also suppresses the \f[V]version\f[R] string.
-.TP
-\f[V]--show-members\f[R] \f[I]value\f[R]
-Specifies which members (fields, methods, or constructors) are
-documented, where \f[I]value\f[R] can be any of the following:
-.RS
-.IP \[bu] 2
-\f[V]public\f[R] --- shows only public members
-.IP \[bu] 2
-\f[V]protected\f[R] --- shows public and protected members; this is the
-default
-.IP \[bu] 2
-\f[V]package\f[R] --- shows public, protected, and package members
-.IP \[bu] 2
-\f[V]private\f[R] --- shows all members
-.RE
-.TP
-\f[V]--show-module-contents\f[R] \f[I]value\f[R]
-Specifies the documentation granularity of module declarations, where
-\f[I]value\f[R] can be \f[V]api\f[R] or \f[V]all\f[R].
-.TP
-\f[V]--show-packages\f[R] \f[I]value\f[R]
-Specifies which module packages are documented, where \f[I]value\f[R]
-can be \f[V]exported\f[R] or \f[V]all\f[R] packages.
-.TP
-\f[V]--show-types\f[R] \f[I]value\f[R]
-Specifies which types (classes, interfaces, etc.)
-are documented, where \f[I]value\f[R] can be any of the following:
-.RS
-.IP \[bu] 2
-\f[V]public\f[R] --- shows only public types
-.IP \[bu] 2
-\f[V]protected\f[R] --- shows public and protected types; this is the
-default
-.IP \[bu] 2
-\f[V]package\f[R] --- shows public, protected, and package types
-.IP \[bu] 2
-\f[V]private\f[R] --- shows all types
-.RE
-.TP
-\f[V]-subpackages\f[R] \f[I]subpkglist\f[R]
-Generates documentation from source files in the specified packages and
-recursively in their subpackages.
-This option is useful when adding new subpackages to the source code
-because they are automatically included.
-Each package argument is any top-level subpackage (such as
-\f[V]java\f[R]) or fully qualified package (such as
-\f[V]javax.swing\f[R]) that doesn\[aq]t need to contain source files.
-Arguments are separated by colons on all operating systems.
-Wild cards aren\[aq]t allowed.
-Use \f[V]-sourcepath\f[R] to specify where to find the packages.
-This option doesn\[aq]t process source files that are in the source tree
-but don\[aq]t belong to the packages.
-.RS
-.PP
-For example, the following commands generates documentation for packages
-named \f[V]java\f[R] and \f[V]javax.swing\f[R] and all of their
-subpackages.
-.IP \[bu] 2
-\f[B]Linux and macOS:\f[R]
-.RS 2
-.IP
-.nf
-\f[CB]
-javadoc -d docs -sourcepath /home/user/src -subpackages java:javax.swing
-\f[R]
-.fi
-.RE
-.IP \[bu] 2
-\f[B]Windows:\f[R]
-.RS 2
-.IP
-.nf
-\f[CB]
-javadoc -d docs -sourcepath \[rs]user\[rs]src -subpackages java:javax.swing
-\f[R]
-.fi
-.RE
-.RE
-.TP
-\f[V]-verbose\f[R]
-Provides more detailed messages while the \f[V]javadoc\f[R] tool runs.
-Without the \f[V]-verbose\f[R] option, messages appear for loading the
-source files, generating the documentation (one message per source
-file), and sorting.
-The \f[V]-verbose\f[R] option causes the printing of additional messages
-that specify the number of milliseconds to parse each Java source file.
-.TP
-\f[V]--version\f[R]
-Prints version information.
-.TP
-\f[V]-Werror\f[R]
-Reports an error if any warnings occur.
-.PP
-Note that if a Java source file contains an implicitly declared class,
-then that class and its public, protected, and package members will be
-documented regardless of the options such as \f[V]--show-types\f[R],
-\f[V]--show-members\f[R], \f[V]-private\f[R], \f[V]-protected\f[R],
-\f[V]-package\f[R], and \f[V]-public\f[R].
-If \f[V]--show-members\f[R] is specified with value \f[V]private\f[R] or
-if \f[V]-private\f[R] is used then all private members of an implicitly
-declared class will be documented too.
-.SS Extra \f[V]javadoc\f[R] Options
-.PP
-\f[I]Note:\f[R] The additional options for \f[V]javadoc\f[R] are subject
-to change without notice.
-.PP
-The following additional \f[V]javadoc\f[R] options are equivalent to
-corresponding \f[V]javac\f[R] options.
-See \f[I]Extra Options\f[R] in \f[B]javac\f[R] for the detailed
-descriptions of using these options:
-.IP \[bu] 2
-\f[V]--add-exports\f[R]
-.IP \[bu] 2
-\f[V]--add-reads\f[R]
-.IP \[bu] 2
-\f[V]--patch-module\f[R]
-.IP \[bu] 2
-\f[V]-Xmaxerrs\f[R]
-.IP \[bu] 2
-\f[V]-Xmaxwarns\f[R]
-.SS Standard Options for the Standard Doclet
-.PP
-The following options are provided by the standard doclet.
-.TP
-\f[V]--add-script\f[R] \f[I]file\f[R]
-Adds \f[I]file\f[R] as an additional JavaScript file to the generated
-documentation.
-This option can be used one or more times to specify additional script
-files.
-.RS
-.PP
-Command-line example:
-.RS
-.PP
-\f[V]javadoc --add-script first_script.js --add-script second_script.js pkg_foo\f[R]
-.RE
-.RE
-.TP
-\f[V]--add-stylesheet\f[R] \f[I]file\f[R]
-Adds \f[I]file\f[R] as an additional stylesheet file to the generated
-documentation.
-This option can be used one or more times to specify additional
-stylesheets included in the documentation.
-.RS
-.PP
-Command-line example:
-.IP
-.nf
-\f[CB]
-javadoc --add-stylesheet new_stylesheet_1.css --add-stylesheet new_stylesheet_2.css pkg_foo
-\f[R]
-.fi
-.RE
-.TP
-\f[V]--allow-script-in-comments\f[R]
-Allow JavaScript in documentation comments, and options whose value is
-\f[I]html-code\f[R].
-.TP
-\f[V]-author\f[R]
-Includes the text of any \f[V]author\f[R] tags in the generated
-documentation.
-.TP
-\f[V]-bottom\f[R] \f[I]html-code\f[R]
-Specifies the text to be placed at the bottom of each generated page.
-The text can contain HTML tags and white space, but when it does, the
-text must be enclosed in quotation marks.
-Use escape characters for any internal quotation marks within text.
-.TP
-\f[V]-charset\f[R] \f[I]name\f[R]
-Specifies the HTML character set for this document.
-The name should be a preferred MIME name as specified in the \f[B]IANA
-Registry, Character Sets\f[R]
-[http://www.iana.org/assignments/character-sets].
-.RS
-.PP
-For example:
-.IP
-.nf
-\f[CB]
-javadoc -charset \[dq]iso-8859-1\[dq] mypackage
-\f[R]
-.fi
-.PP
-This command inserts the following line, containing a
-\f[B]\f[VB]meta\f[B] element\f[R]
-[https://html.spec.whatwg.org/multipage/semantics.html#the-meta-element]
-in the head of every generated page:
-.IP
-.nf
-\f[CB]
-
-\f[R]
-.fi
-.RE
-.TP
-\f[V]-d\f[R] \f[I]directory\f[R]
-Specifies the destination directory where the \f[V]javadoc\f[R] tool
-saves the generated HTML files.
-If you omit the \f[V]-d\f[R] option, then the files are saved to the
-current directory.
-The \f[V]directory\f[R] value can be absolute or relative to the current
-working directory.
-The destination directory is automatically created when the
-\f[V]javadoc\f[R] tool runs.
-.RS
-.IP \[bu] 2
-\f[B]Linux and macOS:\f[R] For example, the following command generates
-the documentation for the package \f[V]com.mypackage\f[R] and saves the
-results in the \f[V]/user/doc/\f[R] directory:
-.RS 2
-.IP
-.nf
-\f[CB]
-javadoc -d /user/doc/ com.mypackage
-\f[R]
-.fi
-.RE
-.IP \[bu] 2
-\f[B]Windows:\f[R] For example, the following command generates the
-documentation for the package \f[V]com.mypackage\f[R] and saves the
-results in the \f[V]\[rs]user\[rs]doc\[rs]\f[R] directory:
-.RS 2
-.IP
-.nf
-\f[CB]
-javadoc -d \[rs]user\[rs]doc\[rs] com.mypackage
-\f[R]
-.fi
-.RE
-.RE
-.TP
-\f[V]-docencoding\f[R] \f[I]name\f[R]
-Specifies the encoding of the generated HTML files.
-The name should be a preferred MIME name as specified in the \f[B]IANA
-Registry, Character Sets\f[R]
-[http://www.iana.org/assignments/character-sets].
-.RS
-.PP
-Three options are available for use in a \f[V]javadoc\f[R] encoding
-command.
-The \f[V]-encoding\f[R] option is used for encoding the files read by
-the \f[V]javadoc\f[R] tool, while the \f[V]-docencoding\f[R] and
-\f[V]-charset\f[R] options are used for encoding the files written by
-the tool.
-Of the three available options, at most, only the input and an output
-encoding option are used in a single encoding command.
-If you specify both input and output encoding options in a command, they
-must be the same value.
-If you specify neither output option, it defaults to the input encoding.
-.PP
-For example:
-.IP
-.nf
-\f[CB]
-javadoc -docencoding \[dq]iso-8859-1\[dq] mypackage
-\f[R]
-.fi
-.RE
-.TP
-\f[V]-docfilessubdirs\f[R]
-Enables deep copying of \f[V]doc-files\f[R] directories.
-Subdirectories and all contents are recursively copied to the
-destination.
-For example, the directory \f[V]doc-files/example/images\f[R] and all of
-its contents are copied.
-Use the \f[B]\f[VB]-excludedocfilessubdir\f[B]\f[R] option to restrict
-the subdirectories to be copied.
-.TP
-\f[V]-doctitle\f[R] \f[I]html-code\f[R]
-Specifies the title to place near the top of the overview summary file.
-The text specified in the \f[V]title\f[R] tag is placed as a centered,
-level-one heading directly beneath the navigation bar.
-The \f[V]title\f[R] tag can contain HTML tags and white space, but when
-it does, you must enclose the title in quotation marks.
-Additional quotation marks within the \f[V]title\f[R] tag must be
-escaped.
-For example,
-\f[V]javadoc -doctitle \[dq]My Library
v1.0\[dq] com.mypackage\f[R]. -.TP -\f[V]-excludedocfilessubdir\f[R] \f[I]name1\f[R]\f[V],\f[R]\f[I]name2...\f[R] -Excludes any subdirectories with the given names when recursively -copying \f[V]doc-files\f[R] subdirectories. -See \f[B]\f[VB]-docfilessubdirs\f[B]\f[R]. -For historical reasons, \f[V]:\f[R] can be used anywhere in the argument -as a separator instead of \f[V],\f[R]. -.TP -\f[V]-footer\f[R] \f[I]html-code\f[R] -This option is no longer supported and reports a warning. -.TP -\f[V]-group\f[R] \f[I]name\f[R] \f[I]p1\f[R]\f[V],\f[R]\f[I]p2...\f[R] -Group the specified packages together in the Overview page. -For historical reasons, \f[V]:\f[R] can be used as a separator anywhere -in the argument instead of \f[V],\f[R]. -.TP -\f[V]-header\f[R] \f[I]html-code\f[R] -Specifies the header text to be placed at the top of each output file. -The header is placed to the right of the navigation bar. -The \f[V]header\f[R] can contain HTML tags and white space, but when it -does, the \f[V]header\f[R] must be enclosed in quotation marks. -Use escape characters for internal quotation marks within a header. -For example, -\f[V]javadoc -header \[dq]My Library
v1.0\[dq] com.mypackage\f[R]. -.TP -\f[V]-helpfile\f[R] \f[I]filename\f[R] -Specifies a file containing the text that will be displayed when the -\f[B]HELP\f[R] link in the navigation bar is clicked. -If this option is not given, the \f[V]javadoc\f[R] tool creates a -default page that will be used. -.TP -\f[V]-html5\f[R] -This option is a no-op and is just retained for backwards compatibility. -.TP -\f[V]--javafx\f[R] or \f[V]-javafx\f[R] -Enables JavaFX functionality. -This option is enabled by default if the JavaFX library classes are -detected on the module path. -.TP -\f[V]-keywords\f[R] -Adds HTML keyword \f[V]\f[R] tags to the generated file for each -class. -These tags can help search engines that look for \f[V]\f[R] tags -find the pages. -Most search engines that search the entire Internet don\[aq]t look at -\f[V]\f[R] tags, because pages can misuse them. -Search engines offered by companies that confine their searches to their -own website can benefit by looking at \f[V]\f[R] tags. -The \f[V]\f[R] tags include the fully qualified name of the class -and the unqualified names of the fields and methods. -Constructors aren\[aq]t included because they are identical to the class -name. -For example, the page for the class \f[V]String\f[R] includes these -keywords: -.RS -.IP -.nf -\f[CB] - - - - -\f[R] -.fi -.RE -.TP -\f[V]-link\f[R] \f[I]url\f[R] -Creates links to existing \f[V]javadoc\f[R] generated documentation of -externally referenced classes. -The \f[I]url\f[R] argument is the absolute or relative URL of the -directory that contains the external \f[V]javadoc\f[R] generated -documentation. -You can specify multiple \f[V]-link\f[R] options in a specified -\f[V]javadoc\f[R] tool run to link to multiple documents. -.RS -.PP -Either a \f[V]package-list\f[R] or an \f[V]element-list\f[R] file must -be in this \f[I]url\f[R] directory (otherwise, use the -\f[V]-linkoffline\f[R] option). -.PP -\f[I]Note:\f[R] The \f[V]package-list\f[R] and \f[V]element-list\f[R] -files are generated by the \f[V]javadoc\f[R] tool when generating the -API documentation and should not be modified by the user. -.PP -When you use the \f[V]javadoc\f[R] tool to document packages, it uses -the \f[V]package-list\f[R] file to determine the packages declared in an -API. -When you generate API documents for modules, the \f[V]javadoc\f[R] tool -uses the \f[V]element-list\f[R] file to determine the modules and -packages declared in an API. -.PP -The \f[V]javadoc\f[R] tool reads the names from the appropriate list -file and then links to the packages or modules at that URL. -.PP -When the \f[V]javadoc\f[R] tool runs, the \f[I]url\f[R] value is copied -into the \f[V]\f[R] links that are created. -Therefore, \f[I]url\f[R] must be the URL to the directory and not to a -file. -.PP -You can use an absolute link for \f[I]url\f[R] to enable your documents -to link to a document on any web site, or you can use a relative link to -link only to a relative location. -If you use a relative link, then the value you pass in should be the -relative path from the destination directory (specified with the -\f[V]-d\f[R] option) to the directory containing the packages being -linked to. -When you specify an absolute link, you usually use an HTTP link. -However, if you want to link to a file system that has no web server, -then you can use a file link. -Use a file link only when everyone who wants to access the generated -documentation shares the same file system. -In all cases, and on all operating systems, use a slash as the -separator, whether the URL is absolute or relative, and -\f[V]https:\f[R], \f[V]http:\f[R], or \f[V]file:\f[R] as specified in -the \f[B]RFC 1738: Uniform Resource Locators (URL)\f[R] -[https://www.rfc-editor.org/info/rfc1738]. -.IP -.nf -\f[CB] --link https://///.../ --link http://///.../ --link file://///.../ --link //.../ -\f[R] -.fi -.RE -.TP -\f[V]--link-modularity-mismatch\f[R] (\f[V]warn\f[R]|\f[V]info\f[R]) -Specifies whether external documentation with wrong modularity (e.g. -non-modular documentation for a modular library, or the reverse case) -should be reported as a warning (\f[V]warn\f[R]) or just a message -(\f[V]info\f[R]). -The default behavior is to report a warning. -.TP -\f[V]-linkoffline\f[R] \f[I]url1\f[R] \f[I]url2\f[R] -This option is a variation of the \f[V]-link\f[R] option. -They both create links to \f[V]javadoc\f[R] generated documentation for -externally referenced classes. -You can specify multiple \f[V]-linkoffline\f[R] options in a specified -\f[V]javadoc\f[R] tool run. -.RS -.PP -Use the \f[V]-linkoffline\f[R] option when: -.IP \[bu] 2 -Linking to a document on the web that the \f[V]javadoc\f[R] tool -can\[aq]t access through a web connection -.IP \[bu] 2 -The \f[V]package-list\f[R] or \f[V]element-list\f[R] file of the -external document either isn\[aq]t accessible or doesn\[aq]t exist at -the URL location, but does exist at a different location and can be -specified by either the \f[V]package-list\f[R] or \f[V]element-list\f[R] -file (typically local). -.PP -\f[I]Note:\f[R] The \f[V]package-list\f[R] and \f[V]element-list\f[R] -files are generated by the \f[V]javadoc\f[R] tool when generating the -API documentation and should not be modified by the user. -.PP -If \f[I]url1\f[R] is accessible only on the World Wide Web, then the -\f[V]-linkoffline\f[R] option removes the constraint that the -\f[V]javadoc\f[R] tool must have a web connection to generate -documentation. -.PP -Another use of the \f[V]-linkoffline\f[R] option is as a work-around to -update documents. -After you have run the \f[V]javadoc\f[R] tool on a full set of packages -or modules, you can run the \f[V]javadoc\f[R] tool again on a smaller -set of changed packages or modules, so that the updated files can be -inserted back into the original set. -.PP -For example, the \f[V]-linkoffline\f[R] option takes two arguments. -The first is for the string to be embedded in the \f[V]\f[R] -links, and the second tells the \f[V]javadoc\f[R] tool where to find -either the \f[V]package-list\f[R] or \f[V]element-list\f[R] file. -.PP -The \f[I]url1\f[R] or \f[I]url2\f[R] value is the absolute or relative -URL of the directory that contains the external \f[V]javadoc\f[R] -generated documentation that you want to link to. -When relative, the value should be the relative path from the -destination directory (specified with the \f[V]-d\f[R] option) to the -root of the packages being linked to. -See \f[I]url\f[R] in the \f[V]-link\f[R] option. -.RE -.TP -\f[V]--link-platform-properties\f[R] \f[I]url\f[R] -Specifies a properties file used to configure links to platform -documentation. -.RS -.PP -The \f[I]url\f[R] argument is expected to point to a properties file -containing one or more entries with the following format, where -\f[V]\f[R] is the platform version as passed to the -\f[V]--release\f[R] or \f[V]--source\f[R] option and \f[V]\f[R] is -the base URL of the corresponding platform API documentation: -.IP -.nf -\f[CB] -doclet.platform.docs.= -\f[R] -.fi -.PP -For instance, a properties file containing URLs for releases 15 to 17 -might contain the following lines: -.IP -.nf -\f[CB] -doclet.platform.docs.15=https://example.com/api/15/ -doclet.platform.docs.16=https://example.com/api/16/ -doclet.platform.docs.17=https://example.com/api/17/ -\f[R] -.fi -.PP -If the properties file does not contain an entry for a particular -release no platform links are generated. -.RE -.TP -\f[V]-linksource\f[R] -Creates an HTML version of each source file (with line numbers) and adds -links to them from the standard HTML documentation. -Links are created for classes, interfaces, constructors, methods, and -fields whose declarations are in a source file. -Otherwise, links aren\[aq]t created, such as for default constructors -and generated classes. -.RS -.PP -This option exposes all private implementation details in the included -source files, including private classes, private fields, and the bodies -of private methods, regardless of the \f[V]-public\f[R], -\f[V]-package\f[R], \f[V]-protected\f[R], and \f[V]-private\f[R] -options. -Unless you also use the \f[V]-private\f[R] option, not all private -classes or interfaces are accessible through links. -.PP -Each link appears on the name of the identifier in its declaration. -For example, the link to the source code of the \f[V]Button\f[R] class -would be on the word \f[V]Button\f[R]: -.IP -.nf -\f[CB] -public class Button extends Component implements Accessible -\f[R] -.fi -.PP -The link to the source code of the \f[V]getLabel\f[R] method in the -\f[V]Button\f[R] class is on the word \f[V]getLabel\f[R]: -.IP -.nf -\f[CB] -public String getLabel() -\f[R] -.fi -.RE -.TP -\f[V]--main-stylesheet\f[R] \f[I]file\f[R] or \f[V]-stylesheetfile\f[R] \f[I]file\f[R] -Specifies the path of an alternate stylesheet file that contains the -definitions for the CSS styles used in the generated documentation. -This option lets you override the default. -If you do not specify the option, the \f[V]javadoc\f[R] tool will create -and use a default stylesheet. -The file name can be any name and isn\[aq]t restricted to -\f[V]stylesheet.css\f[R]. -The \f[V]--main-stylesheet\f[R] option is the preferred form. -.RS -.PP -Command-line example: -.IP -.nf -\f[CB] -javadoc --main-stylesheet main_stylesheet.css pkg_foo -\f[R] -.fi -.RE -.TP -\f[V]-nocomment\f[R] -Suppresses the entire comment body, including the main description and -all tags, and generate only declarations. -This option lets you reuse source files that were originally intended -for a different purpose so that you can produce skeleton HTML -documentation during the early stages of a new project. -.TP -\f[V]-nodeprecated\f[R] -Prevents the generation of any deprecated API in the documentation. -This does what the \f[V]-nodeprecatedlist\f[R] option does, and it -doesn\[aq]t generate any deprecated API throughout the rest of the -documentation. -This is useful when writing code when you don\[aq]t want to be -distracted by the deprecated code. -.TP -\f[V]-nodeprecatedlist\f[R] -Prevents the generation of the file that contains the list of deprecated -APIs (\f[V]deprecated-list.html\f[R]) and the link in the navigation bar -to that page. -The \f[V]javadoc\f[R] tool continues to generate the deprecated API -throughout the rest of the document. -This is useful when your source code contains no deprecated APIs, and -you want to make the navigation bar cleaner. -.TP -\f[V]--no-fonts\f[R] -Prevents inclusion of font files in the generated documentation. -This can be useful if the documentation uses a custom stylesheet which -does not use the default fonts. -.TP -\f[V]-nohelp\f[R] -Omits the \f[B]HELP\f[R] link in the navigation bar at the top of each -generated page. -.TP -\f[V]-noindex\f[R] -Omits the index from the generated documents. -The index is produced by default. -.TP -\f[V]-nonavbar\f[R] -Prevents the generation of the navigation bar and header. -The \f[V]-nonavbar\f[R] option has no effect on the \f[V]-bottom\f[R] -option. -The \f[V]-nonavbar\f[R] option is useful when you are interested only in -the content and have no need for navigation, such as when you are -converting the files to PostScript or PDF for printing only. -.TP -\f[V]--no-platform-links\f[R] -Prevents the generation of links to platform documentation. -These links are generated by default. -.TP -\f[V]-noqualifier\f[R] \f[I]name1\f[R]\f[V],\f[R]\f[I]name2...\f[R] -Excludes the list of qualifiers from the output. -The package name is removed from places where class or interface names -appear. -For historical reasons, \f[V]:\f[R] can be used anywhere in the argument -as a separator instead of \f[V],\f[R]. -.RS -.PP -The following example omits all package qualifiers: -\f[V]-noqualifier all\f[R]. -.PP -The following example omits \f[V]java.lang\f[R] and \f[V]java.io\f[R] -package qualifiers: \f[V]-noqualifier java.lang:java.io\f[R]. -.PP -The following example omits package qualifiers starting with -\f[V]java\f[R] and \f[V]com.sun\f[R] subpackages, but not -\f[V]javax: -noqualifier java.*:com.sun.*\f[R]. -.PP -Where a package qualifier would appear due to the previous behavior, the -name can be suitably shortened. -This rule is in effect whether or not the \f[V]-noqualifier\f[R] option -is used. -.RE -.TP -\f[V]-nosince\f[R] -Omits from the generated documentation the \f[V]Since\f[R] sections -derived from any \f[V]since\f[R] tags. -.TP -\f[V]-notimestamp\f[R] -Suppresses the time stamp, which is hidden in an HTML comment in the -generated HTML near the top of each page. -The \f[V]-notimestamp\f[R] option is useful when you want to run the -\f[V]javadoc\f[R] tool on two source bases and compare them, because it -prevents time stamps from causing a difference (which would otherwise be -a difference on every page). -The time stamp includes the \f[V]javadoc\f[R] tool release number. -.TP -\f[V]-notree\f[R] -Omits the class and interface hierarchy pages from the generated -documents. -These are the pages you reach using the \f[B]TREE\f[R] link in the -navigation bar. -The hierarchy is produced by default. -.TP -\f[V]--override-methods\f[R] (\f[V]detail\f[R]|\f[V]summary\f[R]) -Documents overridden methods in the detail or summary sections. -The default is \f[V]detail\f[R]. -.TP -\f[V]-overview\f[R] \f[I]filename\f[R] -Specifies that the \f[V]javadoc\f[R] tool should retrieve the content -for the overview documentation from the file specified by -\f[I]filename\f[R] and place it on the Overview page -(\f[V]overview-summary.html\f[R]). -If the \f[I]filename\f[R] is a relative path, it is evaluated relative -to the current working directory. -.RS -.PP -The file may be an HTML file, with a filename ending in \f[V].html\f[R], -or a Markdown file, with a filename ending in \f[V].md\f[R]. -If the file is an HTML file, the content for the overview documentation -is taken from the \f[V]
\f[R] element in the file, if one is -present, or from the \f[V]\f[R] element is there is no -\f[V]
\f[R] element. -If the file is a Markdown file, the entire content of the file is used. -.PP -The title on the overview page is set by \f[V]-doctitle\f[R]. -.PP -\f[I]Note:\f[R] older versions of the \f[V]javadoc\f[R] tool assumed -that any use of this option was for an HTML file, and allowed any -extension for the \f[I]filename\f[R]. -.RE -.TP -\f[V]-serialwarn\f[R] -Reports compile-time warnings for missing \f[V]\[at]serial\f[R] tags. -By default, Javadoc reports no serial warnings. -Use this option to display the serial warnings, which helps to properly -document default serializable fields and \f[V]writeExternal\f[R] -methods. -.TP -\f[V]--since\f[R] \f[I]release\f[R](\f[V],\f[R]\f[I]release\f[R])* -Generates documentation for APIs that were added or newly deprecated in -the specified \f[I]release\f[R]s. -.RS -.PP -If the \f[V]\[at]since\f[R] tag in the \f[V]javadoc\f[R] comment of an -element in the documented source code matches a \f[I]release\f[R] passed -as the option argument, information about the element and the release it -was added in is included in a \[dq]New API\[dq] page. -.PP -If the \[dq]Deprecated API\[dq] page is generated and the -\f[V]since\f[R] element of the \f[V]java.lang.Deprecated\f[R] annotation -of a documented element matches a \f[I]release\f[R] in the option -arguments, information about the release the element was deprecated in -is added to the \[dq]Deprecated API\[dq] page. -.PP -Releases are compared using case-sensitive string comparison. -.RE -.TP -\f[V]--since-label\f[R] \f[I]text\f[R] -Specifies the \f[I]text\f[R] to use in the heading of the \[dq]New -API\[dq] page. -This may contain information about the releases covered in the page, -e.g. -\[dq]New API in release 2.0\[dq], or \[dq]New API since release 1\[dq]. -.TP -\f[V]--snippet-path\f[R] \f[I]snippetpathlist\f[R] -Specifies the search paths for finding files for external snippets. -The \f[I]snippetpathlist\f[R] can contain multiple paths by separating -them with the platform path separator (\f[V];\f[R] on Windows; -\f[V]:\f[R] on other platforms.) -The standard doclet first searches the \f[V]snippet-files\f[R] -subdirectory in the package containing the snippet, and then searches -all the directories in the given list. -.TP -\f[V]-sourcetab\f[R] \f[I]tab-length\f[R] -Specifies the number of spaces each tab uses in the source. -.TP -\f[V]--spec-base-url\f[R] \f[I]url\f[R] -Specifies the base URL for relative URLs in \f[V]\[at]spec\f[R] tags, to -be used when generating links to any external specifications. -It can either be an absolute URL, or a relative URL, in which case it is -evaluated relative to the base directory of the generated output files. -The default value is equivalent to \f[V]{\[at]docRoot}/../specs\f[R]. -.TP -\f[V]-splitindex\f[R] -Splits the index file into multiple files, alphabetically, one file per -letter, plus a file for any index entries that start with -non-alphabetical symbols. -.TP -\f[V]-tag\f[R] \f[I]name\f[R]:\f[I]locations\f[R]:\f[I]header\f[R] -Specifies a custom tag with a single argument. -For the \f[V]javadoc\f[R] tool to spell-check tag names, it is important -to include a \f[V]-tag\f[R] option for every custom tag that is present -in the source code, disabling (with \f[V]X\f[R]) those that aren\[aq]t -being output in the current run. -The colon (\f[V]:\f[R]) is always the separator. -To include a colon in the tag name, escape it with a backward slash -(\f[V]\[rs]\f[R]). -The \f[V]-tag\f[R] option outputs the tag heading, \f[I]header\f[R], in -bold, followed on the next line by the text from its single argument. -Similar to any block tag, the argument text can contain inline tags, -which are also interpreted. -The output is similar to standard one-argument tags, such as the -\f[V]\[at]return\f[R] and \f[V]\[at]author\f[R] tags. -Omitting a \f[I]header\f[R] value causes the \f[I]name\f[R] to be the -heading. -\f[I]locations\f[R] is a list of characters specifying the kinds of -declarations in which the tag may be used. -The following characters may be used, in either uppercase or lowercase: -.RS -.IP \[bu] 2 -\f[V]A\f[R]: all declarations -.IP \[bu] 2 -\f[V]C\f[R]: constructors -.IP \[bu] 2 -\f[V]F\f[R]: fields -.IP \[bu] 2 -\f[V]M\f[R]: methods -.IP \[bu] 2 -\f[V]O\f[R]: the overview page and other documentation files in -\f[V]doc-files\f[R] subdirectories -.IP \[bu] 2 -\f[V]P\f[R]: packages -.IP \[bu] 2 -\f[V]S\f[R]: modules -.IP \[bu] 2 -\f[V]T\f[R]: types (classes and interfaces) -.IP \[bu] 2 -\f[V]X\f[R]: nowhere: the tag is disabled, and will be ignored -.PP -The order in which tags are given on the command line will be used as -the order in which the tags appear in the generated output. -You can include standard tags in the order given on the command line by -using the \f[V]-tag\f[R] option with no \f[I]locations\f[R] or -\f[I]header\f[R]. -.RE -.TP -\f[V]-taglet\f[R] \f[I]class\f[R] -Specifies the fully qualified name of the taglet used in generating the -documentation for that tag. -Use the fully qualified name for the \f[I]class\f[R] value. -This taglet also defines the number of text arguments that the custom -tag has. -The taglet accepts those arguments, processes them, and generates the -output. -.RS -.PP -Taglets are useful for block or inline tags. -They can have any number of arguments and implement custom behavior, -such as making text bold, formatting bullets, writing out the text to a -file, or starting other processes. -Taglets can only determine where a tag should appear and in what form. -All other decisions are made by the doclet. -A taglet can\[aq]t do things such as remove a class name from the list -of included classes. -However, it can execute side effects, such as printing the tag\[aq]s -text to a file or triggering another process. -Use the \f[V]-tagletpath\f[R] option to specify the path to the taglet. -The following example inserts the To Do taglet after Parameters and -ahead of Throws in the generated pages. -.IP -.nf -\f[CB] --taglet com.sun.tools.doclets.ToDoTaglet --tagletpath /home/taglets --tag return --tag param --tag todo --tag throws --tag see -\f[R] -.fi -.PP -Alternately, you can use the \f[V]-taglet\f[R] option in place of its -\f[V]-tag\f[R] option, but that might be difficult to read. -.RE -.TP -\f[V]-tagletpath\f[R] \f[I]tagletpathlist\f[R] -Specifies the search paths for finding taglet class files. -The \f[I]tagletpathlist\f[R] can contain multiple paths by separating -them with the platform path separator (\f[V];\f[R] on Windows; -\f[V]:\f[R] on other platforms.) -The \f[V]javadoc\f[R] tool searches all subdirectories of the specified -paths. -.TP -\f[V]-top\f[R] \f[I]html-code\f[R] -Specifies the text to be placed at the top of each output file. -.TP -\f[V]-use\f[R] -Creates class and package usage pages. -Includes one Use page for each documented class and package. -The page describes what packages, classes, methods, constructors, and -fields use any API of the specified class or package. -Given class C, things that use class C would include subclasses of C, -fields declared as C, methods that return C, and methods and -constructors with parameters of type C. -For example, you can look at the Use page for the \f[V]String\f[R] type. -Because the \f[V]getName\f[R] method in the \f[V]java.awt.Font\f[R] -class returns type \f[V]String\f[R], the \f[V]getName\f[R] method uses -\f[V]String\f[R] and so the \f[V]getName\f[R] method appears on the Use -page for \f[V]String\f[R]. -This documents only uses of the API, not the implementation. -When a method uses \f[V]String\f[R] in its implementation, but -doesn\[aq]t take a string as an argument or return a string, that -isn\[aq]t considered a use of \f[V]String\f[R]. -To access the generated Use page, go to the class or package and click -the \f[B]USE\f[R] link in the navigation bar. -.TP -\f[V]-version\f[R] -Includes the text of any \f[V]version\f[R] tags in the generated -documentation. -This text is omitted by default. -Note: To find out what version of the \f[V]javadoc\f[R] tool you are -using, use the \f[V]--version\f[R] option (with two hyphens). -.TP -\f[V]-windowtitle\f[R] \f[I]title\f[R] -Specifies the title to be placed in the HTML \f[V]\f[R] tag. -The text specified in the \f[V]title\f[R] tag appears in the window -title and in any browser bookmarks (favorite places) that someone -creates for this page. -This title should not contain any HTML tags because a browser will not -interpret them correctly. -Use escape characters on any internal quotation marks within the -\f[V]title\f[R] tag. -If the \f[V]-windowtitle\f[R] option is omitted, then the -\f[V]javadoc\f[R] tool uses the value of the \f[V]-doctitle\f[R] option -for the \f[V]-windowtitle\f[R] option. -For example, -\f[V]javadoc -windowtitle \[dq]My Library\[dq] com.mypackage\f[R]. -.SS Extra Options for the Standard Doclet -.PP -The following are additional options provided by the standard doclet and -are subject to change without notice. -Additional options are less commonly used or are otherwise regarded as -advanced. -.TP -\f[V]--date\f[R] \f[I]date-and-time\f[R] -Specifies the value to be used to timestamp the generated pages, in -\f[B]ISO 8601\f[R] -[https://www.iso.org/iso-8601-date-and-time-format.html] format. -The specified value must be within 10 years of the current date and -time. -It is an error to specify both \f[V]-notimestamp\f[R] and -\f[V]--date\f[R]. -Using a specific value means the generated documentation can be part of -a \f[B]reproducible build\f[R] [https://reproducible-builds.org/]. -If the option is not given, the default value is the current date and -time. -For example: -.RS -.IP -.nf -\f[CB] -javadoc --date 2022-02-01T17:41:59-08:00 mypackage -\f[R] -.fi -.RE -.TP -\f[V]--legal-notices\f[R] (\f[V]default\f[R]|\f[V]none\f[R]|\f[I]directory\f[R]) -Specifies the location from which to copy legal files to the generated -documentation. -If the option is not specified or is used with the value -\f[V]default\f[R], the files are copied from the default location. -If the argument is used with value \f[V]none\f[R], no files are copied. -Every other argument is interpreted as directory from which to copy the -legal files. -.TP -\f[V]--no-frames\f[R] -This option is no longer supported and reports a warning. -.TP -\f[V]-Xdoclint\f[R] -Enables recommended checks for problems in documentation comments. -.RS -.PP -By default, the \f[V]-Xdoclint\f[R] option is enabled. -Disable it with the option \f[V]-Xdoclint:none\f[R]. -.PP -For more details, see \f[B]DocLint\f[R]. -.RE -.TP -\f[V]-Xdoclint:\f[R]\f[I]flag\f[R],\f[I]flag\f[R],... -Enables or disables specific checks for different kinds of issues in -documentation comments. -.RS -.PP -Each \f[I]flag\f[R] can be one of \f[V]all\f[R], \f[V]none\f[R], or -\f[V][-]\f[R]\f[I]group\f[R] where \f[I]group\f[R] has one of the -following values: \f[V]accessibility\f[R], \f[V]html\f[R], -\f[V]missing\f[R], \f[V]reference\f[R], \f[V]syntax\f[R]. -For more details on these values, see \f[B]DocLint Groups\f[R]. -.PP -When specifying two or more flags, you can either use a single -\f[V]-Xdoclint:...\f[R] option, listing all the desired flags, or you -can use multiple options giving one or more flag in each option. -For example, use either of the following commands to check for the HTML, -syntax, and accessibility issues in the file \f[V]MyFile.java\f[R]. -.IP -.nf -\f[CB] -javadoc -Xdoclint:html -Xdoclint:syntax -Xdoclint:accessibility MyFile.java -javadoc -Xdoclint:html,syntax,accessibility MyFile.java -\f[R] -.fi -.PP -The following examples illustrate how to change what DocLint reports: -.IP \[bu] 2 -\f[V]-Xdoclint:none\f[R] --- disables all checks -.IP \[bu] 2 -\f[V]-Xdoclint:\f[R]\f[I]group\f[R] --- enables \f[I]group\f[R] checks -.IP \[bu] 2 -\f[V]-Xdoclint:all\f[R] --- enables all groups of checks -.IP \[bu] 2 -\f[V]-Xdoclint:all,-\f[R]\f[I]group\f[R] --- enables all checks except -\f[I]group\f[R] checks -.PP -For more details, see \f[B]DocLint\f[R]. -.RE -.TP -\f[V]-Xdoclint/package:\f[R][\f[V]-\f[R]]\f[I]packages\f[R] -Enables or disables checks in specific packages. -\f[I]packages\f[R] is a comma separated list of package specifiers. -A package specifier is either a qualified name of a package or a package -name prefix followed by \f[V]*\f[R], which expands to all subpackages of -the given package. -Prefix the package specifier with \f[V]-\f[R] to disable checks for the -specified packages. -.RS -.PP -For more details, see \f[B]DocLint\f[R]. -.RE -.TP -\f[V]-Xdocrootparent\f[R] \f[I]url\f[R] -Replaces all \f[V]\[at]docRoot\f[R] items followed by \f[V]/..\f[R] in -documentation comments with \f[I]url\f[R]. -.SH DOCLINT -.PP -DocLint provides the ability to check for possible problems in -documentation comments. -Problems may be reported as warnings or errors, depending on their -severity. -For example, a missing comment may be bad style that deserves a warning, -but a link to an unknown Java declaration is more serious and deserves -an error. -Problems are organized into \f[B]groups\f[R], and options can be used to -enable or disable messages in one or more groups. -Within the source code, messages in one or more groups can be -\f[B]suppressed\f[R] by using \f[V]\[at]SuppressWarnings\f[R] -annotations. -.PP -When invoked from \f[V]javadoc\f[R], by default DocLint checks all -comments that are used in the generated documentation. -It thus relies on other command-line options to determine which -declarations, and which corresponding documentation comments will be -included. -\f[I]Note:\f[R] this may mean that even comments on some private members -of serializable classes will also be checked, if the members need to be -documented in the generated \f[V]Serialized Forms\f[R] page. -.PP -In contrast, when DocLint is invoked from \f[V]javac\f[R], DocLint -solely relies on the various \f[V]-Xdoclint...\f[R] options to determine -which documentation comments to check. -.PP -DocLint doesn\[aq]t attempt to fix invalid input, it just reports it. -.PP -\f[I]Note:\f[R] DocLint doesn\[aq]t guarantee the completeness of these -checks. -In particular, it isn\[aq]t a full HTML compliance checker. -The goal is to just report common errors in a convenient manner. -.SS Groups -.PP -The checks performed by DocLint are organized into groups. -The warnings and errors in each group can be enabled or disabled with -command-line options, or suppressed with \f[V]\[at]SuppressWarnings\f[R] -annotations. -.PP -The groups are as follows: -.IP \[bu] 2 -\f[V]accessibility\f[R] --- Checks for issues related to accessibility. -For example, no \f[V]alt\f[R] attribute specified in an \f[V]<img>\f[R] -element, or no caption or summary attributes specified in a -\f[V]<table>\f[R] element. -.RS 2 -.PP -Issues are reported as errors if a downstream validation tool might be -expected to report an error in the files generated by \f[V]javadoc\f[R]. -.PP -For reference, see the \f[B]Web Content Accessibility Guidelines\f[R] -[https://www.w3.org/WAI/standards-guidelines/wcag/]. -.RE -.IP \[bu] 2 -\f[V]html\f[R] --- Detects common high-level HTML issues. -For example, putting block elements inside inline elements, or not -closing elements that require an end tag. -.RS 2 -.PP -Issues are reported as errors if a downstream validation tool might be -expected to report an error in the files generated by \f[V]javadoc\f[R]. -.PP -For reference, see the \f[B]HTML Living Standard\f[R] -[https://html.spec.whatwg.org/multipage/]. -.RE -.IP \[bu] 2 -\f[V]missing\f[R] --- Checks for missing documentation comments or tags. -For example, a missing comment on a class declaration, or a missing -\f[V]\[at]param\f[R] or \f[V]\[at]return\f[R] tag in the comment for a -method declaration. -.RS 2 -.PP -Issues related to missing items are typically reported as warnings -because they are unlikely to be reported as errors by downstream -validation tools that may be used to check the output generated by -\f[V]javadoc\f[R]. -.RE -.IP \[bu] 2 -\f[V]reference\f[R] --- Checks for issues relating to the references to -Java API elements from documentation comment tags. -For example, the reference in \f[V]\[at]see\f[R] or -\f[V]{\[at]link ...}\f[R] cannot be found, or a bad name is given for -\f[V]\[at]param\f[R] or \f[V]\[at]throws\f[R]. -.RS 2 -.PP -Issues are typically reported as errors because while the issue may not -cause problems in the generated files, the author has likely made a -mistake that will lead to incorrect or unexpected documentation. -.RE -.IP \[bu] 2 -\f[V]syntax\f[R] --- Checks for low-level syntactic issues in -documentation comments. -For example, unescaped angle brackets (\f[V]<\f[R] and \f[V]>\f[R]) and -ampersands (\f[V]&\f[R]) and invalid documentation comment tags. -.RS 2 -.PP -Issues are typically reported as errors because the issues may lead to -incorrect or unexpected documentation. -.RE -.SS Suppressing Messages -.PP -DocLint checks for and recognizes two strings that may be present in the -arguments for an \f[V]\[at]SuppressWarnings\f[R] annotation. -.IP \[bu] 2 -\f[V]doclint\f[R] -.IP \[bu] 2 -\f[V]doclint:\f[R]\f[I]LIST\f[R] -.PP -where \f[I]LIST\f[R] is a comma-separated list of one or more of -\f[V]accessibility\f[R], \f[V]html\f[R], \f[V]missing\f[R], -\f[V]reference\f[R], \f[V]syntax\f[R]. -.PP -The names in \f[I]LIST\f[R] are the same \f[B]group\f[R] names supported -by the command-line \f[V]-Xdoclint\f[R] option for \f[V]javac\f[R] and -\f[V]javadoc\f[R]. -(This is the same convention honored by the \f[V]javac\f[R] -\f[V]-Xlint\f[R] option and the corresponding names supported by -\f[V]\[at]SuppressWarnings\f[R].) -.PP -The names in \f[I]LIST\f[R] can equivalently be specified in separate -arguments of the annotation. -For example, the following are equivalent: -.IP \[bu] 2 -\f[V]\[at]SuppressWarnings(\[dq]doclint:accessibility,missing\[dq])\f[R] -.IP \[bu] 2 -\f[V]\[at]SuppressWarnings(\[dq]doclint:accessibility\[dq], \[dq]doclint:missing\[dq])\f[R] -.PP -When DocLint detects an issue in a documentation comment, it checks for -the presence of \f[V]\[at]SuppressWarnings\f[R] on the associated -declaration and on all lexically enclosing declarations. -The issue will be ignored if any such annotation is found containing the -simple string \f[V]doclint\f[R] or the longer form -\f[V]doclint:LIST\f[R] where \f[I]LIST\f[R] contains the name of the -group for the issue. -.PP -\f[I]Note:\f[R] as with other uses of \f[V]\[at]SuppressWarnings\f[R], -using the annotation on a module or package declaration only affects -that declaration; it does not affect the contents of the module or -package in other source files. -.PP -All messages related to an issue are suppressed by the presence of an -appropriate \f[V]\[at]SuppressWarnings\f[R] annotation: this includes -errors as well as warnings. -.PP -\f[I]Note:\f[R] It is only possible to \f[I]suppress\f[R] messages. -If an annotation of \f[V]\[at]SuppressWarnings(\[dq]doclint\[dq])\f[R] -is given on a top-level declaration, all DocLint messages for that -declaration and any enclosed declarations will be suppressed; it is not -possible to selectively re-enable messages for issues in enclosed -declarations. -.SS Comparison with downstream validation tools -.PP -DocLint is a utility built into \f[V]javac\f[R] and \f[V]javadoc\f[R] -that checks the content of documentation comments, as found in source -files. -In contrast, downstream validation tools can be used to validate the -output generated from those documentation comments by \f[V]javadoc\f[R] -and the standard doclet. -.PP -Although there is some overlap in functionality, the two mechanisms are -different and each has its own strengths and weaknesses. -.IP \[bu] 2 -Downstream validation tools can check the end result of any generated -documentation, as it will be seen by the end user. -This includes content from all sources, including documentation -comments, the standard doclet itself, user-provided taglets, and content -supplied via command-line options. -Because such tools are analyzing complete HTML pages, they can do more -complete checks than can DocLint. -However, when a problem is found in the generated pages, it can be -harder to track down exactly where in the build pipeline the problem -needs to be fixed. -.IP \[bu] 2 -DocLint checks the content of documentation comments, in source files. -This makes it very easy to identify the exact position of any issues -that may be found. -DocLint can also detect some semantic errors in documentation comments -that downstream tools cannot detect, such as missing comments, using an -\f[V]\[at]return\f[R] tag in a method returning \f[V]void\f[R], or an -\f[V]\[at]param\f[R] tag describing a non-existent parameter. -But by its nature, DocLint cannot report on problems such as missing -links, or errors in user-provided custom taglets, or problems in the -standard doclet itself. -It also cannot reliably detect errors in documentation comments at the -boundaries between content in a documentation comment and content -generated by a custom taglet. diff --git a/src/jdk.javadoc/share/man/javadoc.md b/src/jdk.javadoc/share/man/javadoc.md new file mode 100644 index 00000000000..6a1a92e7d16 --- /dev/null +++ b/src/jdk.javadoc/share/man/javadoc.md @@ -0,0 +1,1214 @@ +--- +# Copyright (c) 1994, 2024, 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. +# + +title: 'JAVADOC(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +javadoc - generate HTML pages of API documentation from Java source files + +## Synopsis + +`javadoc` \[*options*\] \[*packagenames*\] \[*sourcefiles*\] \[`@`*files*\] + +*options* +: Specifies command-line options, separated by spaces. See [Standard `javadoc` + Options], [Extra `javadoc` Options], [Standard Options for the Standard Doclet], + and [Extra Options for the Standard Doclet]. + +*packagenames* +: Specifies names of packages that you want to document, separated by spaces, + for example `java.lang java.lang.reflect java.awt`. If you want to also + document the subpackages, then use the `-subpackages` option to specify the + packages. + + By default, `javadoc` looks for the specified packages in the current + directory and subdirectories. Use the `-sourcepath` option to specify the + list of directories where to look for packages. + +*sourcefiles* +: Specifies names of Java source files that you want to document, separated + by spaces, for example `Class.java Object.java Button.java`. By default, + `javadoc` looks for the specified classes in the current directory. + However, you can specify the full path to the class file and use wildcard + characters, for example `/home/src/java/awt/Graphics*.java`. You can also + specify the path relative to the current directory. + +`@`*files* +: Specifies names of files that contain a list of `javadoc` tool options, + package names, and source file names in any order. + +## Description + +The `javadoc` tool parses the declarations and documentation comments in a set +of Java source files and processes them using a pluggable back-end called a +[_doclet_][doclet]. + +The [_standard doclet_][standard-doclet] is the one that is used by default, +and can produce corresponding HTML pages that describe the public and protected +classes, nested and implicitly declared classes (but not anonymous inner classes), +interfaces, constructors, methods, and fields. The standard doclet interprets +the content of documentation comments according to the +[JavaDoc Documentation Comment Specification for the Standard Doclet][doc-comment-spec]. +Custom tags in documentation comments are supported by means of [taglets][taglet]. + +You can use the `javadoc` tool and the standard doclet to generate the API +documentation or the implementation documentation for a set of source files. + +You can run the `javadoc` tool on entire packages, individual source files, or +both. When documenting entire packages, you can use the `-subpackages` option +either to recursively traverse a directory and its subdirectories, or to pass +in an explicit list of package names. When you document individual source +files, pass in a list of Java source file names. + +### Documentation Comments + +The `javadoc` tool uses the documentation comment, if any, that immediately +precedes the beginning of the declaration, whether that is an annotation, +modifier, or the name being declared. If there are multiple documentation +comments before the declaration, only the last one (closest to the declaration) +will be used. If there are any documentation comments after the beginning of +the declaration, they will be ignored. To check for any extra or misplaced +documentation comments, compile your source code with the `javac` option +`-Xlint`, or more specifically, `-Xlint:dangling-doc-comments`. Within a +source file, you may suppress any warnings generated by these options +by using `@SuppressWarnings("dangling-doc-comments")` on a suitable enclosing +declaration. + +[doc-comment-spec]: ../javadoc/doc-comment-spec.html +[doclet]: ../../api/jdk.javadoc/jdk/javadoc/doclet/Doclet.html +[standard-doclet]: ../../api/jdk.javadoc/jdk/javadoc/doclet/StandardDoclet.html +[taglet]: ../../api/jdk.javadoc/jdk/javadoc/doclet/Taglet.html + +### Conformance + +The standard doclet does not validate the content of documentation comments for +conformance, nor does it attempt to correct any errors in documentation +comments. Anyone running javadoc is advised to be aware of the problems that +may arise when generating non-conformant output or output containing executable +content, such as JavaScript. The standard doclet does provide the [DocLint](#doclint) +feature to help developers detect common problems in documentation comments; +but it is also recommended to check the generated output with any appropriate +conformance and other checking tools. + +For more details on the conformance requirements for HTML5 documents, see +[Conformance requirements for authors]( +https://html.spec.whatwg.org/multipage/introduction.html#conformance-requirements-for-authors) +in the HTML5 Specification. For more details on security issues related to web +pages, see the [Open Web Application Security Project (OWASP)]( +https://www.owasp.org) page. + +## Options + +`javadoc` supports command-line options for both the main `javadoc` tool +and the currently selected doclet. The standard doclet is used if no other +doclet is specified. + +GNU-style options (that is, those beginning with `--`) can use an equal sign +(`=`) instead of whitespace characters to separate the name of an option from +its value. + +### Standard `javadoc` Options + +The following core `javadoc` options are equivalent to corresponding `javac` +options. See *Standard Options* in [javac](javac.html) for the detailed +descriptions of using these options: + +* <span id="option-add-modules">`--add-modules`</span> +* <span id="option-bootclasspath">`-bootclasspath`</span> +* <span id="option-class-path">`--class-path`, `-classpath`, or `-cp`</span> +* <span id="option-disable-line-doc-comments">`--disable-line-doc-comments`</span> +* <span id="option-enable-preview">`--enable-preview`</span> +* <span id="option-encoding">`-encoding`</span> +* <span id="option-extdirs">`-extdirs`</span> +* <span id="option-limit-modules">`--limit-modules`</span> +* <span id="option-module">`--module`</span> +* <span id="option-module-path">`--module-path` or `-p`</span> +* <span id="option-module-source-path">`--module-source-path`</span> +* <span id="option-release">`--release`</span> +* <span id="option-source">`--source` or `-source`</span> +* <span id="option-source-path">`--source-path` or `-sourcepath`</span> +* <span id="option-system">`--system`</span> +* <span id="option-upgrade-module-path">`--upgrade-module-path`</span> + +The following options are the core `javadoc` options that are not equivalent to +a corresponding `javac` option: + +<span id="option-breakiterator">`-breakiterator`</span> +: Computes the first sentence of the description in a documentation comment + using an instance of `java.text.BreakIterator` to detect _sentence breaks_. + The rules that are used depend on the [current locale](#option-locale): + for example, for English, a sentence break occurs after a period, question mark, + or exclamation point followed by a space when the next word starts with a + capital letter. (This is meant to handle most abbreviations, such as + "The serial no. is valid", but will not handle "Mr. Smith".) + + The option is enabled by default if the language of the current locale is + not English. If the language of the current locale is English, and the + `-breakiterator` option is not given, a simple default algorithm is used, + which just looks for a period followed by a space. + + In a traditional `/**...*/` comment, the search for the end of the first + sentence is terminated by an HTML block tag, such as `<p>`, `<pre>`, or + the tag for a heading. + + In a Markdown `///` comment, the search for the end of the first sentence + skips over any characters enclosed in code spans and links, and is + terminated by the end of the initial block, as indicated by a + blank line or the beginning of the next block, such as a list, thematic break, + or an HTML block. + + The first sentence of the description in a documentation comment is used in + summary tables, index pages, and other situations where a short summary is + required. For more explicit control in any individual documentation comment, + enclose the contents of the first sentence in a `{@summary ...}` tag, or + when applicable, in a `{@return ...}` tag. + +<span id="option-doclet">`-doclet` *class*</span> +: Generates output by using an alternate doclet. Use the fully qualified + name. This doclet defines the content and formats the output. If the + `-doclet` option isn't used, then the `javadoc` tool uses the standard + doclet for generating the default HTML format. This class must implement + the `jdk.javadoc.doclet.Doclet` interface. The path to this class is + defined by the `-docletpath` option. + +<span id="option-docletpath">`-docletpath` *path*</span> +: Specifies where to find doclet class files (specified with the `-doclet` + option) and any JAR files it depends on. If the starting class file is in a + JAR file, then this option specifies the path to that JAR file. You can + specify an absolute path or a path relative to the current directory. If + `path` contains multiple paths or JAR files, then they should be + separated with a colon (`:`) on Linux and macOS, and a semicolon (`;`) on + Windows. This option isn't necessary when the `doclet` starting class is + already in the search path. + +<span id="option-exclude">`-exclude` *pkglist*</span> +: Unconditionally, excludes the specified packages and their subpackages from + the list formed by `-subpackages`. It excludes those packages even when + they would otherwise be included by some earlier or later `-subpackages` + option. + + The following example would include `java.io`, `java.util`, and `java.math` + (among others), but would exclude packages rooted at `java.net` and + `java.lang`. Notice that these examples exclude `java.lang.ref`, which is a + subpackage of `java.lang`. Arguments are separated by colons on all + operating systems. + + - **Linux and macOS:** + + ``` + javadoc -sourcepath /home/user/src -subpackages java -exclude java.net:java.lang + ``` + + - **Windows:** + + ``` + javadoc -sourcepath \user\src -subpackages java -exclude java.net:java.lang + ``` + +<span id="option-expand-requires">`--expand-requires` (`transitive`|`all`)</span> +: Instructs the javadoc tool to expand the set of modules to be documented. + By default, only the modules given explicitly on the command line are + documented. Supports the following values: + + - `transitive`: additionally includes all the required transitive + dependencies of those modules. + + - `all`: includes all dependencies. + +<span id="option-help">`--help`, `-help`, `-h`, or `-?`</span> +: Prints a synopsis of the standard options. + +<span id="option-help-extra">`--help-extra` or `-X`</span> +: Prints a synopsis of the set of extra options. + +<span id="option-J">`-J`*flag*</span> +: Passes *flag* directly to the Java Runtime Environment (JRE) that runs the + `javadoc` tool. For example, if you must ensure that the system sets aside + 32 MB of memory in which to process the generated documentation, then you + would call the `-Xmx` option as follows: + `javadoc -J-Xmx32m -J-Xms32m com.mypackage`. Be aware that `-Xms` is + optional because it only sets the size of initial memory, which is useful + when you know the minimum amount of memory required. + + There is no space between the `J` and the `flag`. + + Use the `-version` option to report the version of the JRE being used to + run the `javadoc` tool. + + ``` + javadoc -J-version + java version "17" 2021-09-14 LTS + Java(TM) SE Runtime Environment (build 17+35-LTS-2724) + Java HotSpot(TM) 64-Bit Server VM (build 17+35-LTS-2724, mixed mode, sharing) + ``` + +<span id="option-locale">`-locale` *name*</span> +: Specifies the locale that the `javadoc` tool uses when it generates + documentation. The argument is the name of the locale, as described in + `java.util.Locale` documentation, such as `en_US` (English, United States) + or `en_US_WIN` (Windows variant). + + Specifying a locale causes the `javadoc` tool to choose the resource files + of that locale for messages such as strings in the navigation bar, headings + for lists and tables, help file contents, comments in the `stylesheet.css` + file, and so on. It also specifies the sorting order for lists sorted + alphabetically, and the sentence separator to determine the end of the + first sentence. The `-locale` option doesn't determine the locale of the + documentation comment text specified in the source files of the documented + classes. + +<span id="option-package">`-package`</span> +: Shows only package, protected, and public classes and members. + +<span id="option-private">`-private`</span> +: Shows all classes and members. + +<span id="option-protected">`-protected`</span> +: Shows only protected and public classes and members. This is the default. + +<span id="option-public">`-public`</span> +: Shows only the public classes and members. + +<span id="option-quiet">`-quiet`</span> +: Shuts off messages so that only the warnings and errors appear to make them + easier to view. It also suppresses the `version` string. + +<span id="option-show-members">`--show-members` *value*</span> +: Specifies which members (fields, methods, or constructors) are documented, + where *value* can be any of the following: + + * `public` --- shows only public members + * `protected` --- shows public and protected members; this is the default + * `package` --- shows public, protected, and package members + * `private` --- shows all members + +<span id="option-show-module-contents">`--show-module-contents` *value*</span> +: Specifies the documentation granularity of module declarations, where + *value* can be `api` or `all`. + +<span id="option-show-packages">`--show-packages` *value*</span> +: Specifies which module packages are documented, where *value* can be + `exported` or `all` packages. + +<span id="option-show-types">`--show-types` *value*</span> +: Specifies which types (classes, interfaces, etc.) are documented, where + *value* can be any of the following: + + * `public` --- shows only public types + * `protected` --- shows public and protected types; this is the default + * `package` --- shows public, protected, and package types + * `private` --- shows all types + +<span id="option-subpackages">`-subpackages` *subpkglist*</span> +: Generates documentation from source files in the specified packages and + recursively in their subpackages. This option is useful when adding new + subpackages to the source code because they are automatically included. + Each package argument is any top-level subpackage (such as `java`) or fully + qualified package (such as `javax.swing`) that doesn't need to contain + source files. Arguments are separated by colons on all operating systems. + Wild cards aren't allowed. Use `-sourcepath` to specify where to find the + packages. This option doesn't process source files that are in the source + tree but don't belong to the packages. + + For example, the following commands generates documentation for packages + named `java` and `javax.swing` and all of their subpackages. + + - **Linux and macOS:** + + ``` + javadoc -d docs -sourcepath /home/user/src -subpackages java:javax.swing + ``` + + - **Windows:** + + ``` + javadoc -d docs -sourcepath \user\src -subpackages java:javax.swing + ``` + +<span id="option-verbose">`-verbose`</span> +: Provides more detailed messages while the `javadoc` tool runs. Without the + `-verbose` option, messages appear for loading the source files, generating + the documentation (one message per source file), and sorting. The + `-verbose` option causes the printing of additional messages that specify + the number of milliseconds to parse each Java source file. + +<span id="option--version">`--version`</span> +: Prints version information. + +<span id="option-Werror">`-Werror`</span> +: Reports an error if any warnings occur. + +Note that if a Java source file contains an implicitly declared class, then +that class and its public, protected, and package members will be documented +regardless of the options such as `--show-types`, `--show-members`, `-private`, +`-protected`, `-package`, and `-public`. If `--show-members` is specified with +value `private` or if `-private` is used then all private members of an +implicitly declared class will be documented too. + +### Extra `javadoc` Options + +_Note:_ The additional options for `javadoc` are subject to change without +notice. + +The following additional `javadoc` options are equivalent to corresponding +`javac` options. See *Extra Options* in [javac](javac.html) for the detailed +descriptions of using these options: + +* <span id="option-add-exports">`--add-exports`</span> +* <span id="option-add-reads">`--add-reads`</span> +* <span id="option-patch-module">`--patch-module`</span> +* <span id="option-Xmaxerrs">`-Xmaxerrs`</span> +* <span id="option-Xmaxwarns">`-Xmaxwarns`</span> + +### Standard Options for the Standard Doclet + +The following options are provided by the standard doclet. + +<span id="option-add-script">`--add-script` *file*</span> +: Adds *file* as an additional JavaScript file to the generated documentation. + This option can be used one or more times to specify additional script + files. + + Command-line example: + + > `javadoc --add-script first_script.js --add-script + second_script.js pkg_foo` + +<span id="option-add-stylesheet">`--add-stylesheet` *file*</span> +: Adds *file* as an additional stylesheet file to the generated documentation. + This option can be used one or more times to specify additional stylesheets + included in the documentation. + + Command-line example: + + ``` + javadoc --add-stylesheet new_stylesheet_1.css --add-stylesheet new_stylesheet_2.css pkg_foo + ``` + +<span id="option-allow-script-in-comments">`--allow-script-in-comments`</span> +: Allow JavaScript in documentation comments, and options whose value is + _html-code_. + +<span id="option-author">`-author`</span> +: Includes the text of any `author` tags in the generated documentation. + +<span id="option-bottom">`-bottom` *html-code*</span> +: Specifies the text to be placed at the bottom of each generated page. + The text can contain HTML tags and white space, but when it does, the text + must be enclosed in quotation marks. Use escape characters for any internal + quotation marks within text. + +<span id="option-charset">`-charset` *name*</span> +: Specifies the HTML character set for this document. The name should be a + preferred MIME name as specified in the [IANA Registry, Character Sets]( + http://www.iana.org/assignments/character-sets). + + For example: + + ``` + javadoc -charset "iso-8859-1" mypackage + ``` + + This command inserts the following line, containing a + [`meta` element](https://html.spec.whatwg.org/multipage/semantics.html#the-meta-element) + in the head of every generated page: + + ``` + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + ``` + +<span id="option-d">`-d` *directory*</span> +: Specifies the destination directory where the `javadoc` tool saves the + generated HTML files. If you omit the `-d` option, then the files are saved + to the current directory. The `directory` value can be absolute or relative + to the current working directory. The destination directory is + automatically created when the `javadoc` tool runs. + + - **Linux and macOS:** For example, the following command + generates the documentation for the package `com.mypackage` and saves + the results in the `/user/doc/` directory: + + ``` + javadoc -d /user/doc/ com.mypackage + ``` + + - **Windows:** For example, the following command generates the + documentation for the package `com.mypackage` and saves the results in + the `\user\doc\` directory: + + ``` + javadoc -d \user\doc\ com.mypackage + ``` + +<span id="option-docencoding">`-docencoding` *name*</span> +: Specifies the encoding of the generated HTML files. The name should be a + preferred MIME name as specified in the [IANA Registry, Character Sets]( + http://www.iana.org/assignments/character-sets). + + Three options are available for use in a `javadoc` encoding command. The + `-encoding` option is used for encoding the files read by the `javadoc` + tool, while the `-docencoding` and `-charset` options are used for encoding + the files written by the tool. Of the three available options, at most, + only the input and an output encoding option are used in a single encoding + command. If you specify both input and output encoding options in a + command, they must be the same value. If you specify neither output option, + it defaults to the input encoding. + + For example: + + ``` + javadoc -docencoding "iso-8859-1" mypackage + ``` + +<span id="option-docfilessubdirs">`-docfilessubdirs`</span> +: Enables deep copying of `doc-files` directories. Subdirectories and all + contents are recursively copied to the destination. For example, the + directory `doc-files/example/images` and all of its contents are copied. + Use the [`-excludedocfilessubdir`](#option-excludedocfilessubdir) option to + restrict the subdirectories to be copied. + +<span id="option-doctitle">`-doctitle` *html-code*</span> +: Specifies the title to place near the top of the overview summary file. The + text specified in the `title` tag is placed as a centered, level-one + heading directly beneath the navigation bar. The `title` tag can + contain HTML tags and white space, but when it does, you must enclose the + title in quotation marks. Additional quotation marks within the `title` tag + must be escaped. For example, + `javadoc -doctitle "<b>My Library</b><br>v1.0" com.mypackage`. + +<span id="option-excludedocfilessubdir">`-excludedocfilessubdir` *name1*`,`*name2...*</span> +: Excludes any subdirectories with the given names + when recursively copying `doc-files` subdirectories. + See [`-docfilessubdirs`](#option-docfilessubdirs). + For historical reasons, `:` can be used anywhere in the argument as a + separator instead of `,`. + +<span id="option-footer">`-footer` *html-code*</span> +: This option is no longer supported and reports a warning. + +<span id="option-group">`-group` *name* *p1*`,`*p2...*</span> +: Group the specified packages together in the Overview page. + For historical reasons, `:` can be used as a separator anywhere in the + argument instead of `,`. + +<span id="option-header">`-header` *html-code*</span> +: Specifies the header text to be placed at the top of each output file. The + header is placed to the right of the navigation bar. The `header` can + contain HTML tags and white space, but when it does, the `header` must be + enclosed in quotation marks. Use escape characters for internal quotation + marks within a header. For example, + `javadoc -header "<b>My Library</b><br>v1.0" com.mypackage`. + +<span id="option-helpfile">`-helpfile` *filename*</span> +: Specifies a file containing the text that will be displayed when the + **HELP** link in the navigation bar is clicked. If this option is not given, + the `javadoc` tool creates a default page that will be used. + +<span id="option-html5">`-html5`</span> +: This option is a no-op and is just retained for backwards compatibility. + +<span id="option-javafx">`--javafx` or `-javafx`</span> +: Enables JavaFX functionality. This option is enabled by default if the + JavaFX library classes are detected on the module path. + +<span id="option-keywords">`-keywords`</span> +: Adds HTML keyword `<meta>` tags to the generated file for each class. These + tags can help search engines that look for `<meta>` tags find the pages. + Most search engines that search the entire Internet don't look at `<meta>` + tags, because pages can misuse them. Search engines offered by companies + that confine their searches to their own website can benefit by looking at + `<meta>` tags. The `<meta>` tags include the fully qualified name of the + class and the unqualified names of the fields and methods. Constructors + aren't included because they are identical to the class name. For example, + the page for the class `String` includes these keywords: + + ``` + <meta name="keywords" content="java.lang.String class"> + <meta name="keywords" content="CASE_INSENSITIVE_ORDER"> + <meta name="keywords" content="length()"> + <meta name="keywords" content="isEmpty()"> + ``` + +<span id="option-link">`-link` *url*</span> +: Creates links to existing `javadoc` generated documentation of externally + referenced classes. The *url* argument is the absolute or relative URL of + the directory that contains the external `javadoc` generated documentation. + You can specify multiple `-link` options in a specified `javadoc` tool run + to link to multiple documents. + + Either a `package-list` or an `element-list` file must be in this *url* + directory (otherwise, use the `-linkoffline` option). + + _Note:_ The `package-list` and `element-list` files are generated by the + `javadoc` tool when generating the API documentation and should not be + modified by the user. + + When you use the `javadoc` tool to document packages, it uses the + `package-list` file to determine the packages declared in an API. When you + generate API documents for modules, the `javadoc` tool uses the + `element-list` file to determine the modules and packages declared in an + API. + + The `javadoc` tool reads the names from the appropriate list file and then + links to the packages or modules at that URL. + + When the `javadoc` tool runs, the *url* value is copied into the `<a href>` + links that are created. Therefore, *url* must be the URL to the directory + and not to a file. + + You can use an absolute link for *url* to enable your documents to link to + a document on any web site, or you can use a relative link to link only to + a relative location. If you use a relative link, then the value you pass in + should be the relative path from the destination directory (specified with + the `-d` option) to the directory containing the packages being linked to. + When you specify an absolute link, you usually use an HTTP link. However, + if you want to link to a file system that has no web server, then you can + use a file link. Use a file link only when everyone who wants to access the + generated documentation shares the same file system. In all cases, and on + all operating systems, use a slash as the separator, whether the URL is + absolute or relative, and `https:`, `http:`, or `file:` as specified in the + [RFC 1738: Uniform Resource Locators (URL)](https://www.rfc-editor.org/info/rfc1738). + + ``` + -link https://<host>/<directory>/<directory>/.../<name> + -link http://<host>/<directory>/<directory>/.../<name> + -link file://<host>/<directory>/<directory>/.../<name> + -link <directory>/<directory>/.../<name> + ``` + +<span id="option-link-modularity-mismatch">`--link-modularity-mismatch` (`warn`|`info`)</span> +: Specifies whether external documentation with wrong modularity (e.g. + non-modular documentation for a modular library, or the reverse case) + should be reported as a warning (`warn`) or just a message (`info`). + The default behavior is to report a warning. + +<span id="option-linkoffline">`-linkoffline` *url1* *url2*</span> +: This option is a variation of the `-link` option. They both create links to + `javadoc` generated documentation for externally referenced classes. You + can specify multiple `-linkoffline` options in a specified `javadoc` tool + run. + + Use the `-linkoffline` option when: + + - Linking to a document on the web that the `javadoc` tool can't access + through a web connection + + - The `package-list` or `element-list` file of the external document + either isn't accessible or doesn't exist at the URL location, but does + exist at a different location and can be specified by either the + `package-list` or `element-list` file (typically local). + + _Note:_ The `package-list` and `element-list` files are generated by the + `javadoc` tool when generating the API documentation and should not be + modified by the user. + + If *url1* is accessible only on the World Wide Web, then the `-linkoffline` + option removes the constraint that the `javadoc` tool must have a web + connection to generate documentation. + + Another use of the `-linkoffline` option is as a work-around to update + documents. After you have run the `javadoc` tool on a full set of packages + or modules, you can run the `javadoc` tool again on a smaller set of + changed packages or modules, so that the updated files can be inserted back + into the original set. + + For example, the `-linkoffline` option takes two arguments. The first is + for the string to be embedded in the `<a href>` links, and the second tells + the `javadoc` tool where to find either the `package-list` or + `element-list` file. + + The *url1* or *url2* value is the absolute or relative URL of the directory + that contains the external `javadoc` generated documentation that you want + to link to. When relative, the value should be the relative path from the + destination directory (specified with the `-d` option) to the root of the + packages being linked to. See *url* in the `-link` option. + +<span id="option-link-platform-properties">`--link-platform-properties` *url*</span> +: Specifies a properties file used to configure links to platform + documentation. + + The *url* argument is expected to point to a properties file containing + one or more entries with the following format, where `<version>` is the + platform version as passed to the `--release` or `--source` option and + `<url>` is the base URL of the corresponding platform API documentation: + + ``` + doclet.platform.docs.<version>=<url> + ``` + + For instance, a properties file containing URLs for releases 15 to 17 might + contain the following lines: + + ``` + doclet.platform.docs.15=https://example.com/api/15/ + doclet.platform.docs.16=https://example.com/api/16/ + doclet.platform.docs.17=https://example.com/api/17/ + ``` + + If the properties file does not contain an entry for a particular release + no platform links are generated. + +<span id="option-linksource">`-linksource`</span> +: Creates an HTML version of each source file (with line numbers) and adds + links to them from the standard HTML documentation. Links are created for + classes, interfaces, constructors, methods, and fields whose declarations + are in a source file. Otherwise, links aren't created, such as for default + constructors and generated classes. + + This option exposes all private implementation details in the included + source files, including private classes, private fields, and the bodies of + private methods, regardless of the `-public`, `-package`, `-protected`, and + `-private` options. Unless you also use the `-private` option, not all + private classes or interfaces are accessible through links. + + Each link appears on the name of the identifier in its declaration. For + example, the link to the source code of the `Button` class would be on the + word `Button`: + + ``` + public class Button extends Component implements Accessible + ``` + + The link to the source code of the `getLabel` method in the `Button` class + is on the word `getLabel`: + + ``` + public String getLabel() + ``` + +<span id="option-main-stylesheet">`--main-stylesheet` *file* or `-stylesheetfile` *file*</span> +: Specifies the path of an alternate stylesheet file that contains the + definitions for the CSS styles used in the generated documentation. This + option lets you override the default. If you do not specify the option, the + `javadoc` tool will create and use a default stylesheet. The file name can + be any name and isn't restricted to `stylesheet.css`. The + `--main-stylesheet` option is the preferred form. + + Command-line example: + + ``` + javadoc --main-stylesheet main_stylesheet.css pkg_foo + ``` + +<span id="option-nocomment">`-nocomment`</span> +: Suppresses the entire comment body, including the main description and all + tags, and generate only declarations. This option lets you reuse source + files that were originally intended for a different purpose so that you can + produce skeleton HTML documentation during the early stages of a new + project. + +<span id="option-nodeprecated">`-nodeprecated`</span> +: Prevents the generation of any deprecated API in the documentation. This + does what the `-nodeprecatedlist` option does, and it doesn't generate any + deprecated API throughout the rest of the documentation. This is useful + when writing code when you don't want to be distracted by the deprecated + code. + +<span id="option-nodeprecatedlist">`-nodeprecatedlist`</span> +: Prevents the generation of the file that contains the list of deprecated + APIs (`deprecated-list.html`) and the link in the navigation bar to that + page. The `javadoc` tool continues to generate the deprecated API + throughout the rest of the document. This is useful when your source code + contains no deprecated APIs, and you want to make the navigation bar + cleaner. + +<span id="option-no-fonts">`--no-fonts`</span> +: Prevents inclusion of font files in the generated documentation. This can + be useful if the documentation uses a custom stylesheet which does not + use the default fonts. + +<span id="option-nohelp">`-nohelp`</span> +: Omits the **HELP** link in the navigation bar at the top of each + generated page. + +<span id="option-noindex">`-noindex`</span> +: Omits the index from the generated documents. The index is produced by + default. + +<span id="option-nonavbar">`-nonavbar`</span> +: Prevents the generation of the navigation bar and header. The `-nonavbar` + option has no effect on the `-bottom` option. The `-nonavbar` option is + useful when you are interested only in the content and have no need for + navigation, such as when you are converting the files to PostScript or PDF + for printing only. + +<span id="option-no-platform-links">`--no-platform-links`</span> +: Prevents the generation of links to platform documentation. + These links are generated by default. + +<span id="option-noqualifier">`-noqualifier` *name1*`,`*name2...*</span> +: Excludes the list of qualifiers from the output. The package name is + removed from places where class or interface names appear. + For historical reasons, `:` can be used anywhere in the argument as a + separator instead of `,`. + + The following example omits all package qualifiers: `-noqualifier all`. + + The following example omits `java.lang` and `java.io` package qualifiers: + `-noqualifier java.lang:java.io`. + + The following example omits package qualifiers starting with `java` and + `com.sun` subpackages, but not `javax: -noqualifier java.*:com.sun.*`. + + Where a package qualifier would appear due to the previous behavior, the + name can be suitably shortened. This rule is in effect whether or not the + `-noqualifier` option is used. + +<span id="option-nosince">`-nosince`</span> +: Omits from the generated documentation the `Since` sections derived from + any `since` tags. + +<span id="option-notimestamp">`-notimestamp`</span> +: Suppresses the time stamp, which is hidden in an HTML comment in the + generated HTML near the top of each page. The `-notimestamp` option is + useful when you want to run the `javadoc` tool on two source bases and + compare them, because it prevents time stamps from causing a difference + (which would otherwise be a difference on every page). The time stamp + includes the `javadoc` tool release number. + +<span id="option-notree">`-notree`</span> +: Omits the class and interface hierarchy pages from the generated documents. + These are the pages you reach using the **TREE** link in the navigation bar. + The hierarchy is produced by default. + +<span id="option-override-methods">`--override-methods` (`detail`|`summary`)</span> +: Documents overridden methods in the detail or summary sections. + The default is `detail`. + +<span id="option-overview">`-overview` *filename*</span> +: Specifies that the `javadoc` tool should retrieve the content for the overview + documentation from the file specified by *filename* and place it on + the Overview page (`overview-summary.html`). If the *filename* is a relative + path, it is evaluated relative to the current working directory. + + The file may be an HTML file, with a filename ending in `.html`, + or a Markdown file, with a filename ending in `.md`. + If the file is an HTML file, the content for the overview documentation + is taken from the `<main>` element in the file, if one is present, or from + the `<body>` element is there is no `<main>` element. If the file is + a Markdown file, the entire content of the file is used. + + The title on the overview page is set by `-doctitle`. + + _Note:_ older versions of the `javadoc` tool assumed that any use of this + option was for an HTML file, and allowed any extension for the *filename*. + +<span id="option-serialwarn">`-serialwarn`</span> +: Reports compile-time warnings for missing `@serial` tags. By default, + Javadoc reports no serial warnings. Use this option to display the serial + warnings, which helps to properly document default serializable fields and + `writeExternal` methods. + +<span id="option-since">`--since` *release*(`,`*release*)*</span> +: Generates documentation for APIs that were added or newly deprecated in the + specified *release*s. + + If the `@since` tag in the `javadoc` comment of an element in the documented + source code matches a *release* passed as the option argument, information + about the element and the release it was added in is included in a "New API" + page. + + If the "Deprecated API" page is generated and the `since` element of the + `java.lang.Deprecated` annotation of a documented element matches a *release* + in the option arguments, information about the release the element was + deprecated in is added to the "Deprecated API" page. + + Releases are compared using case-sensitive string comparison. + +<span id="option-since-label">`--since-label` *text*</span> +: Specifies the *text* to use in the heading of the "New API" page. This may + contain information about the releases covered in the page, e.g. + "New API in release 2.0", or "New API since release 1". + +<span id="option-snippet-path">`--snippet-path` *snippetpathlist*</span> +: Specifies the search paths for finding files for external snippets. + The *snippetpathlist* can contain multiple paths by separating them with the + platform path separator (`;` on Windows; `:` on other platforms.) + The standard doclet first searches the `snippet-files` subdirectory in the + package containing the snippet, and then searches all the directories in the + given list. + +<span id="option-sourcetab">`-sourcetab` *tab-length*</span> +: Specifies the number of spaces each tab uses in the source. + +<span id="option-spec-base-url">`--spec-base-url` *url*</span> +: Specifies the base URL for relative URLs in `@spec` tags, to be used when + generating links to any external specifications. It can either be an + absolute URL, or a relative URL, in which case it is evaluated relative + to the base directory of the generated output files. The default value is + equivalent to `{@docRoot}/../specs`. + +<span id="option-splitindex">`-splitindex`</span> +: Splits the index file into multiple files, alphabetically, one file per + letter, plus a file for any index entries that start with non-alphabetical + symbols. + +<span id="option-tag">`-tag` *name*:*locations*:*header*</span> +: Specifies a custom tag with a single argument. For the `javadoc` tool to + spell-check tag names, it is important to include a `-tag` option for every + custom tag that is present in the source code, disabling (with `X`) those + that aren't being output in the current run. The colon (`:`) is always the + separator. To include a colon in the tag name, escape it with a backward + slash (`\`). The `-tag` option outputs the tag heading, *header*, in bold, + followed on the next line by the text from its single argument. Similar to + any block tag, the argument text can contain inline tags, which are also + interpreted. The output is similar to standard one-argument tags, such as + the `@return` and `@author` tags. Omitting a *header* value causes the + *name* to be the heading. *locations* is a list of characters specifying + the kinds of declarations in which the tag may be used. The following + characters may be used, in either uppercase or lowercase: + + * `A`: all declarations + * `C`: constructors + * `F`: fields + * `M`: methods + * `O`: the overview page and other documentation files in `doc-files` subdirectories + * `P`: packages + * `S`: modules + * `T`: types (classes and interfaces) + * `X`: nowhere: the tag is disabled, and will be ignored + + The order in which tags are given on the command line will be used + as the order in which the tags appear in the generated output. + You can include standard tags in the order given on the command line + by using the `-tag` option with no *locations* or *header*. + +<span id="option-taglet">`-taglet` *class*</span> +: Specifies the fully qualified name of the taglet used in generating the + documentation for that tag. Use the fully qualified name for the *class* + value. This taglet also defines the number of text arguments that the + custom tag has. The taglet accepts those arguments, processes them, and + generates the output. + + Taglets are useful for block or inline tags. They can have any number of + arguments and implement custom behavior, such as making text bold, + formatting bullets, writing out the text to a file, or starting other + processes. Taglets can only determine where a tag should appear and in what + form. All other decisions are made by the doclet. A taglet can't do things + such as remove a class name from the list of included classes. However, it + can execute side effects, such as printing the tag's text to a file or + triggering another process. Use the `-tagletpath` option to specify the + path to the taglet. The following example inserts the To Do taglet after + Parameters and ahead of Throws in the generated pages. + + ``` + -taglet com.sun.tools.doclets.ToDoTaglet + -tagletpath /home/taglets + -tag return + -tag param + -tag todo + -tag throws + -tag see + ``` + + Alternately, you can use the `-taglet` option in place of its `-tag` + option, but that might be difficult to read. + +<span id="option-tagletpath">`-tagletpath` *tagletpathlist*</span> +: Specifies the search paths for finding taglet class files. + The *tagletpathlist* can contain multiple paths by separating them with the + platform path separator (`;` on Windows; `:` on other platforms.) + The `javadoc` tool searches all subdirectories of the specified paths. + +<span id="option-top">`-top` *html-code*</span> +: Specifies the text to be placed at the top of each output file. + +<span id="option-use">`-use`</span> +: Creates class and package usage pages. Includes one Use page for each + documented class and package. The page describes what packages, classes, + methods, constructors, and fields use any API of the specified class or + package. Given class C, things that use class C would include subclasses of + C, fields declared as C, methods that return C, and methods and + constructors with parameters of type C. For example, you can look at the + Use page for the `String` type. Because the `getName` method in the + `java.awt.Font` class returns type `String`, the `getName` method uses + `String` and so the `getName` method appears on the Use page for `String`. + This documents only uses of the API, not the implementation. When a method + uses `String` in its implementation, but doesn't take a string as an + argument or return a string, that isn't considered a use of `String`. To + access the generated Use page, go to the class or package and click the + **USE** link in the navigation bar. + +<span id="option-version">`-version`</span> +: Includes the text of any `version` tags in the generated documentation. + This text is omitted by default. + Note: To find out what version of the `javadoc` tool you are using, use + the `--version` option (with two hyphens). + +<span id="option-windowtitle">`-windowtitle` *title*</span> +: Specifies the title to be placed in the HTML `<title>` tag. The text + specified in the `title` tag appears in the window title and in any browser + bookmarks (favorite places) that someone creates for this page. This title + should not contain any HTML tags because a browser will not interpret them + correctly. Use escape characters on any internal quotation marks within the + `title` tag. If the `-windowtitle` option is omitted, then the `javadoc` + tool uses the value of the `-doctitle` option for the `-windowtitle` + option. For example, `javadoc -windowtitle "My Library" com.mypackage`. + +### Extra Options for the Standard Doclet + +The following are additional options provided by the standard doclet and are +subject to change without notice. Additional options are less commonly +used or are otherwise regarded as advanced. + +<span id="option-date">`--date` *date-and-time*</span> +: Specifies the value to be used to timestamp the generated pages, in + [ISO 8601][] format. The specified value must be within 10 years of the + current date and time. It is an error to specify both `-notimestamp` + and `--date`. Using a specific value means the generated documentation + can be part of a [reproducible build][]. If the option is not given, the + default value is the current date and time. For example: + + ``` + javadoc --date 2022-02-01T17:41:59-08:00 mypackage + ``` + +<span id="option-legal-notices">`--legal-notices` (`default`|`none`|*directory*)</span> +: Specifies the location from which to copy legal files to the generated + documentation. If the option is not specified or is used with the value + `default`, the files are copied from the default location. + If the argument is used with value `none`, no files are copied. Every + other argument is interpreted as directory from which to copy the legal + files. + +<span id="option-no-frames">`--no-frames`</span> +: This option is no longer supported and reports a warning. + +<span id="option-Xdoclint">`-Xdoclint`</span> +: Enables recommended checks for problems in documentation comments. + + By default, the `-Xdoclint` option is enabled. Disable it with the option + `-Xdoclint:none`. + + For more details, see [DocLint](#doclint). + +<span id="option-Xdoclint-flags">`-Xdoclint:`*flag*,*flag*,...</span> +: Enables or disables specific checks for different kinds of issues in + documentation comments. + + Each *flag* can be one of `all`, `none`, or `[-]`*group* where + *group* has one of the following values: + `accessibility`, `html`, `missing`, `reference`, `syntax`. + For more details on these values, see [DocLint Groups](#groups). + + When specifying two or more flags, you can either use a single `-Xdoclint:...` + option, listing all the desired flags, or you can use multiple options + giving one or more flag in each option. For example, use either of the + following commands to check for the HTML, syntax, and accessibility issues + in the file `MyFile.java`. + + ``` + javadoc -Xdoclint:html -Xdoclint:syntax -Xdoclint:accessibility MyFile.java + javadoc -Xdoclint:html,syntax,accessibility MyFile.java + ``` + + The following examples illustrate how to change what DocLint reports: + + * `-Xdoclint:none` --- disables all checks + * `-Xdoclint:`*group* --- enables *group* checks + * `-Xdoclint:all` --- enables all groups of checks + * `-Xdoclint:all,-`*group* --- enables all checks except *group* checks + + For more details, see [DocLint](#doclint). + +<span id="option-Xdoclint-package">`-Xdoclint/package:`\[`-`\]*packages*</span> +: Enables or disables checks in specific packages. *packages* is a comma + separated list of package specifiers. A package specifier is either a + qualified name of a package or a package name prefix followed by `*`, which + expands to all subpackages of the given package. Prefix the package + specifier with `-` to disable checks for the specified packages. + + For more details, see [DocLint](#doclint). + +<span id="option-Xdocrootparent">`-Xdocrootparent` *url*</span> +: Replaces all `@docRoot` items followed by `/..` in documentation comments + with *url*. + +[ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html +[reproducible build]: https://reproducible-builds.org/ + +## DocLint + +DocLint provides the ability to check for possible problems in documentation +comments. Problems may be reported as warnings or errors, depending on their +severity. For example, a missing comment may be bad style that deserves a +warning, but a link to an unknown Java declaration is more serious and deserves +an error. Problems are organized into [groups](#groups), and options can be +used to enable or disable messages in one or more groups. Within the source +code, messages in one or more groups can be [suppressed](#suppressing-messages) +by using `@SuppressWarnings` annotations. + +When invoked from `javadoc`, by default DocLint checks all comments that are +used in the generated documentation. It thus relies on other command-line +options to determine which declarations, and which corresponding documentation +comments will be included. _Note:_ this may mean that even comments on some +private members of serializable classes will also be checked, if the members +need to be documented in the generated `Serialized Forms` page. + +In contrast, when DocLint is invoked from `javac`, DocLint solely relies on the +various `-Xdoclint...` options to determine which documentation comments to +check. + +DocLint doesn't attempt to fix invalid input, it just reports it. + +_Note:_ DocLint doesn't guarantee the completeness of these checks. +In particular, it isn't a full HTML compliance checker. The goal is to just +report common errors in a convenient manner. + +### Groups + +The checks performed by DocLint are organized into groups. The warnings and +errors in each group can be enabled or disabled with command-line options, or +suppressed with `@SuppressWarnings` annotations. + +The groups are as follows: + +* `accessibility` --- Checks for issues related to accessibility.<br> + For example, no `alt` attribute specified in an `<img>` element, + or no caption or summary attributes specified in a `<table>` element. + + Issues are reported as errors if a downstream validation tool might + be expected to report an error in the files generated by `javadoc`. + + For reference, see the [Web Content Accessibility Guidelines][]. + + +* `html` --- Detects common high-level HTML issues.<br> + For example, putting block elements inside inline elements, or not closing + elements that require an end tag. + + Issues are reported as errors if a downstream validation tool might + be expected to report an error in the files generated by `javadoc`. + + For reference, see the [HTML Living Standard][]. + + +* `missing` --- Checks for missing documentation comments or tags.<br> + For example, a missing comment on a class declaration, or a missing `@param` + or `@return` tag in the comment for a method declaration. + + Issues related to missing items are typically reported as warnings because + they are unlikely to be reported as errors by downstream validation tools + that may be used to check the output generated by `javadoc`. + + +* `reference` --- Checks for issues relating to the references to Java API + elements from documentation comment tags.<br> + For example, the reference in `@see` or `{@link ...}` cannot be found, + or a bad name is given for `@param` or `@throws`. + + Issues are typically reported as errors because while the issue may not cause + problems in the generated files, the author has likely made a mistake that + will lead to incorrect or unexpected documentation. + + +* `syntax` --- Checks for low-level syntactic issues in documentation comments.<br> + For example, unescaped angle brackets (`<` and `>`) and ampersands (`&`) + and invalid documentation comment tags.<br> + + Issues are typically reported as errors because the issues may + lead to incorrect or unexpected documentation. + +[HTML Living Standard]: https://html.spec.whatwg.org/multipage/ +[Web Content Accessibility Guidelines]: https://www.w3.org/WAI/standards-guidelines/wcag/ + + +### Suppressing Messages + +DocLint checks for and recognizes two strings that may be present in the +arguments for an `@SuppressWarnings` annotation. + +* `doclint` +* `doclint:`_LIST_ + +where _LIST_ is a comma-separated list of one or more of +`accessibility`, `html`, `missing`, `reference`, `syntax`. + +The names in _LIST_ are the same [group](#groups) names supported by the +command-line `-Xdoclint` option for `javac` and `javadoc`. (This is the same +convention honored by the `javac` `-Xlint` option and the corresponding names +supported by `@SuppressWarnings`.) + +The names in _LIST_ can equivalently be specified in separate arguments of +the annotation. For example, the following are equivalent: + +* `@SuppressWarnings("doclint:accessibility,missing")` +* `@SuppressWarnings("doclint:accessibility", "doclint:missing")` + +When DocLint detects an issue in a documentation comment, it checks for the +presence of `@SuppressWarnings` on the associated declaration and on all +lexically enclosing declarations. The issue will be ignored if any such +annotation is found containing the simple string `doclint` or the longer form +`doclint:LIST` where _LIST_ contains the name of the group for the issue. + +_Note:_ as with other uses of `@SuppressWarnings`, using the annotation on a +module or package declaration only affects that declaration; it does not affect +the contents of the module or package in other source files. + +All messages related to an issue are suppressed by the presence of an +appropriate `@SuppressWarnings` annotation: this includes errors as well as +warnings. + +_Note:_ It is only possible to *suppress* messages. +If an annotation of `@SuppressWarnings("doclint")` is given on a top-level +declaration, all DocLint messages for that declaration and any enclosed +declarations will be suppressed; it is not possible to selectively re-enable +messages for issues in enclosed declarations. + + +### Comparison with downstream validation tools + +DocLint is a utility built into `javac` and `javadoc` that checks the content +of documentation comments, as found in source files. In contrast, downstream +validation tools can be used to validate the output generated from those +documentation comments by `javadoc` and the standard doclet. + +Although there is some overlap in functionality, the two mechanisms are +different and each has its own strengths and weaknesses. + +* Downstream validation tools can check the end result of any generated + documentation, as it will be seen by the end user. + This includes content from all sources, including documentation comments, + the standard doclet itself, user-provided taglets, and content supplied + via command-line options. Because such tools are analyzing complete HTML + pages, they can do more complete checks than can DocLint. + However, when a problem is found in the generated pages, it can be harder to + track down exactly where in the build pipeline the problem needs to be fixed. + + +* DocLint checks the content of documentation comments, in source files. + This makes it very easy to identify the exact position of any issues that + may be found. DocLint can also detect some semantic errors in + documentation comments that downstream tools cannot detect, + such as missing comments, using an `@return` tag in a method returning `void`, + or an `@param` tag describing a non-existent parameter. + But by its nature, DocLint cannot report on problems such as + missing links, or errors in user-provided custom taglets, or + problems in the standard doclet itself. It also cannot reliably + detect errors in documentation comments at the boundaries + between content in a documentation comment and content generated + by a custom taglet. diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 deleted file mode 100644 index 495b629089d..00000000000 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ /dev/null @@ -1,1345 +0,0 @@ -.\" Copyright (c) 2012, 2024, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JCMD" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jcmd - send diagnostic command requests to a running Java Virtual -Machine (JVM) -.SH SYNOPSIS -.PP -\f[V]jcmd\f[R] [\f[I]pid\f[R] | \f[I]main-class\f[R]] -\f[I]command\f[R]... -| \f[V]PerfCounter.print\f[R] | \f[V]-f\f[R] \f[I]filename\f[R] -.PP -\f[V]jcmd\f[R] [\f[V]-l\f[R]] -.PP -\f[V]jcmd\f[R] \f[V]-h\f[R] -.TP -\f[I]pid\f[R] -When used, the \f[V]jcmd\f[R] utility sends the diagnostic command -request to the process ID for the Java process. -.TP -\f[I]main-class\f[R] -When used, the \f[V]jcmd\f[R] utility sends the diagnostic command -request to all Java processes with the specified name of the main class. -.TP -\f[I]command\f[R] -The \f[V]command\f[R] must be a valid \f[V]jcmd\f[R] command for the -selected JVM. -The list of available commands for \f[V]jcmd\f[R] is obtained by running -the \f[V]help\f[R] command (\f[V]jcmd\f[R] \f[I]pid\f[R] \f[V]help\f[R]) -where \f[I]pid\f[R] is the process ID for the running Java process. -.TP -\f[V]Perfcounter.print\f[R] -Prints the performance counters exposed by the specified Java process. -.TP -\f[V]-f\f[R] \f[I]filename\f[R] -Reads and executes commands from a specified file, \f[I]filename\f[R]. -.TP -\f[V]-l\f[R] -Displays the list of Java Virtual Machine process identifiers that are -not running in a separate docker process along with the main class and -command-line arguments that were used to launch the process. -If the JVM is in a docker process, you must use tools such as -\f[V]ps\f[R] to look up the PID. -.RS -.PP -\f[B]Note:\f[R] -.PP -Using \f[V]jcmd\f[R] without arguments is the same as using -\f[V]jcmd -l\f[R]. -.RE -.TP -\f[V]-h\f[R] -Displays the \f[V]jcmd\f[R] utility\[aq]s command-line help. -.SH DESCRIPTION -.PP -The \f[V]jcmd\f[R] utility is used to send diagnostic command requests -to the JVM. -It must be used on the same machine on which the JVM is running, and -have the same effective user and group identifiers that were used to -launch the JVM. -Each diagnostic command has its own set of options and arguments. -To display the description, syntax, and a list of available options and -arguments for a diagnostic command, use the name of the command as the -argument. -For example: -.RS -.PP -\f[V]jcmd\f[R] \f[I]pid\f[R] \f[V]help\f[R] \f[I]command\f[R] -.RE -.PP -If arguments contain spaces, then you must surround them with single or -double quotation marks (\f[V]\[aq]\f[R] or \f[V]\[dq]\f[R]). -In addition, you must escape single or double quotation marks with a -backslash (\f[V]\[rs]\f[R]) to prevent the operating system shell from -processing quotation marks. -Alternatively, you can surround these arguments with single quotation -marks and then with double quotation marks (or with double quotation -marks and then with single quotation marks). -.PP -If you specify the process identifier (\f[I]pid\f[R]) or the main class -(\f[I]main-class\f[R]) as the first argument, then the \f[V]jcmd\f[R] -utility sends the diagnostic command request to the Java process with -the specified identifier or to all Java processes with the specified -name of the main class. -You can also send the diagnostic command request to all available Java -processes by specifying \f[V]0\f[R] as the process identifier. -.SH COMMANDS FOR JCMD -.PP -The \f[I]command\f[R] must be a valid \f[V]jcmd\f[R] diagnostic command -for the selected JVM. -The list of available commands for \f[V]jcmd\f[R] is obtained by running -the \f[V]help\f[R] command (\f[V]jcmd\f[R] \f[I]pid\f[R] \f[V]help\f[R]) -where \f[I]pid\f[R] is the process ID for a running Java process. -If the \f[I]pid\f[R] is \f[V]0\f[R], commands will be sent to all Java -processes. -The main class argument will be used to match, either partially or -fully, the class used to start Java. -If no options are given, it lists the running Java process identifiers -that are not in separate docker processes along with the main class and -command-line arguments that were used to launch the process (the same as -using \f[V]-l\f[R]). -.PP -\f[V]jcmd\f[R] \f[I]commands\f[R] may take options and arguments. -\f[I]Options\f[R] are specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -\f[I]Arguments\f[R] are given as just a value, never name=value. -.PP -The following commands are available: -.TP -\f[V]help\f[R] [\f[I]options\f[R]] [\f[I]arguments\f[R]] -For more information about a specific command. -.RS -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]command name\f[R]: The name of the command for which we want help -(STRING, no default value) -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-all\f[R]: (Optional) Show help for all commands (BOOLEAN, false) . -.RE -.TP -\f[V]Compiler.CodeHeap_Analytics\f[R] [\f[I]function\f[R]] [\f[I]granularity\f[R]] -Print CodeHeap analytics -.RS -.PP -Impact: Low: Depends on code heap size and content. -Holds CodeCache_lock during analysis step, usually sub-second duration. -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]function\f[R]: (Optional) Function to be performed (aggregate, -UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, -discard (STRING, all) -.IP \[bu] 2 -\f[I]granularity\f[R]: (Optional) Detail level - smaller value -> more -detail (INT, 4096) -.RE -.TP -\f[V]Compiler.codecache\f[R] -Prints code cache layout and bounds. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]Compiler.codelist\f[R] -Prints all compiled methods in code cache that are alive. -.RS -.PP -Impact: Medium -.RE -.TP -\f[V]Compiler.directives_add\f[R] \f[I]arguments\f[R] -Adds compiler directives from a file. -.RS -.PP -Impact: Low -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]filename\f[R]: The name of the directives file (STRING, no default -value) -.RE -.TP -\f[V]Compiler.directives_clear\f[R] -Remove all compiler directives. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]Compiler.directives_print\f[R] -Prints all active compiler directives. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]Compiler.directives_remove\f[R] -Remove latest added compiler directive. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]Compiler.memory\f[R] [\f[I]options\f[R]] -Print compilation footprint -.RS -.PP -Impact: Medium: Pause time depends on number of compiled methods -.PP -\f[B]Note:\f[R] -.PP -The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-H\f[R]: (Optional) Human readable format (BOOLEAN, false) -.IP \[bu] 2 -\f[V]-s\f[R]: (Optional) Minimum memory size (MEMORY SIZE, 0) -.RE -.TP -\f[V]Compiler.perfmap\f[R] [\f[I]arguments\f[R]] (Linux only) -Write map file for Linux perf tool. -.RS -.PP -Impact: Low -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]filename\f[R]: (Optional) The name of the map file. -If %p is specified in the filename, it is expanded to the JVM\[aq]s PID. -(FILE, \[dq]/tmp/perf-%p.map\[dq]) -.RE -.TP -\f[V]Compiler.queue\f[R] -Prints methods queued for compilation. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]GC.class_histogram\f[R] [\f[I]options\f[R]] -Provides statistics about the Java heap usage. -.RS -.PP -Impact: High --- depends on Java heap size and content. -.PP -\f[B]Note:\f[R] -.PP -The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-all\f[R]: (Optional) Inspects all objects, including unreachable -objects (BOOLEAN, false) -.IP \[bu] 2 -\f[V]-parallel\f[R]: (Optional) Number of parallel threads to use for -heap inspection. -0 (the default) means let the VM determine the number of threads to use. -1 means use one thread (disable parallelism). -For any other value the VM will try to use the specified number of -threads, but might use fewer. -(INT, 0) -.RE -.TP -\f[V]GC.finalizer_info\f[R] -Provides information about the Java finalization queue. -.RS -.PP -Impact: Medium -.RE -.TP -\f[V]GC.heap_dump\f[R] [\f[I]options\f[R]] \f[I]filename\f[R] -Generates a HPROF format dump of the Java heap. -.RS -.PP -Impact: High --- depends on the Java heap size and content. -Request a full GC unless the \f[V]-all\f[R] option is specified. -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-all\f[R]: (Optional) Dump all objects, including unreachable -objects (BOOLEAN, false) -.IP \[bu] 2 -\f[V]-gz\f[R]: (Optional) If specified, the heap dump is written in -gzipped format using the given compression level. -1 (recommended) is the fastest, 9 the strongest compression. -(INT, 1) -.IP \[bu] 2 -\f[V]-overwrite\f[R]: (Optional) If specified, the dump file will be -overwritten if it exists (BOOLEAN, false) -.IP \[bu] 2 -\f[V]-parallel\f[R]: (Optional) Number of parallel threads to use for -heap dump. -The VM will try to use the specified number of threads, but might use -fewer. -(INT, 1) -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]filename\f[R]: The name of the dump file. -If %p is specified in the filename, it is expanded to the JVM\[aq]s PID. -(FILE, no default value) -.RE -.TP -\f[V]GC.heap_info\f[R] -Provides generic Java heap information. -.RS -.PP -Impact: Medium -.RE -.TP -\f[V]GC.run\f[R] -Calls \f[V]java.lang.System.gc()\f[R]. -.RS -.PP -Impact: Medium --- depends on the Java heap size and content. -.RE -.TP -\f[V]GC.run_finalization\f[R] -Calls \f[V]java.lang.System.runFinalization()\f[R]. -.RS -.PP -Impact: Medium --- depends on the Java content. -.RE -.TP -\f[V]JFR.check\f[R] [\f[I]options\f[R]] -Show information about a running flight recording -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -If no parameters are entered, information for all active recordings is -shown. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]name\f[R]: (Optional) Name of the flight recording. -(STRING, no default value) -.IP \[bu] 2 -\f[V]verbose\f[R]: (Optional) Flag for printing the event settings for -the recording (BOOLEAN, false) -.RE -.TP -\f[V]JFR.configure\f[R] [\f[I]options\f[R]] -Set the parameters for a flight recording -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -If no parameters are entered, the current settings are displayed. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]dumppath\f[R]: (Optional) Path to the location where a recording -file is written in case the VM runs into a critical error, such as a -system crash. -(STRING, The default location is the current directory) -.IP \[bu] 2 -\f[V]globalbuffercount\f[R]: (Optional) Number of global buffers. -This option is a legacy option: change the \f[V]memorysize\f[R] -parameter to alter the number of global buffers. -This value cannot be changed once JFR has been initialized. -(STRING, default determined by the value for \f[V]memorysize\f[R]) -.IP \[bu] 2 -\f[V]globalbuffersize\f[R]: (Optional) Size of the global buffers, in -bytes. -This option is a legacy option: change the \f[V]memorysize\f[R] -parameter to alter the size of the global buffers. -This value cannot be changed once JFR has been initialized. -(STRING, default determined by the value for \f[V]memorysize\f[R]) -.IP \[bu] 2 -\f[V]maxchunksize\f[R]: (Optional) Maximum size of an individual data -chunk in bytes if one of the following suffixes is not used: \[aq]m\[aq] -or \[aq]M\[aq] for megabytes OR \[aq]g\[aq] or \[aq]G\[aq] for -gigabytes. -This value cannot be changed once JFR has been initialized. -(STRING, 12M) -.IP \[bu] 2 -\f[V]memorysize\f[R]: (Optional) Overall memory size, in bytes if one of -the following suffixes is not used: \[aq]m\[aq] or \[aq]M\[aq] for -megabytes OR \[aq]g\[aq] or \[aq]G\[aq] for gigabytes. -This value cannot be changed once JFR has been initialized. -(STRING, 10M) -.IP \[bu] 2 -\f[V]repositorypath\f[R]: (Optional) Path to the location where -recordings are stored until they are written to a permanent file. -(STRING, The default location is the temporary directory for the -operating system. -On Linux operating systems, the temporary directory is \f[V]/tmp\f[R]. -On Windwows, the temporary directory is specified by the \f[V]TMP\f[R] -environment variable.) -.IP \[bu] 2 -\f[V]preserve-repository=\f[R]{\f[V]true\f[R]|\f[V]false\f[R]} : -Specifies whether files stored in the disk repository should be kept -after the JVM has exited. -If false, files are deleted. -By default, this parameter is disabled. -.IP \[bu] 2 -\f[V]stackdepth\f[R]: (Optional) Stack depth for stack traces. -Setting this value greater than the default of 64 may cause a -performance degradation. -This value cannot be changed once JFR has been initialized. -(LONG, 64) -.IP \[bu] 2 -\f[V]thread_buffer_size\f[R]: (Optional) Local buffer size for each -thread in bytes if one of the following suffixes is not used: -\[aq]k\[aq] or \[aq]K\[aq] for kilobytes or \[aq]m\[aq] or \[aq]M\[aq] -for megabytes. -Overriding this parameter could reduce performance and is not -recommended. -This value cannot be changed once JFR has been initialized. -(STRING, 8k) -.IP \[bu] 2 -\f[V]samplethreads\f[R]: (Optional) Flag for activating thread sampling. -(BOOLEAN, true) -.RE -.TP -\f[V]JFR.dump\f[R] [\f[I]options\f[R]] -Write data to a file while a flight recording is running -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -No options are required. -The recording continues to run after the data is written. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]begin\f[R]: (Optional) Specify the time from which recording data -will be included in the dump file. -The format is specified as local time. -(STRING, no default value) -.IP \[bu] 2 -\f[V]end\f[R]: (Optional) Specify the time to which recording data will -be included in the dump file. -The format is specified as local time. -(STRING, no default value) -.RS 2 -.PP -\f[B]Note:\f[R] For both \f[V]begin\f[R] and \f[V]end\f[R], the time -must be in a format that can be read by -java.time.LocalTime::parse(STRING), -java.time.LocalDateTime::parse(STRING) or -java.time.Instant::parse(STRING). -For example, \[dq]13:20:15\[dq], \[dq]2020-03-17T09:00:00\[dq] or -\[dq]2020-03-17T09:00:00Z\[dq]. -.PP -\f[B]Note:\f[R] \f[V]begin\f[R] and \f[V]end\f[R] times correspond to -the timestamps found within the recorded information in the flight -recording data. -.PP -Another option is to use a time relative to the current time that is -specified by a negative integer followed by \[dq]s\[dq], \[dq]m\[dq] or -\[dq]h\[dq]. -For example, \[dq]-12h\[dq], \[dq]-15m\[dq] or \[dq]-30s\[dq] -.RE -.IP \[bu] 2 -\f[V]filename\f[R]: (Optional) Name of the file to which the flight -recording data is dumped. -If no filename is given, a filename is generated from the PID and the -current date. -The filename may also be a directory in which case, the filename is -generated from the PID and the current date in the specified directory. -If %p and/or %t is specified in the filename, it expands to the -JVM\[aq]s PID and the current timestamp, respectively. -(FILE, no default value) -.IP \[bu] 2 -\f[V]maxage\f[R]: (Optional) Length of time for dumping the flight -recording data to a file. -(INTEGER followed by \[aq]s\[aq] for seconds \[aq]m\[aq] for minutes or -\[aq]h\[aq] for hours, no default value) -.IP \[bu] 2 -\f[V]maxsize\f[R]: (Optional) Maximum size for the amount of data to -dump from a flight recording in bytes if one of the following suffixes -is not used: \[aq]m\[aq] or \[aq]M\[aq] for megabytes OR \[aq]g\[aq] or -\[aq]G\[aq] for gigabytes. -(STRING, no default value) -.IP \[bu] 2 -\f[V]name\f[R]: (Optional) Name of the recording. -If no name is given, data from all recordings is dumped. -(STRING, no default value) -.IP \[bu] 2 -\f[V]path-to-gc-roots\f[R]: (Optional) Flag for saving the path to -garbage collection (GC) roots at the time the recording data is dumped. -The path information is useful for finding memory leaks but collecting -it can cause the application to pause for a short period of time. -Turn on this flag only when you have an application that you suspect has -a memory leak. -(BOOLEAN, false) -.RE -.TP -\f[V]JFR.start\f[R] [\f[I]options\f[R]] -Start a flight recording -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -If no parameters are entered, then a recording is started with default -values. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]delay\f[R]: (Optional) Length of time to wait before starting to -record (INTEGER followed by \[aq]s\[aq] for seconds \[aq]m\[aq] for -minutes or \[aq]h\[aq] for hours, 0s) -.IP \[bu] 2 -\f[V]disk\f[R]: (Optional) Flag for also writing the data to disk while -recording (BOOLEAN, true) -.IP \[bu] 2 -\f[V]dumponexit\f[R]: (Optional) Flag for writing the recording to disk -when the Java Virtual Machine (JVM) shuts down. -If set to \[aq]true\[aq] and no value is given for \f[V]filename\f[R], -the recording is written to a file in the directory where the process -was started. -The file name is a system-generated name that contains the process ID, -the recording ID and the current time stamp. -(For example: \f[V]id-1-2019_12_12_10_41.jfr\f[R]) (BOOLEAN, false) -.IP \[bu] 2 -\f[V]duration\f[R]: (Optional) Length of time to record. -Note that \f[V]0s\f[R] means forever (INTEGER followed by \[aq]s\[aq] -for seconds \[aq]m\[aq] for minutes or \[aq]h\[aq] for hours, 0s) -.IP \[bu] 2 -\f[V]filename\f[R]: (Optional) Name of the file to which the flight -recording data is written when the recording is stopped. -If no filename is given, a filename is generated from the PID and the -current date and is placed in the directory where the process was -started. -The filename may also be a directory in which case, the filename is -generated from the PID and the current date in the specified directory. -If %p and/or %t is specified in the filename, it expands to the -JVM\[aq]s PID and the current timestamp, respectively. -(FILE, no default value) -.IP \[bu] 2 -\f[V]maxage\f[R]: (Optional) Maximum time to keep the recorded data on -disk. -This parameter is valid only when the \f[V]disk\f[R] parameter is set to -\f[V]true\f[R]. -Note \f[V]0s\f[R] means forever. -(INTEGER followed by \[aq]s\[aq] for seconds \[aq]m\[aq] for minutes or -\[aq]h\[aq] for hours, 0s) -.IP \[bu] 2 -\f[V]maxsize\f[R]: (Optional) Maximum size of the data to keep on disk -in bytes if one of the following suffixes is not used: \[aq]m\[aq] or -\[aq]M\[aq] for megabytes OR \[aq]g\[aq] or \[aq]G\[aq] for gigabytes. -This parameter is valid only when the \f[V]disk\f[R] parameter is set to -\[aq]true\[aq]. -The value must not be less than the value for the \f[V]maxchunksize\f[R] -parameter set with the \f[V]JFR.configure\f[R] command. -(STRING, 0 (no maximum size)) -.IP \[bu] 2 -\f[V]name\f[R]: (Optional) Name of the recording. -If no name is provided, a name is generated. -Make note of the generated name that is shown in the response to the -command so that you can use it with other commands. -(STRING, system-generated default name) -.IP \[bu] 2 -\f[V]path-to-gc-roots\f[R]: (Optional) Flag for saving the path to -garbage collection (GC) roots at the end of a recording. -The path information is useful for finding memory leaks but collecting -it is time consuming. -Turn on this flag only when you have an application that you suspect has -a memory leak. -If the \f[V]settings\f[R] parameter is set to \[aq]profile\[aq], then -the information collected includes the stack trace from where the -potential leaking object was allocated. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]settings\f[R]: (Optional) Name of the settings file that identifies -which events to record. -To specify more than one file, separate the names with a comma -(\[aq],\[aq]). -Include the path if the file is not in \f[V]JAVA-HOME\f[R]/lib/jfr. -The following profiles are included with the JDK in the -\f[V]JAVA-HOME\f[R]/lib/jfr directory: \[aq]default.jfc\[aq]: collects a -predefined set of information with low overhead, so it has minimal -impact on performance and can be used with recordings that run -continuously; \[aq]profile.jfc\[aq]: Provides more data than the -\[aq]default.jfc\[aq] profile, but with more overhead and impact on -performance. -Use this configuration for short periods of time when more information -is needed. -Use \f[V]none\f[R] to start a recording without a predefined -configuration file. -(STRING, \f[V]JAVA-HOME\f[R]/lib/jfr/default.jfc) -.PP -Event settings and .jfc options can be specified using the following -syntax: -.IP \[bu] 2 -\f[V]option\f[R]: (Optional) Specifies the option value to modify. -To list available options, use the \f[V]JAVA_HOME\f[R]/bin/jfr tool. -.IP \[bu] 2 -\f[V]event-setting\f[R]: (Optional) Specifies the event setting value to -modify. -Use the form: \f[V]<event-name>#<setting-name>=<value>\f[R] To add a new -event setting, prefix the event name with \[aq]+\[aq]. -.PP -You can specify values for multiple event settings and .jfc options by -separating them with a whitespace. -In case of a conflict between a parameter and a .jfc option, the -parameter will take precedence. -The whitespace delimiter can be omitted for timespan values, i.e. -20ms. -For more information about the settings syntax, see Javadoc of the -jdk.jfr package. -.RE -.TP -\f[V]JFR.stop\f[R] [\f[I]options\f[R]] -Stop a flight recording -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -If no parameters are entered, then no recording is stopped. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]filename\f[R]: (Optional) Name of the file to which the recording -is written when the recording is stopped. -If %p and/or %t is specified in the filename, it expands to the -JVM\[aq]s PID and the current timestamp, respectively. -If no path is provided, the data from the recording is discarded. -(FILE, no default value) -.IP \[bu] 2 -\f[V]name\f[R]: (Optional) Name of the recording (STRING, no default -value) -.RE -.TP -\f[V]JFR.view\f[R] [\f[I]options\f[R]] -Display event data in predefined views. -.RS -.PP -Impact: Medium -.PP -\f[B]Note:\f[R] -.PP -The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or -\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -If no parameters are entered, then a list of available views are -displayed. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]cell-height\f[R]: (Optional) Maximum number of rows in a table -cell. -(INT, default value depends on the view) -.IP \[bu] 2 -\f[V]maxage\f[R]: (Optional) Length of time for the view to span. -(INT followed by \[aq]s\[aq] for seconds \[aq]m\[aq] for minutes or -\[aq]h\[aq] for hours, default value is 10m) -.IP \[bu] 2 -\f[V]maxsize\f[R]: (Optional) Maximum size for the view to span in bytes -if one of the following suffixes is not used: \[aq]m\[aq] or \[aq]M\[aq] -for megabytes OR \[aq]g\[aq] or \[aq]G\[aq] for gigabytes. -(STRING, default value is 32MB) -.IP \[bu] 2 -\f[V]truncate\f[R]: (Optional) Maximum number of rows in a table cell. -(INT, default value depends on the view) -.IP \[bu] 2 -\f[V]verbose\f[R]: (Optional) Displays the query that makes up the view. -(BOOLEAN, default value is false) -.IP \[bu] 2 -\f[V]width\f[R]: (Optional) The width of the view in characters. -(INT, default value depends on the view) -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[V]view\f[R]: Name of the view or event type to display. -Use \f[V]help JFR.view\f[R] to see a list of available views. -(STRING, no default value) -.PP -The view parameter can be an event type name. -Use \f[V]JFR.view types\f[R] to see a list. -To display all views, use \f[V]JFR.view all-views\f[R]. -To display all events, use \f[V]JFR.view all-events\f[R]. -.RE -.TP -\f[V]JVMTI.agent_load\f[R] [\f[I]arguments\f[R]] -Loads JVMTI native agent. -.RS -.PP -Impact: Low -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]library path\f[R]: Absolute path of the JVMTI agent to load. -(STRING, no default value) -.IP \[bu] 2 -\f[I]agent option\f[R]: (Optional) Option string to pass the agent. -(STRING, no default value) -.RE -.TP -\f[V]JVMTI.data_dump\f[R] -Signal the JVM to do a data-dump request for JVMTI. -.RS -.PP -Impact: High -.RE -.TP -\f[V]ManagementAgent.start\f[R] [\f[I]options\f[R]] -Starts remote management agent. -.RS -.PP -Impact: Low --- no impact -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]config.file\f[R]: (Optional) Sets -\f[V]com.sun.management.config.file\f[R] (STRING, no default value) -.IP \[bu] 2 -\f[V]jmxremote.host\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.host\f[R] (STRING, no default value) -.IP \[bu] 2 -\f[V]jmxremote.port\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.port\f[R] (STRING, no default value) -.IP \[bu] 2 -\f[V]jmxremote.rmi.port\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.rmi.port\f[R] (STRING, no default -value) -.IP \[bu] 2 -\f[V]jmxremote.ssl\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.ssl\f[R] (STRING, no default value) -.IP \[bu] 2 -\f[V]jmxremote.registry.ssl\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.registry.ssl\f[R] (STRING, no default -value) -.IP \[bu] 2 -\f[V]jmxremote.authenticate\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.authenticate\f[R] (STRING, no default -value) -.IP \[bu] 2 -jmxremote.password.file: (Optional) Sets -\f[V]com.sun.management.jmxremote.password.file\f[R] (STRING, no default -value) -.IP \[bu] 2 -\f[V]jmxremote.access.file\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.acce ss.file\f[R] (STRING, no default -value) -.IP \[bu] 2 -\f[V]jmxremote.login.config\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.log in.config\f[R] (STRING, no default -value) -.IP \[bu] 2 -\f[V]jmxremote.ssl.enabled.cipher.suites\f[R]: (Optional) Sets -\f[V]com.sun.management\f[R]. -.IP \[bu] 2 -\f[V]jmxremote.ssl.enabled.cipher.suite\f[R]: (STRING, no default value) -.IP \[bu] 2 -\f[V]jmxremote.ssl.enabled.protocols\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxr emote.ssl.enabled.protocols\f[R] (STRING, -no default value) -.IP \[bu] 2 -\f[V]jmxremote.ssl.need.client.auth\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxre mote.need.client.auth\f[R] (STRING, no -default value) -.IP \[bu] 2 -\f[V]jmxremote.ssl.config.file\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote. ssl_config_file\f[R] (STRING, no -default value) -.IP \[bu] 2 -\f[V]jmxremote.autodiscovery\f[R]: (Optional) Sets -\f[V]com.sun.management.jmxremote.au todiscovery\f[R] (STRING, no -default value) -.IP \[bu] 2 -\f[V]jdp.port\f[R]: (Optional) Sets -\f[V]com.sun.management.jdp.port\f[R] (INT, no default value) -.IP \[bu] 2 -\f[V]jdp.address\f[R]: (Optional) Sets -\f[V]com.sun.management.jdp.address\f[R] (STRING, no default value) -.IP \[bu] 2 -\f[V]jdp.source_addr\f[R]: (Optional) Sets -\f[V]com.sun.management.jdp.source_addr\f[R] (STRING, no default value) -.IP \[bu] 2 -\f[V]jdp.ttl\f[R]: (Optional) Sets \f[V]com.sun.management.jdp.ttl\f[R] -(INT, no default value) -.IP \[bu] 2 -\f[V]jdp.pause\f[R]: (Optional) Sets -\f[V]com.sun.management.jdp.pause\f[R] (INT, no default value) -.IP \[bu] 2 -\f[V]jdp.name\f[R]: (Optional) Sets -\f[V]com.sun.management.jdp.name\f[R] (STRING, no default value) -.RE -.TP -\f[V]ManagementAgent.start_local\f[R] -Starts the local management agent. -.RS -.PP -Impact: Low --- no impact -.RE -.TP -\f[V]ManagementAgent.status\f[R] -Print the management agent status. -.RS -.PP -Impact: Low --- no impact -.RE -.TP -\f[V]ManagementAgent.stop\f[R] -Stops the remote management agent. -.RS -.PP -Impact: Low --- no impact -.RE -.TP -\f[V]System.dump_map\f[R] [\f[I]options\f[R]] (Linux only) -Dumps an annotated process memory map to an output file. -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-H\f[R]: (Optional) Human readable format (BOOLEAN, false) -.IP \[bu] 2 -\f[V]-F\f[R]: (Optional) File path. -If %p is specified in the filename, it is expanded to the JVM\[aq]s PID. -(FILE, \[dq]vm_memory_map_%p.txt\[dq]) -.RE -.TP -\f[V]System.map\f[R] [\f[I]options\f[R]] (Linux only) -Prints an annotated process memory map of the VM process. -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-H\f[R]: (Optional) Human readable format (BOOLEAN, false) -.RE -.TP -\f[V]System.native_heap_info\f[R] (Linux only) -Attempts to output information regarding native heap usage through -malloc_info(3). -If unsuccessful outputs \[dq]Error: \[dq] and a reason. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]System.trim_native_heap\f[R] (Linux only) -Attempts to free up memory by trimming the C-heap. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]Thread.dump_to_file\f[R] [\f[I]options\f[R]] \f[I]filepath\f[R] -Dump threads, with stack traces, to a file in plain text or JSON format. -.RS -.PP -Impact: Medium: Depends on the number of threads. -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-overwrite\f[R]: (Optional) May overwrite existing file (BOOLEAN, -false) -.IP \[bu] 2 -\f[V]-format\f[R]: (Optional) Output format (\[dq]plain\[dq] or -\[dq]json\[dq]) (STRING, plain) -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]filepath\f[R]: The file path to the output file. -If %p is specified in the filename, it is expanded to the JVM\[aq]s PID. -(FILE, no default value) -.RE -.TP -\f[V]Thread.print\f[R] [\f[I]options\f[R]] -Prints all threads with stacktraces. -.RS -.PP -Impact: Medium --- depends on the number of threads. -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-e\f[R]: (Optional) Print extended thread information (BOOLEAN, -false) -.IP \[bu] 2 -\f[V]-l\f[R]: (Optional) Prints \f[V]java.util.concurrent\f[R] locks -(BOOLEAN, false) -.RE -.TP -\f[V]VM.cds\f[R] [\f[I]arguments\f[R]] -Dump a static or dynamic shared archive that includes all currently -loaded classes. -.RS -.PP -Impact: Medium --- pause time depends on number of loaded classes -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]subcmd\f[R]: must be either \f[V]static_dump\f[R] or -\f[V]dynamic_dump\f[R] (STRING, no default value) -.IP \[bu] 2 -\f[I]filename\f[R]: (Optional) Name of the shared archive to be dumped. -If %p is specified in the filename, it is expanded to the JVM\[aq]s PID. -(FILE, \[dq]java_pid%p_<subcmd>.jsa\[dq]) -.PP -If \f[V]dynamic_dump\f[R] is specified, the target JVM must be started -with the JVM option \f[V]-XX:+RecordDynamicDumpInfo\f[R]. -.RE -.TP -\f[V]VM.class_hierarchy\f[R] [\f[I]options\f[R]] [\f[I]arguments\f[R]] -Print a list of all loaded classes, indented to show the class -hierarchy. -The name of each class is followed by the ClassLoaderData* of its -ClassLoader, or \[dq]null\[dq] if it is loaded by the bootstrap class -loader. -.RS -.PP -Impact: Medium --- depends on the number of loaded classes. -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-i\f[R]: (Optional) Inherited interfaces should be printed. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]-s\f[R]: (Optional) If a classname is specified, print its -subclasses in addition to its superclasses. -Without this option only the superclasses will be printed. -(BOOLEAN, false) -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]classname\f[R]: (Optional) The name of the class whose hierarchy -should be printed. -If not specified, all class hierarchies are printed. -(STRING, no default value) -.RE -.TP -\f[V]VM.classes\f[R] [\f[I]options\f[R]] -Print all loaded classes -.RS -.PP -Impact: Medium: Depends on number of loaded classes. -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-verbose\f[R]: (Optional) Dump the detailed content of a Java -class. -Some classes are annotated with flags: \f[V]F\f[R] = has, or inherits, a -non-empty finalize method, \f[V]f\f[R] = has final method, \f[V]W\f[R] = -methods rewritten, \f[V]C\f[R] = marked with \f[V]\[at]Contended\f[R] -annotation, \f[V]R\f[R] = has been redefined, \f[V]S\f[R] = is shared -class (BOOLEAN, false) -.RE -.TP -\f[V]VM.classloader_stats\f[R] -Print statistics about all ClassLoaders. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]VM.classloaders\f[R] [\f[I]options\f[R]] -Prints classloader hierarchy. -.RS -.PP -Impact: Medium --- Depends on number of class loaders and classes -loaded. -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]show-classes\f[R]: (Optional) Print loaded classes. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]verbose\f[R]: (Optional) Print detailed information. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]fold\f[R]: (Optional) Show loaders of the same name and class as -one. -(BOOLEAN, true) -.RE -.TP -\f[V]VM.command_line\f[R] -Print the command line used to start this VM instance. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]VM.dynlibs\f[R] -Print loaded dynamic libraries. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]VM.events\f[R] [\f[I]options\f[R]] -Print VM event logs -.RS -.PP -Impact: Low --- Depends on event log size. -.PP -\f[I]options\f[R]: -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.IP \[bu] 2 -\f[V]log\f[R]: (Optional) Name of log to be printed. -If omitted, all logs are printed. -(STRING, no default value) -.IP \[bu] 2 -\f[V]max\f[R]: (Optional) Maximum number of events to be printed (newest -first). -If omitted, all events are printed. -(STRING, no default value) -.RE -.TP -\f[V]VM.flags\f[R] [\f[I]options\f[R]] -Print the VM flag options and their current values. -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-all\f[R]: (Optional) Prints all flags supported by the VM -(BOOLEAN, false). -.RE -.TP -\f[V]VM.info\f[R] -Print information about the JVM environment and status. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]VM.log\f[R] [\f[I]options\f[R]] -Lists current log configuration, enables/disables/configures a log -output, or rotates all logs. -.RS -.PP -Impact: Low -.PP -\f[I]options\f[R]: -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.IP \[bu] 2 -\f[V]output\f[R]: (Optional) The name or index (#) of output to -configure. -(STRING, no default value) -.IP \[bu] 2 -\f[V]output_options\f[R]: (Optional) Options for the output. -(STRING, no default value) -.IP \[bu] 2 -\f[V]what\f[R]: (Optional) Configures what tags to log. -(STRING, no default value ) -.IP \[bu] 2 -\f[V]decorators\f[R]: (Optional) Configures which decorators to use. -Use \[aq]none\[aq] or an empty value to remove all. -(STRING, no default value) -.IP \[bu] 2 -\f[V]disable\f[R]: (Optional) Turns off all logging and clears the log -configuration. -(BOOLEAN, no default value) -.IP \[bu] 2 -\f[V]list\f[R]: (Optional) Lists current log configuration. -(BOOLEAN, no default value) -.IP \[bu] 2 -\f[V]rotate\f[R]: (Optional) Rotates all logs. -(BOOLEAN, no default value) -.RE -.TP -\f[V]VM.metaspace\f[R] [\f[I]options\f[R]] -Prints the statistics for the metaspace -.RS -.PP -Impact: Medium --- Depends on number of classes loaded. -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]basic\f[R]: (Optional) Prints a basic summary (does not need a -safepoint). -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]show-loaders\f[R]: (Optional) Shows usage by class loader. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]show-classes\f[R]: (Optional) If show-loaders is set, shows loaded -classes for each loader. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]by-chunktype\f[R]: (Optional) Break down numbers by chunk type. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]by-spacetype\f[R]: (Optional) Break down numbers by loader type. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]vslist\f[R]: (Optional) Shows details about the underlying virtual -space. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]chunkfreelist\f[R]: (Optional) Shows details about global chunk -free lists (ChunkManager). -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]scale\f[R]: (Optional) Memory usage in which to scale. -Valid values are: 1, KB, MB or GB (fixed scale) or \[dq]dynamic\[dq] for -a dynamically chosen scale. -(STRING, dynamic) -.RE -.TP -\f[V]VM.native_memory\f[R] [\f[I]options\f[R]] -Print native memory usage -.RS -.PP -Impact: Medium -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]summary\f[R]: (Optional) Requests runtime to report current memory -summary, which includes total reserved and committed memory, along with -memory usage summary by each subsystem. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]detail\f[R]: (Optional) Requests runtime to report memory -allocation >= 1K by each callsite. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]baseline\f[R]: (Optional) Requests runtime to baseline current -memory usage, so it can be compared against in later time. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]summary.diff\f[R]: (Optional) Requests runtime to report memory -summary comparison against previous baseline. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]detail.diff\f[R]: (Optional) Requests runtime to report memory -detail comparison against previous baseline, which shows the memory -allocation activities at different callsites. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]statistics\f[R]: (Optional) Prints tracker statistics for tuning -purpose. -(BOOLEAN, false) -.IP \[bu] 2 -\f[V]scale\f[R]: (Optional) Memory usage in which scale, KB, MB or GB -(STRING, KB) -.RE -.TP -\f[V]VM.set_flag\f[R] [\f[I]arguments\f[R]] -Sets VM flag option using the provided value. -.RS -.PP -Impact: Low -.PP -\f[I]arguments\f[R]: -.IP \[bu] 2 -\f[I]flag name\f[R]: The name of the flag that you want to set (STRING, -no default value) -.IP \[bu] 2 -\f[I]string value\f[R]: (Optional) The value that you want to set -(STRING, no default value) -.RE -.TP -\f[V]VM.stringtable\f[R] [\f[I]options\f[R]] -Dump string table. -.RS -.PP -Impact: Medium --- depends on the Java content. -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-verbose\f[R]: (Optional) Dumps the content of each string in the -table (BOOLEAN, false) -.RE -.TP -\f[V]VM.symboltable\f[R] [\f[I]options\f[R]] -Dump symbol table. -.RS -.PP -Impact: Medium --- depends on the Java content. -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax). -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-verbose\f[R]: (Optional) Dumps the content of each symbol in the -table (BOOLEAN, false) -.RE -.TP -\f[V]VM.system_properties\f[R] -Print system properties. -.RS -.PP -Impact: Low -.RE -.TP -\f[V]VM.systemdictionary\f[R] -Prints the statistics for dictionary hashtable sizes and bucket length. -.RS -.PP -Impact: Medium -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]verbose\f[R]: (Optional) Dump the content of each dictionary entry -for all class loaders (BOOLEAN, false) . -.RE -.TP -\f[V]VM.uptime\f[R] [\f[I]options\f[R]] -Print VM uptime. -.RS -.PP -Impact: Low -.PP -\f[B]Note:\f[R] -.PP -The following \f[I]options\f[R] must be specified using either -\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax. -.PP -\f[I]options\f[R]: -.IP \[bu] 2 -\f[V]-date\f[R]: (Optional) Adds a prefix with the current date -(BOOLEAN, false) -.RE -.TP -\f[V]VM.version\f[R] -Print JVM version information. -.RS -.PP -Impact: Low -.RE diff --git a/src/jdk.jcmd/share/man/jcmd.md b/src/jdk.jcmd/share/man/jcmd.md new file mode 100644 index 00000000000..2d2e08bc9f5 --- /dev/null +++ b/src/jdk.jcmd/share/man/jcmd.md @@ -0,0 +1,1032 @@ +--- +# Copyright (c) 2012, 2024, 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. +# + +title: 'JCMD(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jcmd - send diagnostic command requests to a running Java Virtual Machine +(JVM) + +## Synopsis + +`jcmd` \[*pid* \| *main-class*\] *command*... \| `PerfCounter.print` \| `-f` +*filename* + +`jcmd` \[`-l`\] + +`jcmd` `-h` + +*pid* +: When used, the `jcmd` utility sends the diagnostic command request to the + process ID for the Java process. + +*main-class* +: When used, the `jcmd` utility sends the diagnostic command request to all + Java processes with the specified name of the main class. + +*command* +: The `command` must be a valid `jcmd` command for the selected JVM. The list + of available commands for `jcmd` is obtained by running the `help` command + (`jcmd` *pid* `help`) where *pid* is the process ID for the running Java + process. + +`Perfcounter.print` +: Prints the performance counters exposed by the specified Java process. + +`-f` *filename* +: Reads and executes commands from a specified file, *filename*. + +`-l` +: Displays the list of Java Virtual Machine process identifiers that are not + running in a separate docker process along with the main class and + command-line arguments that were used to launch the process. If the JVM is + in a docker process, you must use tools such as `ps` to look up the PID. + + **Note:** + + Using `jcmd` without arguments is the same as using `jcmd -l`. + +`-h` +: Displays the `jcmd` utility's command-line help. + +## Description + +The `jcmd` utility is used to send diagnostic command requests to the JVM. It +must be used on the same machine on which the JVM is running, and have the same +effective user and group identifiers that were used to launch the JVM. Each +diagnostic command has its own set of options and arguments. To display the description, +syntax, and a list of available options and arguments for a diagnostic command, use the +name of the command as the argument. For example: + +> `jcmd` *pid* `help` *command* + +If arguments contain spaces, then you must surround them with single or double +quotation marks (`'` or `"`). In addition, you must escape single or double +quotation marks with a backslash (`\`) to prevent the operating system shell +from processing quotation marks. Alternatively, you can surround these +arguments with single quotation marks and then with double quotation marks (or +with double quotation marks and then with single quotation marks). + +If you specify the process identifier (*pid*) or the main class (*main-class*) +as the first argument, then the `jcmd` utility sends the diagnostic command +request to the Java process with the specified identifier or to all Java +processes with the specified name of the main class. You can also send the +diagnostic command request to all available Java processes by specifying `0` as +the process identifier. + +## Commands for jcmd + +The *command* must be a valid `jcmd` diagnostic command for the selected JVM. +The list of available commands for `jcmd` is obtained by running the `help` +command (`jcmd` *pid* `help`) where *pid* is the process ID for a running Java +process. If the *pid* is `0`, commands will be sent to all Java processes. The +main class argument will be used to match, either partially or fully, the class +used to start Java. If no options are given, it lists the running Java process +identifiers that are not in separate docker processes along with the main class +and command-line arguments that were used to launch the process (the same as +using `-l`). + +`jcmd` *commands* may take options and arguments. *Options* are specified using +either *key* or *key*`=`*value* syntax. *Arguments* are given as just a value, +never name=value. + + +The following commands are available: + +`help` \[*options*\] \[*arguments*\] +: For more information about a specific command. + + *arguments*: + + - *command name*: The name of the command for which we want help (STRING, + no default value) + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-all`: (Optional) Show help for all commands (BOOLEAN, false) . + +`Compiler.CodeHeap_Analytics` \[*function*\] \[*granularity*\] +: Print CodeHeap analytics + + Impact: Low: Depends on code heap size and content. Holds CodeCache_lock during analysis step, usually sub-second duration. + + *arguments*: + + - *function*: (Optional) Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, discard (STRING, all) + + - *granularity*: (Optional) Detail level - smaller value -> more detail (INT, 4096) + +`Compiler.codecache` +: Prints code cache layout and bounds. + + Impact: Low + +`Compiler.codelist` +: Prints all compiled methods in code cache that are alive. + + Impact: Medium + +`Compiler.directives_add` *arguments* +: Adds compiler directives from a file. + + Impact: Low + + *arguments*: + + - *filename*: The name of the directives file (STRING, no default value) + +`Compiler.directives_clear` +: Remove all compiler directives. + + Impact: Low + +`Compiler.directives_print` +: Prints all active compiler directives. + + Impact: Low + +`Compiler.directives_remove` +: Remove latest added compiler directive. + + Impact: Low + +`Compiler.memory` \[*options*\] +: Print compilation footprint + + Impact: Medium: Pause time depends on number of compiled methods + + **Note:** + + The *options* must be specified using either *key* or *key*`=`*value* + syntax. + + *options*: + + - `-H`: (Optional) Human readable format (BOOLEAN, false) + - `-s`: (Optional) Minimum memory size (MEMORY SIZE, 0) + +`Compiler.perfmap` \[*arguments*\] (Linux only) +: Write map file for Linux perf tool. + + Impact: Low + + *arguments*: + + - *filename*: (Optional) The name of the map file. If %p is specified in the filename, it is expanded to the JVM's PID. (FILE, "/tmp/perf-%p.map") + +`Compiler.queue` +: Prints methods queued for compilation. + + Impact: Low + +`GC.class_histogram` \[*options*\] +: Provides statistics about the Java heap usage. + + Impact: High --- depends on Java heap size and content. + + **Note:** + + The *options* must be specified using either *key* or *key*`=`*value* + syntax. + + *options*: + + - `-all`: (Optional) Inspects all objects, including unreachable objects + (BOOLEAN, false) + - `-parallel`: (Optional) Number of parallel threads to use for heap inspection. + 0 (the default) means let the VM determine the number of threads to use. + 1 means use one thread (disable parallelism). For any other value the VM will + try to use the specified number of threads, but might use fewer. (INT, 0) + +`GC.finalizer_info` +: Provides information about the Java finalization queue. + + Impact: Medium + +`GC.heap_dump` \[*options*\] *filename* +: Generates a HPROF format dump of the Java heap. + + Impact: High --- depends on the Java heap size and content. Request a full + GC unless the `-all` option is specified. + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-all`: (Optional) Dump all objects, including unreachable objects + (BOOLEAN, false) + - `-gz`: (Optional) If specified, the heap dump is written in gzipped format + using the given compression level. 1 (recommended) is the fastest, 9 the + strongest compression. (INT, 1) + - `-overwrite`: (Optional) If specified, the dump file will be overwritten if + it exists (BOOLEAN, false) + - `-parallel`: (Optional) Number of parallel threads to use for heap dump. The VM will try to use the specified number of threads, but might use fewer. (INT, 1) + + *arguments*: + + - *filename*: The name of the dump file. If %p is specified in the filename, it is expanded to the JVM's PID. (FILE, no default value) + +`GC.heap_info` +: Provides generic Java heap information. + + Impact: Medium + +`GC.run` +: Calls `java.lang.System.gc()`. + + Impact: Medium --- depends on the Java heap size and content. + +`GC.run_finalization` +: Calls `java.lang.System.runFinalization()`. + + Impact: Medium --- depends on the Java content. + +`JFR.check` \[*options*\] +: Show information about a running flight recording + + Impact: Low + + **Note:** + + The *options* must be specified using either *key* or *key*`=`*value* + syntax. If no parameters are entered, information for all active recordings is shown. + + *options*: + + - `name`: (Optional) Name of the flight recording. (STRING, no default value) + + - `verbose`: (Optional) Flag for printing the event settings for the recording + (BOOLEAN, false) + +`JFR.configure` \[*options*\] +: Set the parameters for a flight recording + + Impact: Low + + **Note:** + + The *options* must be specified using either *key* or *key*`=`*value* + syntax. If no parameters are entered, the current settings are displayed. + + *options*: + + - `dumppath`: (Optional) Path to the location where a recording file is written + in case the VM runs into a critical error, such as a system + crash. (STRING, The default location is the current directory) + + - `globalbuffercount`: (Optional) Number of global buffers. This option is + a legacy option: change the `memorysize` parameter to alter the number of + global buffers. This value cannot be changed once JFR has been initialized. + (STRING, default determined by the value for `memorysize`) + + - `globalbuffersize`: (Optional) Size of the global buffers, in bytes. This + option is a legacy option: change the `memorysize` parameter to alter + the size of the global buffers. This value cannot be changed once JFR + has been initialized. (STRING, default determined by the value for `memorysize`) + + - `maxchunksize`: (Optional) Maximum size of an individual data chunk in bytes + if one of the following suffixes is not used: 'm' or 'M' for megabytes OR + 'g' or 'G' for gigabytes. This value cannot be changed once JFR has been + initialized. (STRING, 12M) + + - `memorysize`: (Optional) Overall memory size, in bytes if one of the following + suffixes is not used: 'm' or 'M' for megabytes OR 'g' or 'G' for gigabytes. + This value cannot be changed once JFR has been initialized. (STRING, 10M) + + - `repositorypath`: (Optional) Path to the location where recordings are stored + until they are written to a permanent file. (STRING, The default location is + the temporary directory for the operating system. On Linux operating systems, + the temporary directory is `/tmp`. On Windwows, the temporary directory is + specified by the `TMP` environment variable.) + + - `preserve-repository=`{`true`\|`false`} : Specifies whether files stored in + the disk repository should be kept after the JVM has exited. If false, files + are deleted. By default, this parameter is disabled. + + - `stackdepth`: (Optional) Stack depth for stack traces. Setting this value + greater than the default of 64 may cause a performance degradation. + This value cannot be changed once JFR has been initialized. (LONG, 64) + + - `thread_buffer_size`: (Optional) Local buffer size for each thread in bytes if one + of the following suffixes is not used: 'k' or 'K' for kilobytes or 'm' or 'M' + for megabytes. Overriding this parameter could reduce performance and is + not recommended. This value cannot be changed once JFR has been initialized. + (STRING, 8k) + + - `samplethreads`: (Optional) Flag for activating thread sampling. (BOOLEAN, true) + +`JFR.dump` \[*options*\] +: Write data to a file while a flight recording is running + + Impact: Low + + **Note:** + + The *options* must be specified using either *key* or *key*`=`*value* syntax. + No options are required. The recording continues to run after the data is written. + + *options*: + + - `begin`: (Optional) Specify the time from which recording data will be included + in the dump file. The format is specified as local time. (STRING, no default value) + + - `end`: (Optional) Specify the time to which recording data will be included in the + dump file. The format is specified as local time. (STRING, no default value) + + **Note:** For both `begin` and `end`, the time must be in a format that can be read + by java.time.LocalTime::parse(STRING), java.time.LocalDateTime::parse(STRING) + or java.time.Instant::parse(STRING). For example, "13:20:15", "2020-03-17T09:00:00" + or "2020-03-17T09:00:00Z". + + **Note:** `begin` and `end` times correspond to the timestamps found within the recorded + information in the flight recording data. + + Another option is to use a time relative to the current time that is specified + by a negative integer followed by "s", "m" or "h". For example, "-12h", "-15m" or "-30s" + + - `filename`: (Optional) Name of the file to which the flight recording data + is dumped. If no filename is given, a filename is generated from the PID and + the current date. The filename may also be a directory in which case, the filename + is generated from the PID and the current date in the specified directory. + If %p and/or %t is specified in the filename, it expands to the JVM's PID and + the current timestamp, respectively. + (FILE, no default value) + + - `maxage`: (Optional) Length of time for dumping the flight recording data + to a file. (INTEGER followed by 's' for seconds 'm' for minutes or 'h' for hours, + no default value) + + - `maxsize`: (Optional) Maximum size for the amount of data to dump from a flight + recording in bytes if one of the following suffixes is not used: 'm' or 'M' for megabytes + OR 'g' or 'G' for gigabytes. (STRING, no default value) + + - `name`: (Optional) Name of the recording. If no name is given, data + from all recordings is dumped. (STRING, no default value) + + - `path-to-gc-roots`: (Optional) Flag for saving the path to garbage collection (GC) + roots at the time the recording data is dumped. The path information is useful for + finding memory leaks but collecting it can cause the application to pause for + a short period of time. Turn on this flag only when you have an application + that you suspect has a memory leak. (BOOLEAN, false) + +`JFR.start` \[*options*\] +: Start a flight recording + + Impact: Low + + **Note:** + + The *options* must be specified using either *key* or *key*`=`*value* + syntax. If no parameters are entered, then a recording is started with default values. + + *options*: + + - `delay`: (Optional) Length of time to wait before starting to record + (INTEGER followed by 's' for seconds 'm' for minutes or 'h' for hours, 0s) + + - `disk`: (Optional) Flag for also writing the data to disk while recording + (BOOLEAN, true) + + - `dumponexit`: (Optional) Flag for writing the recording to disk when the + Java Virtual Machine (JVM) shuts down. If set to 'true' and no value is given + for `filename`, the recording is written to a file in the directory where + the process was started. The file name is a system-generated name that + contains the process ID, the recording ID and the current time stamp. + (For example: `id-1-2019_12_12_10_41.jfr`) (BOOLEAN, false) + + - `duration`: (Optional) Length of time to record. Note that `0s` means forever + (INTEGER followed by 's' for seconds 'm' for minutes or 'h' for hours, 0s) + + - `filename`: (Optional) Name of the file to which the flight recording data + is written when the recording is stopped. If no filename is given, a filename + is generated from the PID and the current date and is placed in the directory + where the process was started. The filename may also be a directory in which case, + the filename is generated from the PID and the current date in the specified directory. + If %p and/or %t is specified in the filename, it expands to the JVM's PID + and the current timestamp, respectively. + (FILE, no default value) + + - `maxage`: (Optional) Maximum time to keep the recorded data on disk. This + parameter is valid only when the `disk` parameter is set to `true`. Note + `0s` means forever. (INTEGER followed by 's' for seconds 'm' + for minutes or 'h' for hours, 0s) + + - `maxsize`: (Optional) Maximum size of the data to keep on disk in bytes if one + of the following suffixes is not used: 'm' or 'M' for megabytes OR 'g' or 'G' for gigabytes. + This parameter is valid only when the `disk` parameter is set to 'true'. The value must + not be less than the value for the `maxchunksize` parameter set with the `JFR.configure` command. + (STRING, 0 (no maximum size)) + + - `name`: (Optional) Name of the recording. If no name is provided, a name is generated. + Make note of the generated name that is shown in the response to the command so that + you can use it with other commands. (STRING, system-generated default name) + + - `path-to-gc-roots`: (Optional) Flag for saving the path to garbage collection (GC) + roots at the end of a recording. The path information is useful for finding memory leaks + but collecting it is time consuming. Turn on this flag only when you + have an application that you suspect has a memory leak. If the `settings` parameter + is set to 'profile', then the information collected includes the stack trace + from where the potential leaking object was allocated. (BOOLEAN, false) + + - `settings`: (Optional) Name of the settings file that identifies which events to record. + To specify more than one file, separate the names with a comma (','). Include the path + if the file is not in `JAVA-HOME`/lib/jfr. The following profiles are included with + the JDK in the `JAVA-HOME`/lib/jfr directory: 'default.jfc': collects a predefined set + of information with low overhead, so it has minimal impact on performance and can be + used with recordings that run continuously; 'profile.jfc': Provides more data than the + 'default.jfc' profile, but with more overhead and impact on performance. Use this + configuration for short periods of time when more information is needed. Use `none` to + start a recording without a predefined configuration file. + (STRING, `JAVA-HOME`/lib/jfr/default.jfc) + + Event settings and .jfc options can be specified using the following syntax: + + - `option`: (Optional) Specifies the option value to modify. To list available + options, use the `JAVA_HOME`/bin/jfr tool. + + - `event-setting`: (Optional) Specifies the event setting value to modify. Use the form: + `<event-name>#<setting-name>=<value>` + To add a new event setting, prefix the event name with '+'. + + You can specify values for multiple event settings and .jfc options by + separating them with a whitespace. In case of a conflict between a parameter + and a .jfc option, the parameter will take precedence. The whitespace + delimiter can be omitted for timespan values, i.e. 20ms. For more + information about the settings syntax, see Javadoc of the jdk.jfr + package. + +`JFR.stop` \[*options*\] +: Stop a flight recording + + Impact: Low + + **Note:** + + The *options* must be specified using either *key* or *key*`=`*value* + syntax. If no parameters are entered, then no recording is stopped. + + *options*: + + - `filename`: (Optional) Name of the file to which the recording is + written when the recording is stopped. If %p and/or %t is specified + in the filename, it expands to the JVM's PID and the current + timestamp, respectively. If no path is provided, the data from the + recording is discarded. (FILE, no default value) + + - `name`: (Optional) Name of the recording (STRING, no default value) + + +`JFR.view` \[*options*\] +: Display event data in predefined views. + + Impact: Medium + + **Note:** + + The *options* must be specified using either *key* or *key*`=`*value* + syntax. If no parameters are entered, then a list of available views + are displayed. + + *options*: + + - `cell-height`: (Optional) Maximum number of rows in a table cell. + (INT, default value depends on the view) + + - `maxage`: (Optional) Length of time for the view to span. + (INT followed by 's' for seconds 'm' for minutes or 'h' for hours, + default value is 10m) + + - `maxsize`: (Optional) Maximum size for the view to span in bytes if one + of the following suffixes is not used: 'm' or 'M' for megabytes OR + 'g' or 'G' for gigabytes. (STRING, default value is 32MB) + + - `truncate`: (Optional) Maximum number of rows in a table cell. + (INT, default value depends on the view) + + - `verbose`: (Optional) Displays the query that makes up the view. + (BOOLEAN, default value is false) + + - `width`: (Optional) The width of the view in characters. (INT, + default value depends on the view) + + *arguments*: + + - `view`: Name of the view or event type to display. Use `help JFR.view` + to see a list of available views. (STRING, no default value) + + The view parameter can be an event type name. Use `JFR.view types` to see + a list. To display all views, use `JFR.view all-views`. To display all + events, use `JFR.view all-events`. + +`JVMTI.agent_load` \[*arguments*\] +: Loads JVMTI native agent. + + Impact: Low + + *arguments*: + + - *library path*: Absolute path of the JVMTI agent to load. (STRING, no + default value) + + - *agent option*: (Optional) Option string to pass the agent. (STRING, no + default value) + +`JVMTI.data_dump` +: Signal the JVM to do a data-dump request for JVMTI. + + Impact: High + +`ManagementAgent.start` \[*options*\] +: Starts remote management agent. + + Impact: Low --- no impact + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `config.file`: (Optional) Sets `com.sun.management.config.file` + (STRING, no default value) + + - `jmxremote.host`: (Optional) Sets `com.sun.management.jmxremote.host` + (STRING, no default value) + + - `jmxremote.port`: (Optional) Sets `com.sun.management.jmxremote.port` + (STRING, no default value) + + - `jmxremote.rmi.port`: (Optional) Sets + `com.sun.management.jmxremote.rmi.port` (STRING, no default value) + + - `jmxremote.ssl`: (Optional) Sets `com.sun.management.jmxremote.ssl` + (STRING, no default value) + + - `jmxremote.registry.ssl`: (Optional) Sets + `com.sun.management.jmxremote.registry.ssl` (STRING, no default value) + + - `jmxremote.authenticate`: (Optional) Sets + `com.sun.management.jmxremote.authenticate` (STRING, no default value) + + - jmxremote.password.file: (Optional) Sets + `com.sun.management.jmxremote.password.file` (STRING, no default value) + + - `jmxremote.access.file`: (Optional) Sets + `com.sun.management.jmxremote.acce ss.file` (STRING, no default value) + + - `jmxremote.login.config`: (Optional) Sets + `com.sun.management.jmxremote.log in.config` (STRING, no default value) + + - `jmxremote.ssl.enabled.cipher.suites`: (Optional) Sets + `com.sun.management`. + + - `jmxremote.ssl.enabled.cipher.suite`: (STRING, no default value) + + - `jmxremote.ssl.enabled.protocols`: (Optional) Sets + `com.sun.management.jmxr emote.ssl.enabled.protocols` (STRING, no + default value) + + - `jmxremote.ssl.need.client.auth`: (Optional) Sets + `com.sun.management.jmxre mote.need.client.auth` (STRING, no default + value) + + - `jmxremote.ssl.config.file`: (Optional) Sets + `com.sun.management.jmxremote. ssl_config_file` (STRING, no default + value) + + - `jmxremote.autodiscovery`: (Optional) Sets + `com.sun.management.jmxremote.au todiscovery` (STRING, no default + value) + + - `jdp.port`: (Optional) Sets `com.sun.management.jdp.port` (INT, no + default value) + + - `jdp.address`: (Optional) Sets `com.sun.management.jdp.address` + (STRING, no default value) + + - `jdp.source_addr`: (Optional) Sets `com.sun.management.jdp.source_addr` + (STRING, no default value) + + - `jdp.ttl`: (Optional) Sets `com.sun.management.jdp.ttl` (INT, no + default value) + + - `jdp.pause`: (Optional) Sets `com.sun.management.jdp.pause` (INT, no + default value) + + - `jdp.name`: (Optional) Sets `com.sun.management.jdp.name` (STRING, no + default value) + +`ManagementAgent.start_local` +: Starts the local management agent. + + Impact: Low --- no impact + +`ManagementAgent.status` +: Print the management agent status. + + Impact: Low --- no impact + +`ManagementAgent.stop` +: Stops the remote management agent. + + Impact: Low --- no impact + +`System.dump_map` \[*options*\] (Linux only) +: Dumps an annotated process memory map to an output file. + + Impact: Low + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-H`: (Optional) Human readable format (BOOLEAN, false) + - `-F`: (Optional) File path. If %p is specified in the filename, it is expanded to the JVM's PID. (FILE, "vm_memory_map_%p.txt") + +`System.map` \[*options*\] (Linux only) +: Prints an annotated process memory map of the VM process. + + Impact: Low + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-H`: (Optional) Human readable format (BOOLEAN, false) + +`System.native_heap_info` (Linux only) +: Attempts to output information regarding native heap usage through malloc_info(3). If unsuccessful outputs "Error: " and a reason. + + Impact: Low + +`System.trim_native_heap` (Linux only) +: Attempts to free up memory by trimming the C-heap. + + Impact: Low + +`Thread.dump_to_file` \[*options*\] *filepath* +: Dump threads, with stack traces, to a file in plain text or JSON format. + + Impact: Medium: Depends on the number of threads. + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-overwrite`: (Optional) May overwrite existing file (BOOLEAN, false) + - `-format`: (Optional) Output format ("plain" or "json") (STRING, plain) + + *arguments*: + + - *filepath*: The file path to the output file. If %p is specified in the filename, it is expanded to the JVM's PID. (FILE, no default value) + +`Thread.print` \[*options*\] +: Prints all threads with stacktraces. + + Impact: Medium --- depends on the number of threads. + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-e`: (Optional) Print extended thread information (BOOLEAN, false) + - `-l`: (Optional) Prints `java.util.concurrent` locks (BOOLEAN, false) + +`VM.cds` \[*arguments*\] +: Dump a static or dynamic shared archive that includes all currently loaded classes. + + Impact: Medium --- pause time depends on number of loaded classes + + *arguments*: + + - *subcmd*: must be either `static_dump` or `dynamic_dump` (STRING, no default value) + - *filename*: (Optional) Name of the shared archive to be dumped. If %p is specified in the filename, it is expanded to the JVM's PID. (FILE, "java_pid%p_\<subcmd\>.jsa") + + If `dynamic_dump` is specified, the target JVM must be started with the JVM option + `-XX:+RecordDynamicDumpInfo`. + +`VM.class_hierarchy` \[*options*\] \[*arguments*\] +: Print a list of all loaded classes, indented to show the class hierarchy. + The name of each class is followed by the ClassLoaderData\* of its + ClassLoader, or "null" if it is loaded by the bootstrap class loader. + + Impact: Medium --- depends on the number of loaded classes. + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-i`: (Optional) Inherited interfaces should be printed. (BOOLEAN, + false) + + - `-s`: (Optional) If a classname is specified, print its subclasses + in addition to its superclasses. Without this option only the + superclasses will be printed. (BOOLEAN, false) + + *arguments*: + + - *classname*: (Optional) The name of the class whose hierarchy should be + printed. If not specified, all class hierarchies are printed. (STRING, + no default value) + +`VM.classes` \[*options*\] +: Print all loaded classes + + Impact: Medium: Depends on number of loaded classes. + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-verbose`: (Optional) Dump the detailed content of a Java class. + Some classes are annotated with flags: `F` = has, or inherits, a non-empty finalize method, + `f` = has final method, `W` = methods rewritten, `C` = marked with `@Contended` annotation, + `R` = has been redefined, `S` = is shared class (BOOLEAN, false) + +`VM.classloader_stats` +: Print statistics about all ClassLoaders. + + Impact: Low + +`VM.classloaders` \[*options*\] +: Prints classloader hierarchy. + + Impact: Medium --- Depends on number of class loaders and classes loaded. + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `show-classes`: (Optional) Print loaded classes. (BOOLEAN, false) + - `verbose`: (Optional) Print detailed information. (BOOLEAN, false) + - `fold`: (Optional) Show loaders of the same name and class as one. (BOOLEAN, true) + +`VM.command_line` +: Print the command line used to start this VM instance. + + Impact: Low + +`VM.dynlibs` +: Print loaded dynamic libraries. + + Impact: Low + +`VM.events` \[*options*\] +: Print VM event logs + + Impact: Low --- Depends on event log size. + + *options*: + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + - `log`: (Optional) Name of log to be printed. + If omitted, all logs are printed. (STRING, no default value) + - `max`: (Optional) Maximum number of events to be printed (newest first). + If omitted or zero, all events are printed. (INT, 0) + +`VM.flags` \[*options*\] +: Print the VM flag options and their current values. + + Impact: Low + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-all`: (Optional) Prints all flags supported by the VM (BOOLEAN, + false). + +`VM.info` +: Print information about the JVM environment and status. + + Impact: Low + +`VM.log` \[*options*\] +: Lists current log configuration, enables/disables/configures a log output, + or rotates all logs. + + Impact: Low + + *options*: + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + - `output`: (Optional) The name or index (\#) of output to configure. + (STRING, no default value) + + - `output_options`: (Optional) Options for the output. (STRING, no + default value) + + - `what`: (Optional) Configures what tags to log. (STRING, no default + value ) + + - `decorators`: (Optional) Configures which decorators to use. Use 'none' + or an empty value to remove all. (STRING, no default value) + + - `disable`: (Optional) Turns off all logging and clears the log + configuration. (BOOLEAN, no default value) + + - `list`: (Optional) Lists current log configuration. (BOOLEAN, no + default value) + + - `rotate`: (Optional) Rotates all logs. (BOOLEAN, no default value) + +`VM.metaspace` \[*options*\] +: Prints the statistics for the metaspace + + Impact: Medium --- Depends on number of classes loaded. + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `basic`: (Optional) Prints a basic summary (does not need a safepoint). (BOOLEAN, false) + - `show-loaders`: (Optional) Shows usage by class loader. (BOOLEAN, false) + - `show-classes`: (Optional) If show-loaders is set, shows loaded classes for each loader. (BOOLEAN, false) + - `by-chunktype`: (Optional) Break down numbers by chunk type. (BOOLEAN, false) + - `by-spacetype`: (Optional) Break down numbers by loader type. (BOOLEAN, false) + - `vslist`: (Optional) Shows details about the underlying virtual space. (BOOLEAN, false) + - `chunkfreelist`: (Optional) Shows details about global chunk free lists (ChunkManager). (BOOLEAN, false) + - `scale`: (Optional) Memory usage in which to scale. Valid values are: 1, KB, MB + or GB (fixed scale) or "dynamic" for a dynamically chosen scale. (STRING, dynamic) + +`VM.native_memory` \[*options*\] +: Print native memory usage + + Impact: Medium + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `summary`: (Optional) Requests runtime to report current memory + summary, which includes total reserved and committed memory, along with + memory usage summary by each subsystem. (BOOLEAN, false) + + - `detail`: (Optional) Requests runtime to report memory allocation >= + 1K by each callsite. (BOOLEAN, false) + + - `baseline`: (Optional) Requests runtime to baseline current memory + usage, so it can be compared against in later time. (BOOLEAN, false) + + - `summary.diff`: (Optional) Requests runtime to report memory summary + comparison against previous baseline. (BOOLEAN, false) + + - `detail.diff`: (Optional) Requests runtime to report memory detail + comparison against previous baseline, which shows the memory allocation + activities at different callsites. (BOOLEAN, false) + + - `statistics`: (Optional) Prints tracker statistics for tuning purpose. + (BOOLEAN, false) + + - `scale`: (Optional) Memory usage in which scale, KB, MB or GB (STRING, + KB) + +`VM.set_flag` \[*arguments*\] +: Sets VM flag option using the provided value. + + Impact: Low + + *arguments*: + + - *flag name*: The name of the flag that you want to set (STRING, no + default value) + + - *string value*: (Optional) The value that you want to set (STRING, no + default value) + +`VM.stringtable` \[*options*\] +: Dump string table. + + Impact: Medium --- depends on the Java content. + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-verbose`: (Optional) Dumps the content of each string in the table + (BOOLEAN, false) + +`VM.symboltable` \[*options*\] +: Dump symbol table. + + Impact: Medium --- depends on the Java content. + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax). + + *options*: + + - `-verbose`: (Optional) Dumps the content of each symbol in the table + (BOOLEAN, false) + +`VM.system_properties` +: Print system properties. + + Impact: Low + +`VM.systemdictionary` +: Prints the statistics for dictionary hashtable sizes and bucket length. + + Impact: Medium + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `verbose`: (Optional) Dump the content of each dictionary entry for all + class loaders (BOOLEAN, false) . + +`VM.uptime` \[*options*\] +: Print VM uptime. + + Impact: Low + + **Note:** + + The following *options* must be specified using either *key* or + *key*`=`*value* syntax. + + *options*: + + - `-date`: (Optional) Adds a prefix with the current date (BOOLEAN, + false) + +`VM.version` +: Print JVM version information. + + Impact: Low diff --git a/src/jdk.jcmd/share/man/jinfo.1 b/src/jdk.jcmd/share/man/jinfo.1 deleted file mode 100644 index 49d8a852633..00000000000 --- a/src/jdk.jcmd/share/man/jinfo.1 +++ /dev/null @@ -1,103 +0,0 @@ -.\" Copyright (c) 2004, 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 -.\" 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JINFO" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jinfo - generate Java configuration information for a specified Java -process -.SH SYNOPSIS -.PP -\f[B]Note:\f[R] This command is experimental and unsupported. -.PP -\f[V]jinfo\f[R] [\f[I]option\f[R]] \f[I]pid\f[R] -.TP -\f[I]option\f[R] -This represents the \f[V]jinfo\f[R] command-line options. -See \f[B]Options for the jinfo Command\f[R]. -.TP -\f[I]pid\f[R] -The process ID for which the configuration information is to be printed. -The process must be a Java process. -To get a list of Java processes running on a machine, use either the -\f[V]ps\f[R] command or, if the JVM processes are not running in a -separate docker instance, the \f[B]jps\f[R] command. -.SH DESCRIPTION -.PP -The \f[V]jinfo\f[R] command prints Java configuration information for a -specified Java process. -The configuration information includes Java system properties and JVM -command-line flags. -If the specified process is running on a 64-bit JVM, then you might need -to specify the \f[V]-J-d64\f[R] option, for example: -.RS -.PP -\f[V]jinfo -J-d64 -sysprops\f[R] \f[I]pid\f[R] -.RE -.PP -This command is unsupported and might not be available in future -releases of the JDK. -In Windows Systems where \f[V]dbgeng.dll\f[R] is not present, the -Debugging Tools for Windows must be installed to have these tools work. -The \f[V]PATH\f[R] environment variable should contain the location of -the \f[V]jvm.dll\f[R] that\[aq]s used by the target process or the -location from which the core dump file was produced. -.SH OPTIONS FOR THE JINFO COMMAND -.PP -\f[B]Note:\f[R] -.PP -If none of the following options are used, both the command-line flags -and the system property name-value pairs are printed. -.TP -\f[V]-flag\f[R] \f[I]name\f[R] -Prints the name and value of the specified command-line flag. -.TP -\f[V]-flag\f[R] [\f[V]+\f[R]|\f[V]-\f[R]]\f[I]name\f[R] -Enables or disables the specified Boolean command-line flag. -.TP -\f[V]-flag\f[R] \f[I]name\f[R]\f[V]=\f[R]\f[I]value\f[R] -Sets the specified command-line flag to the specified value. -.TP -\f[V]-flags\f[R] -Prints command-line flags passed to the JVM. -.TP -\f[V]-sysprops\f[R] -Prints Java system properties as name-value pairs. -.TP -\f[V]-h\f[R] or \f[V]-help\f[R] -Prints a help message. diff --git a/src/jdk.jcmd/share/man/jinfo.md b/src/jdk.jcmd/share/man/jinfo.md new file mode 100644 index 00000000000..5e8603e0e08 --- /dev/null +++ b/src/jdk.jcmd/share/man/jinfo.md @@ -0,0 +1,88 @@ +--- +# Copyright (c) 2004, 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 +# 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. +# + +title: 'JINFO(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jinfo - generate Java configuration information for a specified Java process + +## Synopsis + +**Note:** This command is experimental and unsupported. + +`jinfo` \[*option*\] *pid* + +*option* +: This represents the `jinfo` command-line options. See [Options for the + jinfo Command]. + +*pid* +: The process ID for which the configuration information is to be printed. + The process must be a Java process. To get a list of Java processes running + on a machine, use either the `ps` command or, if the JVM processes are not + running in a separate docker instance, the [jps](jps.html) command. + +## Description + +The `jinfo` command prints Java configuration information for a specified Java +process. The configuration information includes Java system properties and JVM +command-line flags. If the specified process is running on a 64-bit JVM, then +you might need to specify the `-J-d64` option, for example: + +> `jinfo -J-d64 -sysprops` *pid* + +This command is unsupported and might not be available in future releases of +the JDK. In Windows Systems where `dbgeng.dll` is not present, the Debugging +Tools for Windows must be installed to have these tools work. The `PATH` +environment variable should contain the location of the `jvm.dll` that's used +by the target process or the location from which the core dump file was +produced. + +## Options for the jinfo Command + +**Note:** + +If none of the following options are used, both the command-line flags and the +system property name-value pairs are printed. + +`-flag` *name* +: Prints the name and value of the specified command-line flag. + +`-flag` \[`+`\|`-`\]*name* +: Enables or disables the specified Boolean command-line flag. + +`-flag` *name*`=`*value* +: Sets the specified command-line flag to the specified value. + +`-flags` +: Prints command-line flags passed to the JVM. + +`-sysprops` +: Prints Java system properties as name-value pairs. + +`-h` or `-help` +: Prints a help message. diff --git a/src/jdk.jcmd/share/man/jmap.1 b/src/jdk.jcmd/share/man/jmap.1 deleted file mode 100644 index 42831aa68ac..00000000000 --- a/src/jdk.jcmd/share/man/jmap.1 +++ /dev/null @@ -1,106 +0,0 @@ -.\" Copyright (c) 2004, 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 -.\" 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JMAP" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jmap - print details of a specified process -.SH SYNOPSIS -.PP -\f[B]Note:\f[R] This command is experimental and unsupported. -.PP -\f[V]jmap\f[R] [\f[I]options\f[R]] \f[I]pid\f[R] -.TP -\f[I]options\f[R] -This represents the \f[V]jmap\f[R] command-line options. -See \f[B]Options for the jmap Command\f[R]. -.TP -\f[I]pid\f[R] -The process ID for which the information specified by the -\f[I]options\f[R] is to be printed. -The process must be a Java process. -To get a list of Java processes running on a machine, use either the -\f[V]ps\f[R] command or, if the JVM processes are not running in a -separate docker instance, the \f[B]jps\f[R] command. -.SH DESCRIPTION -.PP -The \f[V]jmap\f[R] command prints details of a specified running -process. -.PP -\f[B]Note:\f[R] -.PP -This command is unsupported and might not be available in future -releases of the JDK. -On Windows Systems where the \f[V]dbgeng.dll\f[R] file isn\[aq]t -present, the Debugging Tools for Windows must be installed to make these -tools work. -The \f[V]PATH\f[R] environment variable should contain the location of -the \f[V]jvm.dll\f[R] file that\[aq]s used by the target process or the -location from which the core dump file was produced. -.SH OPTIONS FOR THE JMAP COMMAND -.TP -\f[V]-clstats\f[R] \f[I]pid\f[R] -Connects to a running process and prints class loader statistics of Java -heap. -.TP -\f[V]-finalizerinfo\f[R] \f[I]pid\f[R] -Connects to a running process and prints information on objects awaiting -finalization. -.TP -\f[V]-histo\f[R][\f[V]:live\f[R]] \f[I]pid\f[R] -Connects to a running process and prints a histogram of the Java object -heap. -If the \f[V]live\f[R] suboption is specified, it then counts only live -objects. -.TP -\f[V]-dump:\f[R]\f[I]dump_options\f[R] \f[I]pid\f[R] -Connects to a running process and dumps the Java heap. -The \f[I]dump_options\f[R] include: -.RS -.IP \[bu] 2 -\f[V]live\f[R] --- When specified, dumps only the live objects; if not -specified, then dumps all objects in the heap. -.IP \[bu] 2 -\f[V]format=b\f[R] --- Dumps the Java heap in \f[V]hprof\f[R] binary -format -.IP \[bu] 2 -\f[V]file=\f[R]\f[I]filename\f[R] --- Dumps the heap to -\f[I]filename\f[R] -.PP -Example: \f[V]jmap -dump:live,format=b,file=heap.bin\f[R] \f[I]pid\f[R] -.RE diff --git a/src/jdk.jcmd/share/man/jmap.md b/src/jdk.jcmd/share/man/jmap.md new file mode 100644 index 00000000000..1f986f97fab --- /dev/null +++ b/src/jdk.jcmd/share/man/jmap.md @@ -0,0 +1,89 @@ +--- +# Copyright (c) 2004, 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 +# 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. +# + +title: 'JMAP(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jmap - print details of a specified process + +## Synopsis + +**Note:** This command is experimental and unsupported. + +`jmap` \[*options*\] *pid* + +*options* +: This represents the `jmap` command-line options. See [Options for the jmap + Command]. + +*pid* +: The process ID for which the information specified by the *options* is to + be printed. The process must be a Java process. To get a list of Java + processes running on a machine, use either the `ps` command or, if the JVM + processes are not running in a separate docker instance, the + [jps](jps.html) command. + +## Description + +The `jmap` command prints details of a specified running process. + +**Note:** + +This command is unsupported and might not be available in future releases of +the JDK. On Windows Systems where the `dbgeng.dll` file isn't present, the +Debugging Tools for Windows must be installed to make these tools work. The +`PATH` environment variable should contain the location of the `jvm.dll` file +that's used by the target process or the location from which the core dump file +was produced. + +## Options for the jmap Command + +`-clstats` *pid* +: Connects to a running process and prints class loader statistics of Java + heap. + +`-finalizerinfo` *pid* +: Connects to a running process and prints information on objects awaiting + finalization. + +`-histo`\[`:live`\] *pid* +: Connects to a running process and prints a histogram of the Java object + heap. If the `live` suboption is specified, it then counts only live + objects. + +`-dump:`*dump\_options* *pid* +: Connects to a running process and dumps the Java heap. The *dump\_options* + include: + + - `live` --- When specified, dumps only the live objects; if not + specified, then dumps all objects in the heap. + + - `format=b` --- Dumps the Java heap in `hprof` binary format + + - `file=`*filename* --- Dumps the heap to *filename* + + Example: `jmap -dump:live,format=b,file=heap.bin` *pid* diff --git a/src/jdk.jcmd/share/man/jps.1 b/src/jdk.jcmd/share/man/jps.1 deleted file mode 100644 index cbc69872b60..00000000000 --- a/src/jdk.jcmd/share/man/jps.1 +++ /dev/null @@ -1,235 +0,0 @@ -.\" Copyright (c) 2004, 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 -.\" 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JPS" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jps - list the instrumented JVMs on the target system -.SH SYNOPSIS -.PP -\f[B]Note:\f[R] This command is experimental and unsupported. -.PP -\f[V]jps\f[R] [\f[V]-q\f[R]] [\f[V]-mlvV\f[R]] [\f[I]hostid\f[R]] -.PP -\f[V]jps\f[R] [\f[V]-help\f[R]] -.SH OPTIONS -.TP -\f[V]-q\f[R] -Suppresses the output of the class name, JAR file name, and arguments -passed to the \f[V]main\f[R] method, producing a list of only local JVM -identifiers. -.TP -\f[V]-mlvV\f[R] -You can specify any combination of these options. -.RS -.IP \[bu] 2 -\f[V]-m\f[R] displays the arguments passed to the \f[V]main\f[R] method. -The output may be \f[V]null\f[R] for embedded JVMs. -.IP \[bu] 2 -\f[V]-l\f[R] displays the full package name for the application\[aq]s -\f[V]main\f[R] class or the full path name to the application\[aq]s JAR -file. -.IP \[bu] 2 -\f[V]-v\f[R] displays the arguments passed to the JVM. -.IP \[bu] 2 -\f[V]-V\f[R] suppresses the output of the class name, JAR file name, and -arguments passed to the \f[V]main\f[R] method, producing a list of only -local JVM identifiers. -.RE -.TP -\f[I]hostid\f[R] -The identifier of the host for which the process report should be -generated. -The \f[V]hostid\f[R] can include optional components that indicate the -communications protocol, port number, and other implementation specific -data. -See \f[B]Host Identifier\f[R]. -.TP -\f[V]-help\f[R] -Displays the help message for the \f[V]jps\f[R] command. -.SH DESCRIPTION -.PP -The \f[V]jps\f[R] command lists the instrumented Java HotSpot VMs on the -target system. -The command is limited to reporting information on JVMs for which it has -the access permissions. -.PP -If the \f[V]jps\f[R] command is run without specifying a -\f[V]hostid\f[R], then it searches for instrumented JVMs on the local -host. -If started with a \f[V]hostid\f[R], then it searches for JVMs on the -indicated host, using the specified protocol and port. -A \f[V]jstatd\f[R] process is assumed to be running on the target host. -.PP -The \f[V]jps\f[R] command reports the local JVM identifier, or -\f[V]lvmid\f[R], for each instrumented JVM found on the target system. -The \f[V]lvmid\f[R] is typically, but not necessarily, the operating -system\[aq]s process identifier for the JVM process. -With no options, the \f[V]jps\f[R] command lists each Java -application\[aq]s \f[V]lvmid\f[R] followed by the short form of the -application\[aq]s class name or jar file name. -The short form of the class name or JAR file name omits the class\[aq]s -package information or the JAR files path information. -.PP -The \f[V]jps\f[R] command uses the Java launcher to find the class name -and arguments passed to the main method. -If the target JVM is started with a custom launcher, then the class or -JAR file name, and the arguments to the \f[V]main\f[R] method aren\[aq]t -available. -In this case, the \f[V]jps\f[R] command outputs the string -\f[V]Unknown\f[R] for the class name, or JAR file name, and for the -arguments to the \f[V]main\f[R] method. -.PP -The list of JVMs produced by the \f[V]jps\f[R] command can be limited by -the permissions granted to the principal running the command. -The command lists only the JVMs for which the principal has access -rights as determined by operating system-specific access control -mechanisms. -.SH HOST IDENTIFIER -.PP -The host identifier, or \f[V]hostid\f[R], is a string that indicates the -target system. -The syntax of the \f[V]hostid\f[R] string corresponds to the syntax of a -URI: -.RS -.PP -[\f[I]protocol\f[R]\f[V]:\f[R]][[\f[V]//\f[R]]\f[I]hostname\f[R]][\f[V]:\f[R]\f[I]port\f[R]][\f[V]/\f[R]\f[I]servername\f[R]] -.RE -.TP -\f[I]protocol\f[R] -The communications protocol. -If the \f[I]protocol\f[R] is omitted and a \f[I]hostname\f[R] isn\[aq]t -specified, then the default protocol is a platform-specific, optimized, -local protocol. -If the protocol is omitted and a host name is specified, then the -default protocol is \f[V]rmi\f[R]. -.TP -\f[I]hostname\f[R] -A host name or IP address that indicates the target host. -If you omit the \f[I]hostname\f[R] parameter, then the target host is -the local host. -.TP -\f[I]port\f[R] -The default port for communicating with the remote server. -If the \f[I]hostname\f[R] parameter is omitted or the \f[I]protocol\f[R] -parameter specifies an optimized, local protocol, then the -\f[I]port\f[R] parameter is ignored. -Otherwise, treatment of the \f[I]port\f[R] parameter is -implementation-specific. -For the default \f[V]rmi\f[R] protocol, the \f[I]port\f[R] parameter -indicates the port number for the \f[V]rmiregistry\f[R] on the remote -host. -If the \f[I]port\f[R] parameter is omitted, and the \f[I]protocol\f[R] -parameter indicates \f[V]rmi\f[R], then the default -\f[V]rmiregistry\f[R] port (\f[V]1099\f[R]) is used. -.TP -\f[I]servername\f[R] -The treatment of this parameter depends on the implementation. -For the optimized, local protocol, this field is ignored. -For the \f[V]rmi\f[R] protocol, this parameter is a string that -represents the name of the RMI remote object on the remote host. -See the \f[B]jstatd\f[R] command \f[V]-n\f[R] option. -.SH OUTPUT FORMAT OF THE JPS COMMAND -.PP -The output of the \f[V]jps\f[R] command has the following pattern: -.RS -.PP -\f[I]lvmid\f[R] [ [ \f[I]classname\f[R] | \f[I]JARfilename\f[R] | -\f[V]\[dq]Unknown\[dq]\f[R]] [ \f[I]arg\f[R]* ] [ \f[I]jvmarg\f[R]* ] ] -.RE -.PP -All output tokens are separated by white space. -An \f[V]arg\f[R] value that includes embedded white space introduces -ambiguity when attempting to map arguments to their actual positional -parameters. -.PP -\f[B]Note:\f[R] -.PP -It\[aq]s recommended that you don\[aq]t write scripts to parse -\f[V]jps\f[R] output because the format might change in future releases. -If you write scripts that parse \f[V]jps\f[R] output, then expect to -modify them for future releases of this tool. -.SH EXAMPLES -.PP -This section provides examples of the \f[V]jps\f[R] command. -.PP -List the instrumented JVMs on the local host: -.IP -.nf -\f[CB] -jps -18027 Java2Demo.JAR -18032 jps -18005 jstat -\f[R] -.fi -.PP -The following example lists the instrumented JVMs on a remote host. -This example assumes that the \f[V]jstat\f[R] server and either the its -internal RMI registry or a separate external \f[V]rmiregistry\f[R] -process are running on the remote host on the default port (port -\f[V]1099\f[R]). -It also assumes that the local host has appropriate permissions to -access the remote host. -This example includes the \f[V]-l\f[R] option to output the long form of -the class names or JAR file names. -.IP -.nf -\f[CB] -jps -l remote.domain -3002 /opt/jdk1.7.0/demo/jfc/Java2D/Java2Demo.JAR -2857 sun.tools.jstatd.jstatd -\f[R] -.fi -.PP -The following example lists the instrumented JVMs on a remote host with -a nondefault port for the RMI registry. -This example assumes that the \f[V]jstatd\f[R] server, with an internal -RMI registry bound to port \f[V]2002\f[R], is running on the remote -host. -This example also uses the \f[V]-m\f[R] option to include the arguments -passed to the \f[V]main\f[R] method of each of the listed Java -applications. -.IP -.nf -\f[CB] -jps -m remote.domain:2002 -3002 /opt/jdk1.7.0/demo/jfc/Java2D/Java2Demo.JAR -3102 sun.tools.jstatd.jstatd -p 2002 -\f[R] -.fi diff --git a/src/jdk.jcmd/share/man/jps.md b/src/jdk.jcmd/share/man/jps.md new file mode 100644 index 00000000000..be3994c411e --- /dev/null +++ b/src/jdk.jcmd/share/man/jps.md @@ -0,0 +1,189 @@ +--- +# Copyright (c) 2004, 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 +# 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. +# + +title: 'JPS(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jps - list the instrumented JVMs on the target system + +## Synopsis + +**Note:** This command is experimental and unsupported. + +`jps` \[`-q`\] \[`-mlvV`\] \[*hostid*\] + +`jps` \[`-help`\] + +## Options + +`-q` +: Suppresses the output of the class name, JAR file name, and arguments + passed to the `main` method, producing a list of only local JVM + identifiers. + +`-mlvV` +: You can specify any combination of these options. + + - `-m` displays the arguments passed to the `main` method. The output may + be `null` for embedded JVMs. + + - `-l` displays the full package name for the application's `main` class + or the full path name to the application's JAR file. + + - `-v` displays the arguments passed to the JVM. + + - `-V` suppresses the output of the class name, JAR file name, and + arguments passed to the `main` method, producing a list of only local + JVM identifiers. + +*hostid* +: The identifier of the host for which the process report should be + generated. The `hostid` can include optional components that indicate the + communications protocol, port number, and other implementation specific + data. See [Host Identifier]. + +`-help` +: Displays the help message for the `jps` command. + +## Description + +The `jps` command lists the instrumented Java HotSpot VMs on the target system. +The command is limited to reporting information on JVMs for which it has the +access permissions. + +If the `jps` command is run without specifying a `hostid`, then it searches for +instrumented JVMs on the local host. If started with a `hostid`, then it +searches for JVMs on the indicated host, using the specified protocol and port. +A `jstatd` process is assumed to be running on the target host. + +The `jps` command reports the local JVM identifier, or `lvmid`, for each +instrumented JVM found on the target system. The `lvmid` is typically, but not +necessarily, the operating system's process identifier for the JVM process. +With no options, the `jps` command lists each Java application's `lvmid` +followed by the short form of the application's class name or jar file name. +The short form of the class name or JAR file name omits the class's package +information or the JAR files path information. + +The `jps` command uses the Java launcher to find the class name and arguments +passed to the main method. If the target JVM is started with a custom launcher, +then the class or JAR file name, and the arguments to the `main` method aren't +available. In this case, the `jps` command outputs the string `Unknown` for the +class name, or JAR file name, and for the arguments to the `main` method. + +The list of JVMs produced by the `jps` command can be limited by the +permissions granted to the principal running the command. The command lists +only the JVMs for which the principal has access rights as determined by +operating system-specific access control mechanisms. + +## Host Identifier + +The host identifier, or `hostid`, is a string that indicates the target system. +The syntax of the `hostid` string corresponds to the syntax of a URI: + +> \[*protocol*`:`\]\[\[`//`\]*hostname*\]\[`:`*port*\]\[`/`*servername*\] + +*protocol* +: The communications protocol. If the *protocol* is omitted and a *hostname* + isn't specified, then the default protocol is a platform-specific, + optimized, local protocol. If the protocol is omitted and a host name is + specified, then the default protocol is `rmi`. + +*hostname* +: A host name or IP address that indicates the target host. If you omit the + *hostname* parameter, then the target host is the local host. + +*port* +: The default port for communicating with the remote server. If the + *hostname* parameter is omitted or the *protocol* parameter specifies an + optimized, local protocol, then the *port* parameter is ignored. Otherwise, + treatment of the *port* parameter is implementation-specific. For the + default `rmi` protocol, the *port* parameter indicates the port number for + the `rmiregistry` on the remote host. If the *port* parameter is omitted, + and the *protocol* parameter indicates `rmi`, then the default + `rmiregistry` port (`1099`) is used. + +*servername* +: The treatment of this parameter depends on the implementation. For the + optimized, local protocol, this field is ignored. For the `rmi` protocol, + this parameter is a string that represents the name of the RMI remote + object on the remote host. See the [jstatd](jstatd.html) command `-n` + option. + +## Output Format of the jps Command + +The output of the `jps` command has the following pattern: + +> *lvmid* \[ \[ *classname* \| *JARfilename* \| `"Unknown"`\] \[ *arg*\* \] + \[ *jvmarg*\* \] \] + +All output tokens are separated by white space. An `arg` value that includes +embedded white space introduces ambiguity when attempting to map arguments to +their actual positional parameters. + +**Note:** + +It's recommended that you don't write scripts to parse `jps` output because the +format might change in future releases. If you write scripts that parse `jps` +output, then expect to modify them for future releases of this tool. + +## Examples + +This section provides examples of the `jps` command. + +List the instrumented JVMs on the local host: + +``` +jps +18027 Java2Demo.JAR +18032 jps +18005 jstat +``` + +The following example lists the instrumented JVMs on a remote host. This +example assumes that the `jstat` server and either the its internal RMI +registry or a separate external `rmiregistry` process are running on the remote +host on the default port (port `1099`). It also assumes that the local host has +appropriate permissions to access the remote host. This example includes the +`-l` option to output the long form of the class names or JAR file names. + +``` +jps -l remote.domain +3002 /opt/jdk1.7.0/demo/jfc/Java2D/Java2Demo.JAR +2857 sun.tools.jstatd.jstatd +``` + +The following example lists the instrumented JVMs on a remote host with a +nondefault port for the RMI registry. This example assumes that the `jstatd` +server, with an internal RMI registry bound to port `2002`, is running on the +remote host. This example also uses the `-m` option to include the arguments +passed to the `main` method of each of the listed Java applications. + +``` +jps -m remote.domain:2002 +3002 /opt/jdk1.7.0/demo/jfc/Java2D/Java2Demo.JAR +3102 sun.tools.jstatd.jstatd -p 2002 +``` diff --git a/src/jdk.jcmd/share/man/jstack.1 b/src/jdk.jcmd/share/man/jstack.1 deleted file mode 100644 index 933db5fc80d..00000000000 --- a/src/jdk.jcmd/share/man/jstack.1 +++ /dev/null @@ -1,89 +0,0 @@ -.\" Copyright (c) 2004, 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 -.\" 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JSTACK" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jstack - print Java stack traces of Java threads for a specified Java -process -.SH SYNOPSIS -.PP -\f[B]Note:\f[R] This command is experimental and unsupported. -.PP -\f[V]jstack\f[R] [\f[I]options\f[R]] \f[I]pid\f[R] -.TP -\f[I]options\f[R] -This represents the \f[V]jstack\f[R] command-line options. -See \f[B]Options for the jstack Command\f[R]. -.TP -\f[I]pid\f[R] -The process ID for which the stack trace is printed. -The process must be a Java process. -To get a list of Java processes running on a machine, use either the -\f[V]ps\f[R] command or, if the JVM processes are not running in a -separate docker instance, the \f[B]jps\f[R] command. -.SH DESCRIPTION -.PP -The \f[V]jstack\f[R] command prints Java stack traces of Java threads -for a specified Java process. -For each Java frame, the full class name, method name, byte code index -(BCI), and line number, when available, are printed. -C++ mangled names aren\[aq]t demangled. -To demangle C++ names, the output of this command can be piped to -\f[V]c++filt\f[R]. -When the specified process is running on a 64-bit JVM, you might need to -specify the \f[V]-J-d64\f[R] option, for example: -\f[V]jstack -J-d64\f[R] \f[I]pid\f[R]. -.PP -\f[B]Note:\f[R] -.PP -This command is unsupported and might not be available in future -releases of the JDK. -In Windows Systems where the \f[V]dbgeng.dll\f[R] file isn\[aq]t -present, the Debugging Tools for Windows must be installed so that these -tools work. -The \f[V]PATH\f[R] environment variable needs to contain the location of -the \f[V]jvm.dll\f[R] that is used by the target process, or the -location from which the core dump file was produced. -.SH OPTIONS FOR THE JSTACK COMMAND -.TP -\f[V]-l\f[R] -The long listing option prints additional information about locks. -.TP -\f[V]-h\f[R] or \f[V]-help\f[R] -Prints a help message. diff --git a/src/jdk.jcmd/share/man/jstack.md b/src/jdk.jcmd/share/man/jstack.md new file mode 100644 index 00000000000..84df235a70e --- /dev/null +++ b/src/jdk.jcmd/share/man/jstack.md @@ -0,0 +1,73 @@ +--- +# Copyright (c) 2004, 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 +# 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. +# + +title: 'JSTACK(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jstack - print Java stack traces of Java threads for a specified Java process + +## Synopsis + +**Note:** This command is experimental and unsupported. + +`jstack` \[*options*\] *pid* + +*options* +: This represents the `jstack` command-line options. See [Options for the + jstack Command]. + +*pid* +: The process ID for which the stack trace is printed. The process must be a + Java process. To get a list of Java processes running on a machine, use + either the `ps` command or, if the JVM processes are not running in a + separate docker instance, the [jps](jps.html) command. + +## Description + +The `jstack` command prints Java stack traces of Java threads for a specified +Java process. For each Java frame, the full class name, method name, byte code +index (BCI), and line number, when available, are printed. C++ mangled names +aren't demangled. To demangle C++ names, the output of this command can be +piped to `c++filt`. When the specified process is running on a 64-bit JVM, you +might need to specify the `-J-d64` option, for example: `jstack -J-d64` *pid*. + +**Note:** + +This command is unsupported and might not be available in future releases of +the JDK. In Windows Systems where the `dbgeng.dll` file isn't present, the +Debugging Tools for Windows must be installed so that these tools work. The +`PATH` environment variable needs to contain the location of the `jvm.dll` that +is used by the target process, or the location from which the core dump file +was produced. + +## Options for the jstack Command + +`-l` +: The long listing option prints additional information about locks. + +`-h` or `-help` +: Prints a help message. diff --git a/src/jdk.jcmd/share/man/jstat.1 b/src/jdk.jcmd/share/man/jstat.1 deleted file mode 100644 index 22e111a812b..00000000000 --- a/src/jdk.jcmd/share/man/jstat.1 +++ /dev/null @@ -1,689 +0,0 @@ -.\" Copyright (c) 2004, 2023, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JSTAT" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jstat - monitor JVM statistics -.SH SYNOPSIS -.PP -\f[B]Note:\f[R] This command is experimental and unsupported. -.PP -\f[V]jstat\f[R] \f[I]generalOptions\f[R] -.PP -\f[V]jstat\f[R] \f[I]outputOptions\f[R] [\f[V]-t\f[R]] [\f[V]-h\f[R] -\f[I]lines\f[R]] \f[I]vmid\f[R] [\f[I]interval\f[R] [\f[I]count\f[R]]] -.TP -\f[I]generalOptions\f[R] -A single general command-line option. -See \f[B]General Options\f[R]. -.TP -\f[I]outputOptions\f[R] -An option reported by the \f[V]-options\f[R] option. -One or more output options that consist of a single -\f[V]statOption\f[R], plus any of the \f[V]-t\f[R], \f[V]-h\f[R], and -\f[V]-J\f[R] options. -See \f[B]Output Options for the jstat Command\f[R]. -.TP -\f[V]-t\f[R] -Displays a time-stamp column as the first column of output. -The time stamp is the time since the start time of the target JVM. -.TP -\f[V]-h\f[R] \f[I]n\f[R] -Displays a column header every \f[I]n\f[R] samples (output rows), where -\f[I]n\f[R] is a positive integer. -The default value is \f[V]0\f[R], which displays the column header of -the first row of data. -.TP -\f[I]vmid\f[R] -A virtual machine identifier, which is a string that indicates the -target JVM. -See \f[B]Virtual Machine Identifier\f[R]. -.TP -\f[I]interval\f[R] -The sampling interval in the specified units, seconds (s) or -milliseconds (ms). -Default units are milliseconds. -This must be a positive integer. -When specified, the \f[V]jstat\f[R] command produces its output at each -interval. -.TP -\f[I]count\f[R] -The number of samples to display. -The default value is infinity, which causes the \f[V]jstat\f[R] command -to display statistics until the target JVM terminates or the -\f[V]jstat\f[R] command is terminated. -This value must be a positive integer. -.SH DESCRIPTION -.PP -The \f[V]jstat\f[R] command displays performance statistics for an -instrumented Java HotSpot VM. -The target JVM is identified by its virtual machine identifier, or -\f[V]vmid\f[R] option. -.PP -The \f[V]jstat\f[R] command supports two types of options, general -options and output options. -General options cause the \f[V]jstat\f[R] command to display simple -usage and version information. -Output options determine the content and format of the statistical -output. -.PP -All options and their functionality are subject to change or removal in -future releases. -.SH GENERAL OPTIONS -.PP -If you specify one of the general options, then you can\[aq]t specify -any other option or parameter. -.TP -\f[V]-help\f[R] -Displays a help message. -.TP -\f[V]-options\f[R] -Displays a list of static options. -See \f[B]Output Options for the jstat Command\f[R]. -.SH OUTPUT OPTIONS FOR THE JSTAT COMMAND -.PP -If you don\[aq]t specify a general option, then you can specify output -options. -Output options determine the content and format of the \f[V]jstat\f[R] -command\[aq]s output, and consist of a single \f[V]statOption\f[R], plus -any of the other output options (\f[V]-h\f[R], \f[V]-t\f[R], and -\f[V]-J\f[R]). -The \f[V]statOption\f[R] must come first. -.PP -Output is formatted as a table, with columns that are separated by -spaces. -A header row with titles describes the columns. -Use the \f[V]-h\f[R] option to set the frequency at which the header is -displayed. -Column header names are consistent among the different options. -In general, if two options provide a column with the same name, then the -data source for the two columns is the same. -.PP -Use the \f[V]-t\f[R] option to display a time-stamp column, labeled -Timestamp as the first column of output. -The Timestamp column contains the elapsed time, in seconds, since the -target JVM started. -The resolution of the time stamp is dependent on various factors and is -subject to variation due to delayed thread scheduling on heavily loaded -systems. -.PP -Use the interval and count parameters to determine how frequently and -how many times, respectively, the \f[V]jstat\f[R] command displays its -output. -.PP -\f[B]Note:\f[R] -.PP -Don\[aq]t write scripts to parse the \f[V]jstat\f[R] command\[aq]s -output because the format might change in future releases. -If you write scripts that parse the \f[V]jstat\f[R] command output, then -expect to modify them for future releases of this tool. -.TP -\f[V]-statOption\f[R] -Determines the statistics information that the \f[V]jstat\f[R] command -displays. -The following lists the available options. -Use the \f[V]-options\f[R] general option to display the list of options -for a particular platform installation. -See \f[B]Stat Options and Output\f[R]. -.RS -.PP -\f[V]class\f[R]: Displays statistics about the behavior of the class -loader. -.PP -\f[V]compiler\f[R]: Displays statistics about the behavior of the Java -HotSpot VM Just-in-Time compiler. -.PP -\f[V]gc\f[R]: Displays statistics about the behavior of the garbage -collected heap. -.PP -\f[V]gccapacity\f[R]: Displays statistics about the capacities of the -generations and their corresponding spaces. -.PP -\f[V]gccause\f[R]: Displays a summary about garbage collection -statistics (same as \f[V]-gcutil\f[R]), with the cause of the last and -current (when applicable) garbage collection events. -.PP -\f[V]gcnew\f[R]: Displays statistics about the behavior of the new -generation. -.PP -\f[V]gcnewcapacity\f[R]: Displays statistics about the sizes of the new -generations and their corresponding spaces. -.PP -\f[V]gcold\f[R]: Displays statistics about the behavior of the old -generation and metaspace statistics. -.PP -\f[V]gcoldcapacity\f[R]: Displays statistics about the sizes of the old -generation. -.PP -\f[V]gcmetacapacity\f[R]: Displays statistics about the sizes of the -metaspace. -.PP -\f[V]gcutil\f[R]: Displays a summary about garbage collection -statistics. -.PP -\f[V]printcompilation\f[R]: Displays Java HotSpot VM compilation method -statistics. -.RE -.TP -\f[V]-J\f[R]\f[I]javaOption\f[R] -Passes \f[I]javaOption\f[R] to the Java application launcher. -For example, \f[V]-J-Xms48m\f[R] sets the startup memory to 48 MB. -For a complete list of options, see \f[B]java\f[R]. -.SH STAT OPTIONS AND OUTPUT -.PP -The following information summarizes the columns that the -\f[V]jstat\f[R] command outputs for each \f[I]statOption\f[R]. -.TP -\f[V]-class\f[R] \f[I]option\f[R] -Class loader statistics. -.RS -.PP -\f[V]Loaded\f[R]: Number of classes loaded. -.PP -\f[V]Bytes\f[R]: Number of KB loaded. -.PP -\f[V]Unloaded\f[R]: Number of classes unloaded. -.PP -\f[V]Bytes\f[R]: Number of KB unloaded. -.PP -\f[V]Time\f[R]: Time spent performing class loading and unloading -operations. -.RE -.TP -\f[V]-compiler\f[R] \f[I]option\f[R] -Java HotSpot VM Just-in-Time compiler statistics. -.RS -.PP -\f[V]Compiled\f[R]: Number of compilation tasks performed. -.PP -\f[V]Failed\f[R]: Number of compilations tasks failed. -.PP -\f[V]Invalid\f[R]: Number of compilation tasks that were invalidated. -.PP -\f[V]Time\f[R]: Time spent performing compilation tasks. -.PP -\f[V]FailedType\f[R]: Compile type of the last failed compilation. -.PP -\f[V]FailedMethod\f[R]: Class name and method of the last failed -compilation. -.RE -.TP -\f[V]-gc\f[R] \f[I]option\f[R] -Garbage collected heap statistics. -.RS -.PP -\f[V]S0C\f[R]: Current survivor space 0 capacity (KB). -.PP -\f[V]S1C\f[R]: Current survivor space 1 capacity (KB). -.PP -\f[V]S0U\f[R]: Survivor space 0 utilization (KB). -.PP -\f[V]S1U\f[R]: Survivor space 1 utilization (KB). -.PP -\f[V]EC\f[R]: Current eden space capacity (KB). -.PP -\f[V]EU\f[R]: Eden space utilization (KB). -.PP -\f[V]OC\f[R]: Current old space capacity (KB). -.PP -\f[V]OU\f[R]: Old space utilization (KB). -.PP -\f[V]MC\f[R]: Metaspace Committed Size (KB). -.PP -\f[V]MU\f[R]: Metaspace utilization (KB). -.PP -\f[V]CCSC\f[R]: Compressed class committed size (KB). -.PP -\f[V]CCSU\f[R]: Compressed class space used (KB). -.PP -\f[V]YGC\f[R]: Number of young generation garbage collection (GC) -events. -.PP -\f[V]YGCT\f[R]: Young generation garbage collection time. -.PP -\f[V]FGC\f[R]: Number of full GC events. -.PP -\f[V]FGCT\f[R]: Full garbage collection time. -.PP -\f[V]GCT\f[R]: Total garbage collection time. -.RE -.TP -\f[V]-gccapacity\f[R] \f[I]option\f[R] -Memory pool generation and space capacities. -.RS -.PP -\f[V]NGCMN\f[R]: Minimum new generation capacity (KB). -.PP -\f[V]NGCMX\f[R]: Maximum new generation capacity (KB). -.PP -\f[V]NGC\f[R]: Current new generation capacity (KB). -.PP -\f[V]S0C\f[R]: Current survivor space 0 capacity (KB). -.PP -\f[V]S1C\f[R]: Current survivor space 1 capacity (KB). -.PP -\f[V]EC\f[R]: Current eden space capacity (KB). -.PP -\f[V]OGCMN\f[R]: Minimum old generation capacity (KB). -.PP -\f[V]OGCMX\f[R]: Maximum old generation capacity (KB). -.PP -\f[V]OGC\f[R]: Current old generation capacity (KB). -.PP -\f[V]OC\f[R]: Current old space capacity (KB). -.PP -\f[V]MCMN\f[R]: Minimum metaspace capacity (KB). -.PP -\f[V]MCMX\f[R]: Maximum metaspace capacity (KB). -.PP -\f[V]MC\f[R]: Metaspace Committed Size (KB). -.PP -\f[V]CCSMN\f[R]: Compressed class space minimum capacity (KB). -.PP -\f[V]CCSMX\f[R]: Compressed class space maximum capacity (KB). -.PP -\f[V]CCSC\f[R]: Compressed class committed size (KB). -.PP -\f[V]YGC\f[R]: Number of young generation GC events. -.PP -\f[V]FGC\f[R]: Number of full GC events. -.RE -.TP -\f[V]-gccause\f[R] \f[I]option\f[R] -This option displays the same summary of garbage collection statistics -as the \f[V]-gcutil\f[R] option, but includes the causes of the last -garbage collection event and (when applicable), the current garbage -collection event. -In addition to the columns listed for \f[V]-gcutil\f[R], this option -adds the following columns: -.RS -.PP -\f[V]LGCC\f[R]: Cause of last garbage collection -.PP -\f[V]GCC\f[R]: Cause of current garbage collection -.RE -.TP -\f[V]-gcnew\f[R] \f[I]option\f[R] -New generation statistics. -.RS -.PP -\f[V]S0C\f[R]: Current survivor space 0 capacity (KB). -.PP -\f[V]S1C\f[R]: Current survivor space 1 capacity (KB). -.PP -\f[V]S0U\f[R]: Survivor space 0 utilization (KB). -.PP -\f[V]S1U\f[R]: Survivor space 1 utilization (KB). -.PP -\f[V]TT\f[R]: Tenuring threshold. -.PP -\f[V]MTT\f[R]: Maximum tenuring threshold. -.PP -\f[V]DSS\f[R]: Desired survivor size (KB). -.PP -\f[V]EC\f[R]: Current eden space capacity (KB). -.PP -\f[V]EU\f[R]: Eden space utilization (KB). -.PP -\f[V]YGC\f[R]: Number of young generation GC events. -.PP -\f[V]YGCT\f[R]: Young generation garbage collection time. -.RE -.TP -\f[V]-gcnewcapacity\f[R] \f[I]option\f[R] -New generation space size statistics. -.RS -.PP -\f[V]NGCMN\f[R]: Minimum new generation capacity (KB). -.PP -\f[V]NGCMX\f[R]: Maximum new generation capacity (KB). -.PP -\f[V]NGC\f[R]: Current new generation capacity (KB). -.PP -\f[V]S0CMX\f[R]: Maximum survivor space 0 capacity (KB). -.PP -\f[V]S0C\f[R]: Current survivor space 0 capacity (KB). -.PP -\f[V]S1CMX\f[R]: Maximum survivor space 1 capacity (KB). -.PP -\f[V]S1C\f[R]: Current survivor space 1 capacity (KB). -.PP -\f[V]ECMX\f[R]: Maximum eden space capacity (KB). -.PP -\f[V]EC\f[R]: Current eden space capacity (KB). -.PP -\f[V]YGC\f[R]: Number of young generation GC events. -.PP -\f[V]FGC\f[R]: Number of full GC events. -.RE -.TP -\f[V]-gcold\f[R] \f[I]option\f[R] -Old generation size statistics. -.RS -.PP -\f[V]MC\f[R]: Metaspace Committed Size (KB). -.PP -\f[V]MU\f[R]: Metaspace utilization (KB). -.PP -\f[V]CCSC\f[R]: Compressed class committed size (KB). -.PP -\f[V]CCSU\f[R]: Compressed class space used (KB). -.PP -\f[V]OC\f[R]: Current old space capacity (KB). -.PP -\f[V]OU\f[R]: Old space utilization (KB). -.PP -\f[V]YGC\f[R]: Number of young generation GC events. -.PP -\f[V]FGC\f[R]: Number of full GC events. -.PP -\f[V]FGCT\f[R]: Full garbage collection time. -.PP -\f[V]GCT\f[R]: Total garbage collection time. -.RE -.TP -\f[V]-gcoldcapacity\f[R] \f[I]option\f[R] -Old generation statistics. -.RS -.PP -\f[V]OGCMN\f[R]: Minimum old generation capacity (KB). -.PP -\f[V]OGCMX\f[R]: Maximum old generation capacity (KB). -.PP -\f[V]OGC\f[R]: Current old generation capacity (KB). -.PP -\f[V]OC\f[R]: Current old space capacity (KB). -.PP -\f[V]YGC\f[R]: Number of young generation GC events. -.PP -\f[V]FGC\f[R]: Number of full GC events. -.PP -\f[V]FGCT\f[R]: Full garbage collection time. -.PP -\f[V]GCT\f[R]: Total garbage collection time. -.RE -.TP -\f[V]-gcmetacapacity\f[R] \f[I]option\f[R] -Metaspace size statistics. -.RS -.PP -\f[V]MCMN\f[R]: Minimum metaspace capacity (KB). -.PP -\f[V]MCMX\f[R]: Maximum metaspace capacity (KB). -.PP -\f[V]MC\f[R]: Metaspace Committed Size (KB). -.PP -\f[V]CCSMN\f[R]: Compressed class space minimum capacity (KB). -.PP -\f[V]CCSMX\f[R]: Compressed class space maximum capacity (KB). -.PP -\f[V]YGC\f[R]: Number of young generation GC events. -.PP -\f[V]FGC\f[R]: Number of full GC events. -.PP -\f[V]FGCT\f[R]: Full garbage collection time. -.PP -\f[V]GCT\f[R]: Total garbage collection time. -.RE -.TP -\f[V]-gcutil\f[R] \f[I]option\f[R] -Summary of garbage collection statistics. -.RS -.PP -\f[V]S0\f[R]: Survivor space 0 utilization as a percentage of the -space\[aq]s current capacity. -.PP -\f[V]S1\f[R]: Survivor space 1 utilization as a percentage of the -space\[aq]s current capacity. -.PP -\f[V]E\f[R]: Eden space utilization as a percentage of the space\[aq]s -current capacity. -.PP -\f[V]O\f[R]: Old space utilization as a percentage of the space\[aq]s -current capacity. -.PP -\f[V]M\f[R]: Metaspace utilization as a percentage of the space\[aq]s -current capacity. -.PP -\f[V]CCS\f[R]: Compressed class space utilization as a percentage. -.PP -\f[V]YGC\f[R]: Number of young generation GC events. -.PP -\f[V]YGCT\f[R]: Young generation garbage collection time. -.PP -\f[V]FGC\f[R]: Number of full GC events. -.PP -\f[V]FGCT\f[R]: Full garbage collection time. -.PP -\f[V]GCT\f[R]: Total garbage collection time. -.RE -.TP -\f[V]-printcompilation\f[R] \f[I]option\f[R] -Java HotSpot VM compiler method statistics. -.RS -.PP -\f[V]Compiled\f[R]: Number of compilation tasks performed by the most -recently compiled method. -.PP -\f[V]Size\f[R]: Number of bytes of byte code of the most recently -compiled method. -.PP -\f[V]Type\f[R]: Compilation type of the most recently compiled method. -.PP -\f[V]Method\f[R]: Class name and method name identifying the most -recently compiled method. -Class name uses a slash (/) instead of a dot (.) -as a name space separator. -The method name is the method within the specified class. -The format for these two fields is consistent with the HotSpot -\f[V]-XX:+PrintCompilation\f[R] option. -.RE -.SH VIRTUAL MACHINE IDENTIFIER -.PP -The syntax of the \f[V]vmid\f[R] string corresponds to the syntax of a -URI: -.RS -.PP -[\f[I]protocol\f[R]\f[V]:\f[R]][\f[V]//\f[R]]\f[I]lvmid\f[R][\f[V]\[at]\f[R]\f[I]hostname\f[R][\f[V]:\f[R]\f[I]port\f[R]][\f[V]/\f[R]\f[I]servername\f[R]] -.RE -.PP -The syntax of the \f[V]vmid\f[R] string corresponds to the syntax of a -URI. -The \f[V]vmid\f[R] string can vary from a simple integer that represents -a local JVM to a more complex construction that specifies a -communications protocol, port number, and other implementation-specific -values. -.TP -\f[I]protocol\f[R] -The communications protocol. -If the \f[I]protocol\f[R] value is omitted and a host name isn\[aq]t -specified, then the default protocol is a platform-specific optimized -local protocol. -If the \f[I]protocol\f[R] value is omitted and a host name is specified, -then the default protocol is \f[V]rmi\f[R]. -.TP -\f[I]lvmid\f[R] -The local virtual machine identifier for the target JVM. -The \f[I]lvmid\f[R] is a platform-specific value that uniquely -identifies a JVM on a system. -The \f[I]lvmid\f[R] is the only required component of a virtual machine -identifier. -The \f[I]lvmid\f[R] is typically, but not necessarily, the operating -system\[aq]s process identifier for the target JVM process. -You can use the \f[V]jps\f[R] command to determine the \f[I]lvmid\f[R] -provided the JVM processes is not running in a separate docker instance. -You can also determine the \f[I]lvmid\f[R] on Linux and macOS platforms -with the \f[V]ps\f[R] command, and on Windows with the Windows Task -Manager. -.TP -\f[I]hostname\f[R] -A host name or IP address that indicates the target host. -If the \f[I]hostname\f[R] value is omitted, then the target host is the -local host. -.TP -\f[I]port\f[R] -The default port for communicating with the remote server. -If the \f[I]hostname\f[R] value is omitted or the \f[I]protocol\f[R] -value specifies an optimized, local protocol, then the \f[I]port\f[R] -value is ignored. -Otherwise, treatment of the \f[I]port\f[R] parameter is -implementation-specific. -For the default \f[V]rmi\f[R] protocol, the port value indicates the -port number for the \f[V]rmiregistry\f[R] on the remote host. -If the \f[I]port\f[R] value is omitted and the \f[I]protocol\f[R] value -indicates \f[V]rmi\f[R], then the default rmiregistry port (1099) is -used. -.TP -\f[I]servername\f[R] -The treatment of the \f[I]servername\f[R] parameter depends on -implementation. -For the optimized local protocol, this field is ignored. -For the \f[V]rmi\f[R] protocol, it represents the name of the RMI remote -object on the remote host. -.SH EXAMPLES -.PP -This section presents some examples of monitoring a local JVM with an -\f[I]lvmid\f[R] of 21891. -.SH THE GCUTIL OPTION -.PP -This example attaches to lvmid 21891 and takes 7 samples at 250 -millisecond intervals and displays the output as specified by the -\f[V]-gcutil\f[R] option. -.PP -The output of this example shows that a young generation collection -occurred between the third and fourth sample. -The collection took 0.078 seconds and promoted objects from the eden -space (E) to the old space (O), resulting in an increase of old space -utilization from 66.80% to 68.19%. -Before the collection, the survivor space was 97.02% utilized, but after -this collection it\[aq]s 91.03% utilized. -.IP -.nf -\f[CB] -jstat -gcutil 21891 250 7 - S0 S1 E O M CCS YGC YGCT FGC FGCT GCT - 0.00 97.02 70.31 66.80 95.52 89.14 7 0.300 0 0.000 0.300 - 0.00 97.02 86.23 66.80 95.52 89.14 7 0.300 0 0.000 0.300 - 0.00 97.02 96.53 66.80 95.52 89.14 7 0.300 0 0.000 0.300 - 91.03 0.00 1.98 68.19 95.89 91.24 8 0.378 0 0.000 0.378 - 91.03 0.00 15.82 68.19 95.89 91.24 8 0.378 0 0.000 0.378 - 91.03 0.00 17.80 68.19 95.89 91.24 8 0.378 0 0.000 0.378 - 91.03 0.00 17.80 68.19 95.89 91.24 8 0.378 0 0.000 0.378 -\f[R] -.fi -.SH REPEAT THE COLUMN HEADER STRING -.PP -This example attaches to lvmid 21891 and takes samples at 250 -millisecond intervals and displays the output as specified by -\f[V]-gcnew\f[R] option. -In addition, it uses the \f[V]-h3\f[R] option to output the column -header after every 3 lines of data. -.PP -In addition to showing the repeating header string, this example shows -that between the second and third samples, a young GC occurred. -Its duration was 0.001 seconds. -The collection found enough active data that the survivor space 0 -utilization (S0U) would have exceeded the desired survivor size (DSS). -As a result, objects were promoted to the old generation (not visible in -this output), and the tenuring threshold (TT) was lowered from 31 to 2. -.PP -Another collection occurs between the fifth and sixth samples. -This collection found very few survivors and returned the tenuring -threshold to 31. -.IP -.nf -\f[CB] -jstat -gcnew -h3 21891 250 - S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT - 64.0 64.0 0.0 31.7 31 31 32.0 512.0 178.6 249 0.203 - 64.0 64.0 0.0 31.7 31 31 32.0 512.0 355.5 249 0.203 - 64.0 64.0 35.4 0.0 2 31 32.0 512.0 21.9 250 0.204 - S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT - 64.0 64.0 35.4 0.0 2 31 32.0 512.0 245.9 250 0.204 - 64.0 64.0 35.4 0.0 2 31 32.0 512.0 421.1 250 0.204 - 64.0 64.0 0.0 19.0 31 31 32.0 512.0 84.4 251 0.204 - S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT - 64.0 64.0 0.0 19.0 31 31 32.0 512.0 306.7 251 0.204 -\f[R] -.fi -.SH INCLUDE A TIME STAMP FOR EACH SAMPLE -.PP -This example attaches to lvmid 21891 and takes 3 samples at 250 -millisecond intervals. -The \f[V]-t\f[R] option is used to generate a time stamp for each sample -in the first column. -.PP -The Timestamp column reports the elapsed time in seconds since the start -of the target JVM. -In addition, the \f[V]-gcoldcapacity\f[R] output shows the old -generation capacity (OGC) and the old space capacity (OC) increasing as -the heap expands to meet allocation or promotion demands. -The old generation capacity (OGC) has grown from 11,696 KB to 13,820 KB -after the eighty-first full garbage collection (FGC). -The maximum capacity of the generation (and space) is 60,544 KB (OGCMX), -so it still has room to expand. -.IP -.nf -\f[CB] -Timestamp OGCMN OGCMX OGC OC YGC FGC FGCT GCT - 150.1 1408.0 60544.0 11696.0 11696.0 194 80 2.874 3.799 - 150.4 1408.0 60544.0 13820.0 13820.0 194 81 2.938 3.863 - 150.7 1408.0 60544.0 13820.0 13820.0 194 81 2.938 3.863 -\f[R] -.fi -.SH MONITOR INSTRUMENTATION FOR A REMOTE JVM -.PP -This example attaches to lvmid 40496 on the system named -\f[V]remote.domain\f[R] using the \f[V]-gcutil\f[R] option, with samples -taken every second indefinitely. -.PP -The lvmid is combined with the name of the remote host to construct a -vmid of \f[V]40496\[at]remote.domain\f[R]. -This vmid results in the use of the \f[V]rmi\f[R] protocol to -communicate to the default \f[V]jstatd\f[R] server on the remote host. -The \f[V]jstatd\f[R] server is located using the \f[V]rmiregistry\f[R] -command on \f[V]remote.domain\f[R] that\[aq]s bound to the default port -of the \f[V]rmiregistry\f[R] command (port 1099). -.IP -.nf -\f[CB] -jstat -gcutil 40496\[at]remote.domain 1000 -\&... output omitted -\f[R] -.fi diff --git a/src/jdk.jcmd/share/man/jstat.md b/src/jdk.jcmd/share/man/jstat.md new file mode 100644 index 00000000000..795fc9caa40 --- /dev/null +++ b/src/jdk.jcmd/share/man/jstat.md @@ -0,0 +1,588 @@ +--- +# Copyright (c) 2004, 2023, 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. +# + +title: 'JSTAT(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jstat - monitor JVM statistics + +## Synopsis + +**Note:** This command is experimental and unsupported. + +`jstat` *generalOptions* + +`jstat` *outputOptions* \[`-t`\] \[`-h` *lines*\] *vmid* \[*interval* +\[*count*\]\] + +*generalOptions* +: A single general command-line option. See [General Options]. + +*outputOptions* +: An option reported by the `-options` option. One or more output options + that consist of a single `statOption`, plus any of the `-t`, `-h`, and `-J` + options. See [Output Options for the jstat Command]. + +`-t` +: Displays a time-stamp column as the first column of output. The time stamp + is the time since the start time of the target JVM. + +`-h` *n* +: Displays a column header every *n* samples (output rows), where *n* is a + positive integer. The default value is `0`, which displays the column + header of the first row of data. + +*vmid* +: A virtual machine identifier, which is a string that indicates the target + JVM. See [Virtual Machine Identifier]. + +*interval* +: The sampling interval in the specified units, seconds (s) or milliseconds + (ms). Default units are milliseconds. This must be a positive integer. When + specified, the `jstat` command produces its output at each interval. + +*count* +: The number of samples to display. The default value is infinity, which + causes the `jstat` command to display statistics until the target JVM + terminates or the `jstat` command is terminated. This value must be a + positive integer. + +## Description + +The `jstat` command displays performance statistics for an instrumented Java +HotSpot VM. The target JVM is identified by its virtual machine identifier, or +`vmid` option. + +The `jstat` command supports two types of options, general options and output +options. General options cause the `jstat` command to display simple usage and +version information. Output options determine the content and format of the +statistical output. + +All options and their functionality are subject to change or removal in future +releases. + +## General Options + +If you specify one of the general options, then you can't specify any other +option or parameter. + +`-help` +: Displays a help message. + +`-options` +: Displays a list of static options. See [Output Options for the jstat + Command]. + +## Output Options for the jstat Command + +If you don't specify a general option, then you can specify output options. +Output options determine the content and format of the `jstat` command's +output, and consist of a single `statOption`, plus any of the other output +options (`-h`, `-t`, and `-J`). The `statOption` must come first. + +Output is formatted as a table, with columns that are separated by spaces. A +header row with titles describes the columns. Use the `-h` option to set the +frequency at which the header is displayed. Column header names are consistent +among the different options. In general, if two options provide a column with +the same name, then the data source for the two columns is the same. + +Use the `-t` option to display a time-stamp column, labeled Timestamp as the +first column of output. The Timestamp column contains the elapsed time, in +seconds, since the target JVM started. The resolution of the time stamp is +dependent on various factors and is subject to variation due to delayed thread +scheduling on heavily loaded systems. + +Use the interval and count parameters to determine how frequently and how many +times, respectively, the `jstat` command displays its output. + +**Note:** + +Don't write scripts to parse the `jstat` command's output because the format +might change in future releases. If you write scripts that parse the `jstat` +command output, then expect to modify them for future releases of this tool. + +`-statOption` +: Determines the statistics information that the `jstat` command displays. + The following lists the available options. Use the `-options` general + option to display the list of options for a particular platform + installation. See [Stat Options and Output]. + + `class`: Displays statistics about the behavior of the class loader. + + `compiler`: Displays statistics about the behavior of the Java HotSpot VM + Just-in-Time compiler. + + `gc`: Displays statistics about the behavior of the garbage collected heap. + + `gccapacity`: Displays statistics about the capacities of the generations + and their corresponding spaces. + + `gccause`: Displays a summary about garbage collection statistics (same as + `-gcutil`), with the cause of the last and current (when applicable) + garbage collection events. + + `gcnew`: Displays statistics about the behavior of the new generation. + + `gcnewcapacity`: Displays statistics about the sizes of the new generations + and their corresponding spaces. + + `gcold`: Displays statistics about the behavior of the old generation and + metaspace statistics. + + `gcoldcapacity`: Displays statistics about the sizes of the old generation. + + `gcmetacapacity`: Displays statistics about the sizes of the metaspace. + + `gcutil`: Displays a summary about garbage collection statistics. + + `printcompilation`: Displays Java HotSpot VM compilation method statistics. + +`-J`*javaOption* +: Passes *javaOption* to the Java application launcher. For example, + `-J-Xms48m` sets the startup memory to 48 MB. For a complete list of + options, see [java](java.html). + +## Stat Options and Output + +The following information summarizes the columns that the `jstat` command +outputs for each *statOption*. + +`-class` *option* +: Class loader statistics. + + `Loaded`: Number of classes loaded. + + `Bytes`: Number of KB loaded. + + `Unloaded`: Number of classes unloaded. + + `Bytes`: Number of KB unloaded. + + `Time`: Time spent performing class loading and unloading operations. + +`-compiler` *option* +: Java HotSpot VM Just-in-Time compiler statistics. + + `Compiled`: Number of compilation tasks performed. + + `Failed`: Number of compilations tasks failed. + + `Invalid`: Number of compilation tasks that were invalidated. + + `Time`: Time spent performing compilation tasks. + + `FailedType`: Compile type of the last failed compilation. + + `FailedMethod`: Class name and method of the last failed compilation. + +`-gc` *option* +: Garbage collected heap statistics. + + `S0C`: Current survivor space 0 capacity (KB). + + `S1C`: Current survivor space 1 capacity (KB). + + `S0U`: Survivor space 0 utilization (KB). + + `S1U`: Survivor space 1 utilization (KB). + + `EC`: Current eden space capacity (KB). + + `EU`: Eden space utilization (KB). + + `OC`: Current old space capacity (KB). + + `OU`: Old space utilization (KB). + + `MC`: Metaspace Committed Size (KB). + + `MU`: Metaspace utilization (KB). + + `CCSC`: Compressed class committed size (KB). + + `CCSU`: Compressed class space used (KB). + + `YGC`: Number of young generation garbage collection (GC) events. + + `YGCT`: Young generation garbage collection time. + + `FGC`: Number of full GC events. + + `FGCT`: Full garbage collection time. + + `GCT`: Total garbage collection time. + +`-gccapacity` *option* +: Memory pool generation and space capacities. + + `NGCMN`: Minimum new generation capacity (KB). + + `NGCMX`: Maximum new generation capacity (KB). + + `NGC`: Current new generation capacity (KB). + + `S0C`: Current survivor space 0 capacity (KB). + + `S1C`: Current survivor space 1 capacity (KB). + + `EC`: Current eden space capacity (KB). + + `OGCMN`: Minimum old generation capacity (KB). + + `OGCMX`: Maximum old generation capacity (KB). + + `OGC`: Current old generation capacity (KB). + + `OC`: Current old space capacity (KB). + + `MCMN`: Minimum metaspace capacity (KB). + + `MCMX`: Maximum metaspace capacity (KB). + + `MC`: Metaspace Committed Size (KB). + + `CCSMN`: Compressed class space minimum capacity (KB). + + `CCSMX`: Compressed class space maximum capacity (KB). + + `CCSC`: Compressed class committed size (KB). + + `YGC`: Number of young generation GC events. + + `FGC`: Number of full GC events. + +`-gccause` *option* +: This option displays the same summary of garbage collection statistics as + the `-gcutil` option, but includes the causes of the last garbage + collection event and (when applicable), the current garbage collection + event. In addition to the columns listed for `-gcutil`, this option adds + the following columns: + + `LGCC`: Cause of last garbage collection + + `GCC`: Cause of current garbage collection + +`-gcnew` *option* +: New generation statistics. + + `S0C`: Current survivor space 0 capacity (KB). + + `S1C`: Current survivor space 1 capacity (KB). + + `S0U`: Survivor space 0 utilization (KB). + + `S1U`: Survivor space 1 utilization (KB). + + `TT`: Tenuring threshold. + + `MTT`: Maximum tenuring threshold. + + `DSS`: Desired survivor size (KB). + + `EC`: Current eden space capacity (KB). + + `EU`: Eden space utilization (KB). + + `YGC`: Number of young generation GC events. + + `YGCT`: Young generation garbage collection time. + +`-gcnewcapacity` *option* +: New generation space size statistics. + + `NGCMN`: Minimum new generation capacity (KB). + + `NGCMX`: Maximum new generation capacity (KB). + + `NGC`: Current new generation capacity (KB). + + `S0CMX`: Maximum survivor space 0 capacity (KB). + + `S0C`: Current survivor space 0 capacity (KB). + + `S1CMX`: Maximum survivor space 1 capacity (KB). + + `S1C`: Current survivor space 1 capacity (KB). + + `ECMX`: Maximum eden space capacity (KB). + + `EC`: Current eden space capacity (KB). + + `YGC`: Number of young generation GC events. + + `FGC`: Number of full GC events. + +`-gcold` *option* +: Old generation size statistics. + + `MC`: Metaspace Committed Size (KB). + + `MU`: Metaspace utilization (KB). + + `CCSC`: Compressed class committed size (KB). + + `CCSU`: Compressed class space used (KB). + + `OC`: Current old space capacity (KB). + + `OU`: Old space utilization (KB). + + `YGC`: Number of young generation GC events. + + `FGC`: Number of full GC events. + + `FGCT`: Full garbage collection time. + + `GCT`: Total garbage collection time. + +`-gcoldcapacity` *option* +: Old generation statistics. + + `OGCMN`: Minimum old generation capacity (KB). + + `OGCMX`: Maximum old generation capacity (KB). + + `OGC`: Current old generation capacity (KB). + + `OC`: Current old space capacity (KB). + + `YGC`: Number of young generation GC events. + + `FGC`: Number of full GC events. + + `FGCT`: Full garbage collection time. + + `GCT`: Total garbage collection time. + +`-gcmetacapacity` *option* +: Metaspace size statistics. + + `MCMN`: Minimum metaspace capacity (KB). + + `MCMX`: Maximum metaspace capacity (KB). + + `MC`: Metaspace Committed Size (KB). + + `CCSMN`: Compressed class space minimum capacity (KB). + + `CCSMX`: Compressed class space maximum capacity (KB). + + `YGC`: Number of young generation GC events. + + `FGC`: Number of full GC events. + + `FGCT`: Full garbage collection time. + + `GCT`: Total garbage collection time. + +`-gcutil` *option* +: Summary of garbage collection statistics. + + `S0`: Survivor space 0 utilization as a percentage of the space's current + capacity. + + `S1`: Survivor space 1 utilization as a percentage of the space's current + capacity. + + `E`: Eden space utilization as a percentage of the space's current + capacity. + + `O`: Old space utilization as a percentage of the space's current capacity. + + `M`: Metaspace utilization as a percentage of the space's current capacity. + + `CCS`: Compressed class space utilization as a percentage. + + `YGC`: Number of young generation GC events. + + `YGCT`: Young generation garbage collection time. + + `FGC`: Number of full GC events. + + `FGCT`: Full garbage collection time. + + `GCT`: Total garbage collection time. + +`-printcompilation` *option* +: Java HotSpot VM compiler method statistics. + + `Compiled`: Number of compilation tasks performed by the most recently + compiled method. + + `Size`: Number of bytes of byte code of the most recently compiled method. + + `Type`: Compilation type of the most recently compiled method. + + `Method`: Class name and method name identifying the most recently compiled + method. Class name uses a slash (/) instead of a dot (.) as a name space + separator. The method name is the method within the specified class. The + format for these two fields is consistent with the HotSpot + `-XX:+PrintCompilation` option. + +## Virtual Machine Identifier + +The syntax of the `vmid` string corresponds to the syntax of a URI: + +> \[*protocol*`:`\]\[`//`\]*lvmid*\[`@`*hostname*\[`:`*port*\]\[`/`*servername*\] + +The syntax of the `vmid` string corresponds to the syntax of a URI. The `vmid` +string can vary from a simple integer that represents a local JVM to a more +complex construction that specifies a communications protocol, port number, and +other implementation-specific values. + +*protocol* +: The communications protocol. If the *protocol* value is omitted and a host + name isn't specified, then the default protocol is a platform-specific + optimized local protocol. If the *protocol* value is omitted and a host + name is specified, then the default protocol is `rmi`. + +*lvmid* +: The local virtual machine identifier for the target JVM. The *lvmid* is a + platform-specific value that uniquely identifies a JVM on a system. The + *lvmid* is the only required component of a virtual machine identifier. The + *lvmid* is typically, but not necessarily, the operating system's process + identifier for the target JVM process. You can use the `jps` command to + determine the *lvmid* provided the JVM processes is not running in a + separate docker instance. You can also determine the *lvmid* on Linux and + macOS platforms with the `ps` command, and on Windows with the Windows Task + Manager. + +*hostname* +: A host name or IP address that indicates the target host. If the *hostname* + value is omitted, then the target host is the local host. + +*port* +: The default port for communicating with the remote server. If the + *hostname* value is omitted or the *protocol* value specifies an optimized, + local protocol, then the *port* value is ignored. Otherwise, treatment of + the *port* parameter is implementation-specific. For the default `rmi` + protocol, the port value indicates the port number for the `rmiregistry` on + the remote host. If the *port* value is omitted and the *protocol* value + indicates `rmi`, then the default rmiregistry port (1099) is used. + +*servername* +: The treatment of the *servername* parameter depends on implementation. For + the optimized local protocol, this field is ignored. For the `rmi` + protocol, it represents the name of the RMI remote object on the remote + host. + +## Examples + +This section presents some examples of monitoring a local JVM with an *lvmid* +of 21891. + +## The gcutil Option + +This example attaches to lvmid 21891 and takes 7 samples at 250 millisecond +intervals and displays the output as specified by the `-gcutil` option. + +The output of this example shows that a young generation collection occurred +between the third and fourth sample. The collection took 0.078 seconds and +promoted objects from the eden space (E) to the old space (O), resulting in an +increase of old space utilization from 66.80% to 68.19%. Before the collection, +the survivor space was 97.02% utilized, but after this collection it's 91.03% +utilized. + +``` +jstat -gcutil 21891 250 7 + S0 S1 E O M CCS YGC YGCT FGC FGCT GCT + 0.00 97.02 70.31 66.80 95.52 89.14 7 0.300 0 0.000 0.300 + 0.00 97.02 86.23 66.80 95.52 89.14 7 0.300 0 0.000 0.300 + 0.00 97.02 96.53 66.80 95.52 89.14 7 0.300 0 0.000 0.300 + 91.03 0.00 1.98 68.19 95.89 91.24 8 0.378 0 0.000 0.378 + 91.03 0.00 15.82 68.19 95.89 91.24 8 0.378 0 0.000 0.378 + 91.03 0.00 17.80 68.19 95.89 91.24 8 0.378 0 0.000 0.378 + 91.03 0.00 17.80 68.19 95.89 91.24 8 0.378 0 0.000 0.378 +``` + +## Repeat the Column Header String + +This example attaches to lvmid 21891 and takes samples at 250 millisecond +intervals and displays the output as specified by `-gcnew` option. In addition, +it uses the `-h3` option to output the column header after every 3 lines of +data. + +In addition to showing the repeating header string, this example shows that +between the second and third samples, a young GC occurred. Its duration was +0.001 seconds. The collection found enough active data that the survivor space +0 utilization (S0U) would have exceeded the desired survivor size (DSS). As a +result, objects were promoted to the old generation (not visible in this +output), and the tenuring threshold (TT) was lowered from 31 to 2. + +Another collection occurs between the fifth and sixth samples. This collection +found very few survivors and returned the tenuring threshold to 31. + +``` +jstat -gcnew -h3 21891 250 + S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT + 64.0 64.0 0.0 31.7 31 31 32.0 512.0 178.6 249 0.203 + 64.0 64.0 0.0 31.7 31 31 32.0 512.0 355.5 249 0.203 + 64.0 64.0 35.4 0.0 2 31 32.0 512.0 21.9 250 0.204 + S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT + 64.0 64.0 35.4 0.0 2 31 32.0 512.0 245.9 250 0.204 + 64.0 64.0 35.4 0.0 2 31 32.0 512.0 421.1 250 0.204 + 64.0 64.0 0.0 19.0 31 31 32.0 512.0 84.4 251 0.204 + S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT + 64.0 64.0 0.0 19.0 31 31 32.0 512.0 306.7 251 0.204 +``` + +## Include a Time Stamp for Each Sample + +This example attaches to lvmid 21891 and takes 3 samples at 250 millisecond +intervals. The `-t` option is used to generate a time stamp for each sample in +the first column. + +The Timestamp column reports the elapsed time in seconds since the start of the +target JVM. In addition, the `-gcoldcapacity` output shows the old generation +capacity (OGC) and the old space capacity (OC) increasing as the heap expands +to meet allocation or promotion demands. The old generation capacity (OGC) has +grown from 11,696 KB to 13,820 KB after the eighty-first full garbage +collection (FGC). The maximum capacity of the generation (and space) is 60,544 +KB (OGCMX), so it still has room to expand. + +``` +Timestamp OGCMN OGCMX OGC OC YGC FGC FGCT GCT + 150.1 1408.0 60544.0 11696.0 11696.0 194 80 2.874 3.799 + 150.4 1408.0 60544.0 13820.0 13820.0 194 81 2.938 3.863 + 150.7 1408.0 60544.0 13820.0 13820.0 194 81 2.938 3.863 +``` + +## Monitor Instrumentation for a Remote JVM + +This example attaches to lvmid 40496 on the system named `remote.domain` using +the `-gcutil` option, with samples taken every second indefinitely. + +The lvmid is combined with the name of the remote host to construct a vmid of +`40496@remote.domain`. This vmid results in the use of the `rmi` protocol to +communicate to the default `jstatd` server on the remote host. The `jstatd` +server is located using the `rmiregistry` command on `remote.domain` that's +bound to the default port of the `rmiregistry` command (port 1099). + +``` +jstat -gcutil 40496@remote.domain 1000 +... output omitted +``` diff --git a/src/jdk.jconsole/share/man/jconsole.1 b/src/jdk.jconsole/share/man/jconsole.1 deleted file mode 100644 index ec70040acf4..00000000000 --- a/src/jdk.jconsole/share/man/jconsole.1 +++ /dev/null @@ -1,104 +0,0 @@ -.\" Copyright (c) 2004, 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 -.\" 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JCONSOLE" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jconsole - start a graphical console to monitor and manage Java -applications -.SH SYNOPSIS -.PP -\f[V]jconsole\f[R] [\f[V]-interval=\f[R]\f[I]n\f[R]] [\f[V]-notile\f[R]] -[\f[V]-plugin\f[R] \f[I]path\f[R]] [\f[V]-version\f[R]] -[\f[I]connection\f[R] ... -] [\f[V]-J\f[R]\f[I]input_arguments\f[R]] -.PP -\f[V]jconsole\f[R] \f[V]-help\f[R] -.SH OPTIONS -.TP -\f[V]-interval\f[R] -Sets the update interval to \f[V]n\f[R] seconds (default is 4 seconds). -.TP -\f[V]-notile\f[R] -Doesn\[aq]t tile the windows for two or more connections. -.TP -\f[V]-pluginpath\f[R] \f[I]path\f[R] -Specifies the path that \f[V]jconsole\f[R] uses to look up plug-ins. -The plug-in \f[I]path\f[R] should contain a provider-configuration file -named \f[V]META-INF/services/com.sun.tools.jconsole.JConsolePlugin\f[R] -that contains one line for each plug-in. -The line specifies the fully qualified class name of the class -implementing the \f[V]com.sun.tools.jconsole.JConsolePlugin\f[R] class. -.TP -\f[V]-version\f[R] -Prints the program version. -.TP -\f[I]connection\f[R] = \f[I]pid\f[R] | \f[I]host\f[R]\f[V]:\f[R]\f[I]port\f[R] | \f[I]jmxURL\f[R] -A connection is described by either \f[I]pid\f[R], -\f[I]host\f[R]\f[V]:\f[R]\f[I]port\f[R] or \f[I]jmxURL\f[R]. -.RS -.IP \[bu] 2 -The \f[I]pid\f[R] value is the process ID of a target process. -The JVM must be running with the same user ID as the user ID running the -\f[V]jconsole\f[R] command. -.IP \[bu] 2 -The \f[I]host\f[R]\f[V]:\f[R]\f[I]port\f[R] values are the name of the -host system on which the JVM is running, and the port number specified -by the system property \f[V]com.sun.management.jmxremote.port\f[R] when -the JVM was started. -.IP \[bu] 2 -The \f[I]jmxUrl\f[R] value is the address of the JMX agent to be -connected to as described in JMXServiceURL. -.RE -.TP -\f[V]-J\f[R]\f[I]input_arguments\f[R] -Passes \f[I]input_arguments\f[R] to the JVM on which the -\f[V]jconsole\f[R] command is run. -.TP -\f[V]-help\f[R] or \f[V]--help\f[R] -Displays the help message for the command. -.SH DESCRIPTION -.PP -The \f[V]jconsole\f[R] command starts a graphical console tool that lets -you monitor and manage Java applications and virtual machines on a local -or remote machine. -.PP -On Windows, the \f[V]jconsole\f[R] command doesn\[aq]t associate with a -console window. -It does, however, display a dialog box with error information when the -\f[V]jconsole\f[R] command fails. diff --git a/src/jdk.jconsole/share/man/jconsole.md b/src/jdk.jconsole/share/man/jconsole.md new file mode 100644 index 00000000000..59c84a0431a --- /dev/null +++ b/src/jdk.jconsole/share/man/jconsole.md @@ -0,0 +1,86 @@ +--- +# Copyright (c) 2004, 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 +# 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. +# + +title: 'JCONSOLE(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jconsole - start a graphical console to monitor and manage Java applications + +## Synopsis + +`jconsole` \[`-interval=`*n*\] \[`-notile`\] \[`-plugin` *path*\] +\[`-version`\] \[*connection* ... \] \[`-J`*input\_arguments*\] + +`jconsole` `-help` + +## Options + +`-interval` +: Sets the update interval to `n` seconds (default is 4 seconds). + +`-notile` +: Doesn't tile the windows for two or more connections. + +`-pluginpath` *path* +: Specifies the path that `jconsole` uses to look up plug-ins. The plug-in + *path* should contain a provider-configuration file named + `META-INF/services/com.sun.tools.jconsole.JConsolePlugin` that contains one + line for each plug-in. The line specifies the fully qualified class name of + the class implementing the `com.sun.tools.jconsole.JConsolePlugin` class. + +`-version` +: Prints the program version. + +*connection* = *pid* \| *host*`:`*port* \| *jmxURL* +: A connection is described by either *pid*, *host*`:`*port* or *jmxURL*. + + - The *pid* value is the process ID of a target process. The JVM must be + running with the same user ID as the user ID running the `jconsole` + command. + + - The *host*`:`*port* values are the name of the host system on which the + JVM is running, and the port number specified by the system property + `com.sun.management.jmxremote.port` when the JVM was started. + + - The *jmxUrl* value is the address of the JMX agent to be connected to + as described in JMXServiceURL. + +`-J`*input\_arguments* +: Passes *input\_arguments* to the JVM on which the `jconsole` command is + run. + +`-help` or `--help` +: Displays the help message for the command. + +## Description + +The `jconsole` command starts a graphical console tool that lets you monitor +and manage Java applications and virtual machines on a local or remote machine. + +On Windows, the `jconsole` command doesn't associate with a console window. It +does, however, display a dialog box with error information when the `jconsole` +command fails. diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java index cccbaf14f53..2335d882ab1 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java @@ -84,7 +84,7 @@ public void write(Attribute<?> a, CodeAttribute lr) { int i = 0; int j = 0; print(" "); - print(attr.attributeName()); + print(attr.attributeName().stringValue()); print(": "); print("length = 0x" + toHex(data.length)); print(" (unknown attribute)"); diff --git a/src/jdk.jdeps/share/man/javap.1 b/src/jdk.jdeps/share/man/javap.1 deleted file mode 100644 index 27b0a29d0ba..00000000000 --- a/src/jdk.jdeps/share/man/javap.1 +++ /dev/null @@ -1,259 +0,0 @@ -.\" Copyright (c) 1994, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JAVAP" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -javap - disassemble one or more class files -.SH SYNOPSIS -.PP -\f[V]javap\f[R] [\f[I]options\f[R]] \f[I]classes\f[R]... -.TP -\f[I]options\f[R] -Specifies the command-line options. -See \f[B]Options for javap\f[R]. -.TP -\f[I]classes\f[R] -Specifies one or more classes separated by spaces to be processed for -annotations. -You can specify a class that can be found in the class path by its file -name, URL, or by its fully qualified class name. -.RS -.PP -Examples: -.RS -.PP -\f[V]path/to/MyClass.class\f[R] -.RE -.RS -.PP -\f[V]jar:file:///path/to/MyJar.jar!/mypkg/MyClass.class\f[R] -.RE -.RS -.PP -\f[V]java.lang.Object\f[R] -.RE -.RE -.SH DESCRIPTION -.PP -The \f[V]javap\f[R] command disassembles one or more class files. -The output depends on the options used. -When no options are used, the \f[V]javap\f[R] command prints the -protected and public fields, and methods of the classes passed to it. -.PP -The \f[V]javap\f[R] command isn\[aq]t multirelease JAR aware. -Using the class path form of the command results in viewing the base -entry in all JAR files, multirelease or not. -Using the URL form, you can use the URL form of an argument to specify a -specific version of a class to be disassembled. -.PP -The \f[V]javap\f[R] command prints its output to \f[V]stdout\f[R]. -.PP -\f[B]Note:\f[R] -.PP -In tools that support \f[V]--\f[R] style options, the GNU-style options -can use the equal sign (\f[V]=\f[R]) instead of a white space to -separate the name of an option from its value. -.SH OPTIONS FOR JAVAP -.TP -\f[V]--help\f[R], \f[V]-help\f[R] , \f[V]-h\f[R], or \f[V]-?\f[R] -Prints a help message for the \f[V]javap\f[R] command. -.TP -\f[V]-version\f[R] -Prints release information. -.TP -\f[V]-verbose\f[R] or \f[V]-v\f[R] -Prints additional information about the selected class. -.TP -\f[V]-l\f[R] -Prints line and local variable tables. -.TP -\f[V]-public\f[R] -Shows only public classes and members. -.TP -\f[V]-protected\f[R] -Shows only protected and public classes and members. -.TP -\f[V]-package\f[R] -Shows package/protected/public classes and members (default). -.TP -\f[V]-private\f[R] or \f[V]-p\f[R] -Shows all classes and members. -.TP -\f[V]-c\f[R] -Prints disassembled code, for example, the instructions that comprise -the Java bytecodes, for each of the methods in the class. -.TP -\f[V]-s\f[R] -Prints internal type signatures. -.TP -\f[V]-sysinfo\f[R] -Shows system information (path, size, date, SHA-256 hash) of the class -being processed. -.TP -\f[V]-verify\f[R] -Prints additional class verification info. -.TP -\f[V]-constants\f[R] -Shows \f[V]static final\f[R] constants. -.TP -\f[V]--module\f[R] \f[I]module\f[R] or \f[V]-m\f[R] \f[I]module\f[R] -Specifies the module containing classes to be disassembled. -.TP -\f[V]--module-path\f[R] \f[I]path\f[R] -Specifies where to find application modules. -.TP -\f[V]--system\f[R] \f[I]jdk\f[R] -Specifies where to find system modules. -.TP -\f[V]--class-path\f[R] \f[I]path\f[R], \f[V]-classpath\f[R] \f[I]path\f[R], or \f[V]-cp\f[R] \f[I]path\f[R] -Specifies the path that the \f[V]javap\f[R] command uses to find user -class files. -It overrides the default or the \f[V]CLASSPATH\f[R] environment variable -when it\[aq]s set. -.TP -\f[V]-bootclasspath\f[R] \f[I]path\f[R] -Overrides the location of bootstrap class files. -.TP -\f[V]--multi-release\f[R] \f[I]version\f[R] -Specifies the version to select in multi-release JAR files. -.TP -\f[V]-J\f[R]\f[I]option\f[R] -Passes the specified option to the JVM. -For example: -.RS -.IP -.nf -\f[CB] -javap -J-version - -javap -J-Djava.security.manager -J-Djava.security.policy=MyPolicy MyClassName -\f[R] -.fi -.PP -See \f[I]Overview of Java Options\f[R] in \f[B]java\f[R]. -.RE -.SH JAVAP EXAMPLE -.PP -Compile the following \f[V]HelloWorldFrame\f[R] class: -.IP -.nf -\f[CB] -import java.awt.Graphics; - -import javax.swing.JFrame; -import javax.swing.JPanel; - -public class HelloWorldFrame extends JFrame { - - String message = \[dq]Hello World!\[dq]; - - public HelloWorldFrame(){ - setContentPane(new JPanel(){ - \[at]Override - protected void paintComponent(Graphics g) { - g.drawString(message, 15, 30); - } - }); - setSize(100, 100); - } - public static void main(String[] args) { - HelloWorldFrame frame = new HelloWorldFrame(); - frame.setVisible(true); - - } - -} -\f[R] -.fi -.PP -The output from the \f[V]javap HelloWorldFrame.class\f[R] command yields -the following: -.IP -.nf -\f[CB] -Compiled from \[dq]HelloWorldFrame.java\[dq] -public class HelloWorldFrame extends javax.swing.JFrame { - java.lang.String message; - public HelloWorldFrame(); - public static void main(java.lang.String[]); -} -\f[R] -.fi -.PP -The output from the \f[V]javap -c HelloWorldFrame.class\f[R] command -yields the following: -.IP -.nf -\f[CB] -Compiled from \[dq]HelloWorldFrame.java\[dq] -public class HelloWorldFrame extends javax.swing.JFrame { - java.lang.String message; - - public HelloWorldFrame(); - Code: - 0: aload_0 - 1: invokespecial #1 // Method javax/swing/JFrame.\[dq]<init>\[dq]:()V - 4: aload_0 - 5: ldc #2 // String Hello World! - 7: putfield #3 // Field message:Ljava/lang/String; - 10: aload_0 - 11: new #4 // class HelloWorldFrame$1 - 14: dup - 15: aload_0 - 16: invokespecial #5 // Method HelloWorldFrame$1.\[dq]<init>\[dq]:(LHelloWorldFrame;)V - 19: invokevirtual #6 // Method setContentPane:(Ljava/awt/Container;)V - 22: aload_0 - 23: bipush 100 - 25: bipush 100 - 27: invokevirtual #7 // Method setSize:(II)V - 30: return - - public static void main(java.lang.String[]); - Code: - 0: new #8 // class HelloWorldFrame - 3: dup - 4: invokespecial #9 // Method \[dq]<init>\[dq]:()V - 7: astore_1 - 8: aload_1 - 9: iconst_1 - 10: invokevirtual #10 // Method setVisible:(Z)V - 13: return -} -\f[R] -.fi diff --git a/src/jdk.jdeps/share/man/javap.md b/src/jdk.jdeps/share/man/javap.md new file mode 100644 index 00000000000..814db56b3ba --- /dev/null +++ b/src/jdk.jdeps/share/man/javap.md @@ -0,0 +1,227 @@ +--- +# Copyright (c) 1994, 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. +# + +title: 'JAVAP(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +javap - disassemble one or more class files + +## Synopsis + +`javap` \[*options*\] *classes*... + +*options* +: Specifies the command-line options. See [Options for javap]. + +*classes* +: Specifies one or more classes separated by spaces to be processed for + annotations. You can specify a class that can be found in the class path by + its file name, URL, or by its fully qualified class name. + + Examples: + + > `path/to/MyClass.class` + + > `jar:file:///path/to/MyJar.jar!/mypkg/MyClass.class` + + > `java.lang.Object` + +## Description + +The `javap` command disassembles one or more class files. The output depends on +the options used. When no options are used, the `javap` command prints the +protected and public fields, and methods of the classes passed to it. + +The `javap` command isn't multirelease JAR aware. Using the class path form of +the command results in viewing the base entry in all JAR files, multirelease or +not. Using the URL form, you can use the URL form of an argument to specify a +specific version of a class to be disassembled. + +The `javap` command prints its output to `stdout`. + +**Note:** + +In tools that support `--` style options, the GNU-style options can use the +equal sign (`=`) instead of a white space to separate the name of an option +from its value. + +## Options for javap + +`--help`, `-help` , `-h`, or `-?` +: Prints a help message for the `javap` command. + +`-version` +: Prints release information. + +`-verbose` or `-v` +: Prints additional information about the selected class. + +`-l` +: Prints line and local variable tables. + +`-public` +: Shows only public classes and members. + +`-protected` +: Shows only protected and public classes and members. + +`-package` +: Shows package/protected/public classes and members (default). + +`-private` or `-p` +: Shows all classes and members. + +`-c` +: Prints disassembled code, for example, the instructions that comprise the + Java bytecodes, for each of the methods in the class. + +`-s` +: Prints internal type signatures. + +`-sysinfo` +: Shows system information (path, size, date, SHA-256 hash) of the class being + processed. + +`-verify` +: Prints additional class verification info. + +`-constants` +: Shows `static final` constants. + +`--module` *module* or `-m` *module* +: Specifies the module containing classes to be disassembled. + +`--module-path` *path* +: Specifies where to find application modules. + +`--system` *jdk* +: Specifies where to find system modules. + +`--class-path` *path*, `-classpath` *path*, or `-cp` *path* +: Specifies the path that the `javap` command uses to find user class files. + It overrides the default or the `CLASSPATH` environment variable when it's + set. + +`-bootclasspath` *path* +: Overrides the location of bootstrap class files. + +`--multi-release` *version* +: Specifies the version to select in multi-release JAR files. + +`-J`*option* +: Passes the specified option to the JVM. For example: + + ``` + javap -J-version + + javap -J-Djava.security.manager -J-Djava.security.policy=MyPolicy MyClassName + ``` + + See *Overview of Java Options* in [java](java.html). + +## javap Example + +Compile the following `HelloWorldFrame` class: + +``` +import java.awt.Graphics; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +public class HelloWorldFrame extends JFrame { + + String message = "Hello World!"; + + public HelloWorldFrame(){ + setContentPane(new JPanel(){ + @Override + protected void paintComponent(Graphics g) { + g.drawString(message, 15, 30); + } + }); + setSize(100, 100); + } + public static void main(String[] args) { + HelloWorldFrame frame = new HelloWorldFrame(); + frame.setVisible(true); + + } + +} +``` + +The output from the `javap HelloWorldFrame.class` command yields the following: + +``` +Compiled from "HelloWorldFrame.java" +public class HelloWorldFrame extends javax.swing.JFrame { + java.lang.String message; + public HelloWorldFrame(); + public static void main(java.lang.String[]); +} +``` + +The output from the `javap -c HelloWorldFrame.class` command yields the +following: + +``` +Compiled from "HelloWorldFrame.java" +public class HelloWorldFrame extends javax.swing.JFrame { + java.lang.String message; + + public HelloWorldFrame(); + Code: + 0: aload_0 + 1: invokespecial #1 // Method javax/swing/JFrame."<init>":()V + 4: aload_0 + 5: ldc #2 // String Hello World! + 7: putfield #3 // Field message:Ljava/lang/String; + 10: aload_0 + 11: new #4 // class HelloWorldFrame$1 + 14: dup + 15: aload_0 + 16: invokespecial #5 // Method HelloWorldFrame$1."<init>":(LHelloWorldFrame;)V + 19: invokevirtual #6 // Method setContentPane:(Ljava/awt/Container;)V + 22: aload_0 + 23: bipush 100 + 25: bipush 100 + 27: invokevirtual #7 // Method setSize:(II)V + 30: return + + public static void main(java.lang.String[]); + Code: + 0: new #8 // class HelloWorldFrame + 3: dup + 4: invokespecial #9 // Method "<init>":()V + 7: astore_1 + 8: aload_1 + 9: iconst_1 + 10: invokevirtual #10 // Method setVisible:(Z)V + 13: return +} +``` diff --git a/src/jdk.jdeps/share/man/jdeprscan.1 b/src/jdk.jdeps/share/man/jdeprscan.1 deleted file mode 100644 index fc13f05c449..00000000000 --- a/src/jdk.jdeps/share/man/jdeprscan.1 +++ /dev/null @@ -1,271 +0,0 @@ -.\" Copyright (c) 2017, 2023, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JDEPRSCAN" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jdeprscan - static analysis tool that scans a jar file (or some other -aggregation of class files) for uses of deprecated API elements -.SH SYNOPSIS -.PP -\f[V]jdeprscan\f[R] [\f[I]options\f[R]] -{\f[I]dir\f[R]|\f[I]jar\f[R]|\f[I]class\f[R]} -.TP -\f[I]options\f[R] -See \f[B]Options for the jdeprscan Command\f[R] -.TP -\f[I]dir\f[R]|\f[I]jar\f[R]|\f[I]class\f[R] -\f[V]jdeprscan\f[R] command scans each argument for usages of deprecated -APIs. -The arguments can be a: -.RS -.IP \[bu] 2 -\f[I]dir\f[R]: Directory -.IP \[bu] 2 -\f[I]jar\f[R]: JAR file -.IP \[bu] 2 -\f[I]class\f[R]: Class name or class file -.PP -The class name should use a dot (\f[V].\f[R]) as a separator. -For example: -.PP -\f[V]java.lang.Thread\f[R] -.PP -For nested classes, the dollar sign \f[V]$\f[R] separator character -should be used. -For example: -.PP -\f[V]java.lang.Thread$State\f[R] -.PP -A class file can also be named. -For example: -.PP -\f[V]build/classes/java/lang/Thread$State.class\f[R] -.RE -.SH DESCRIPTION -.PP -The \f[V]jdeprscan\f[R] tool is a static analysis tool provided by the -JDK that scans a JAR file or some other aggregation of class files for -uses of deprecated API elements. -The deprecated APIs identified by the \f[V]jdeprscan\f[R] tool are only -those that are defined by Java SE. -Deprecated APIs defined by third-party libraries aren\[aq]t reported. -.PP -To scan a JAR file or a set of class files, you must first ensure that -all of the classes that the scanned classes depend upon are present in -the class path. -Set the class path using the \f[V]--class-path\f[R] option described in -\f[B]Options for the jdeprscan Command\f[R]. -Typically, you would use the same class path as the one that you use -when invoking your application. -.PP -If the \f[V]jdeprscan\f[R] can\[aq]t find all the dependent classes, it -will generate an error message for each class that\[aq]s missing. -These error messages are typically of the form: -.RS -.PP -\f[V]error: cannot find class ...\f[R] -.RE -.PP -If these errors occur, then you must adjust the class path so that it -includes all dependent classes. -.SH OPTIONS FOR THE JDEPRSCAN COMMAND -.PP -The following options are available: -.TP -\f[V]--class-path\f[R] \f[I]path\f[R] -Provides a search path for resolution of dependent classes. -.RS -.PP -\f[I]path\f[R] can be a search path that consists of one or more -directories separated by the system-specific path separator. -For example: -.IP \[bu] 2 -\f[B]Linux and macOS:\f[R] -.RS 2 -.RS -.PP -\f[V]--class-path /some/directory:/another/different/dir\f[R] -.RE -.RE -.PP -\f[B]Note:\f[R] -.PP -On Windows, use a semicolon (\f[V];\f[R]) as the separator instead of a -colon (\f[V]:\f[R]). -.IP \[bu] 2 -\f[B]Windows:\f[R] -.RS 2 -.RS -.PP -\f[V]--class-path \[rs]some\[rs]directory;\[rs]another\[rs]different\[rs]dir\f[R] -.RE -.RE -.RE -.TP -\f[V]--for-removal\f[R] -Limits scanning or listing to APIs that are deprecated for removal. -Can\[aq]t be used with a release value of 6, 7, or 8. -.TP -\f[V]--full-version\f[R] -Prints out the full version string of the tool. -.TP -\f[V]--help\f[R] or \f[V]-h\f[R] -Prints out a full help message. -.TP -\f[V]--list\f[R] or \f[V]-l\f[R] -Prints the set of deprecated APIs. -No scanning is done, so no directory, jar, or class arguments should be -provided. -.TP -\f[V]--release\f[R] \f[V]6\f[R]|\f[V]7\f[R]|\f[V]8\f[R]|\f[V]9\f[R] -Specifies the Java SE release that provides the set of deprecated APIs -for scanning. -.TP -\f[V]--verbose\f[R] or \f[V]-v\f[R] -Enables additional message output during processing. -.TP -\f[V]--version\f[R] -Prints out the abbreviated version string of the tool. -.SH EXAMPLE OF JDEPRSCAN OUTPUT -.PP -The JAR file for this library will be named something similar to -\f[V]commons-math3-3.6.1.jar\f[R]. -To scan this JAR file for the use of deprecated APIs, run the following -command: -.RS -.PP -\f[V]jdeprscan commons-math3-3.6.1.jar\f[R] -.RE -.PP -This command produces several lines of output. -For example, one line of output might be: -.IP -.nf -\f[CB] -class org/apache/commons/math3/util/MathUtils uses deprecated method java/lang/Double::<init>(D)V -\f[R] -.fi -.PP -\f[B]Note:\f[R] -.PP -The class name is specified using the slash-separated binary name as -described in JVMS 4.2.1. -This is the form used internally in class files. -.PP -The deprecated API it uses is a method on the \f[V]java.lang.Double\f[R] -class. -.PP -The name of the deprecated method is \f[V]<init>\f[R], which is a -special name that means that the method is actually a constructor. -Another special name is \f[V]<clinit>\f[R], which indicates a class -static initializer. -.PP -Other methods are listed just by their method name. -Following the method name is the argument list and return type: -.RS -.PP -\f[V](D)V\f[R] -.RE -.PP -This indicates that it takes just one double value (a primitive) and -returns void. -The argument and return types can become cryptic. -For example, another line of output might be: -.IP -.nf -\f[CB] -class org/apache/commons/math3/util/Precision uses deprecated method java/math/BigDecimal::setScale(II)Ljava/math/BigDecimal; -\f[R] -.fi -.PP -In this line of output, the deprecated method is on class -\f[V]java.math.BigDecimal\f[R], and the method is \f[V]setScale()\f[R]. -In this case, the \f[V](II)\f[R] means that it takes two \f[V]int\f[R] -arguments. -The \f[V]Ljava/math/BigDecimal;\f[R] after the parentheses means that it -returns a reference to \f[V]java.math.BigDecimal\f[R]. -.SH JDEPRSCAN ANALYSIS CAN BE VERSION-SPECIFIC -.PP -You can use \f[V]jdeprscan\f[R] relative to the previous three JDK -releases. -For example, if you are running JDK 9, then you can check against JDK 8, -7, and 6. -.PP -As an example, look at this code snippet: -.IP -.nf -\f[CB] -public class Deprecations { - SecurityManager sm = new RMISecurityManager(); // deprecated in 8 - Boolean b2 = new Boolean(true); // deprecated in 9 -} -\f[R] -.fi -.PP -The complete class compiles without warnings in JDK 7. -.PP -If you run \f[V]jdeprscan\f[R] on a system with JDK 9, then you see: -.IP -.nf -\f[CB] -$ jdeprscan --class-path classes --release 7 example.Deprecations -(no output) -\f[R] -.fi -.PP -Run \f[V]jdeprscan\f[R] with a release value of 8: -.IP -.nf -\f[CB] -$ jdeprscan --class-path classes --release 8 example.Deprecations -class example/Deprecations uses type java/rmi/RMISecurityManager deprecated -class example/Deprecations uses method in type java/rmi/RMISecurityManager deprecated -\f[R] -.fi -.PP -Run \f[V]jdeprscan\f[R] on JDK 9: -.IP -.nf -\f[CB] -$ jdeprscan --class-path classes example.Deprecations -class example/Deprecations uses type java/rmi/RMISecurityManager deprecated -class example/Deprecations uses method in type java/rmi/RMISecurityManager deprecated -class example/Deprecations uses method java/lang/Boolean <init> (Z)V deprecated -\f[R] -.fi diff --git a/src/jdk.jdeps/share/man/jdeprscan.md b/src/jdk.jdeps/share/man/jdeprscan.md new file mode 100644 index 00000000000..8f76b29aee3 --- /dev/null +++ b/src/jdk.jdeps/share/man/jdeprscan.md @@ -0,0 +1,217 @@ +--- +# Copyright (c) 2017, 2023, 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. +# + +title: 'JDEPRSCAN(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jdeprscan - static analysis tool that scans a jar file (or some other +aggregation of class files) for uses of deprecated API elements + +## Synopsis + +`jdeprscan` \[*options*\] {*dir*\|*jar*\|*class*} + +*options* +: See [Options for the jdeprscan Command] + +*dir*\|*jar*\|*class* +: `jdeprscan` command scans each argument for usages of deprecated APIs. The + arguments can be a: + + - *dir*: Directory + + - *jar*: JAR file + + - *class*: Class name or class file + + The class name should use a dot (`.`) as a separator. For example: + + `java.lang.Thread` + + For nested classes, the dollar sign `$` separator character should be used. + For example: + + `java.lang.Thread$State` + + A class file can also be named. For example: + + `build/classes/java/lang/Thread$State.class` + +## Description + +The `jdeprscan` tool is a static analysis tool provided by the JDK that scans a +JAR file or some other aggregation of class files for uses of deprecated API +elements. The deprecated APIs identified by the `jdeprscan` tool are only those +that are defined by Java SE. Deprecated APIs defined by third-party libraries +aren't reported. + +To scan a JAR file or a set of class files, you must first ensure that all of +the classes that the scanned classes depend upon are present in the class +path. Set the class path using the `--class-path` option described in [Options +for the jdeprscan Command]. Typically, you would use the same class path as +the one that you use when invoking your application. + +If the `jdeprscan` can't find all the dependent classes, it will generate an +error message for each class that's missing. These error messages are typically +of the form: + +> `error: cannot find class ...` + +If these errors occur, then you must adjust the class path so that it includes +all dependent classes. + +## Options for the jdeprscan Command + +The following options are available: + +`--class-path` *path* +: Provides a search path for resolution of dependent classes. + + *path* can be a search path that consists of one or more directories + separated by the system-specific path separator. For example: + + - **Linux and macOS:** + + > `--class-path /some/directory:/another/different/dir` + + **Note:** + + On Windows, use a semicolon (`;`) as the separator instead of a colon + (`:`). + + - **Windows:** + + > `--class-path \some\directory;\another\different\dir` + +`--for-removal` +: Limits scanning or listing to APIs that are deprecated for removal. Can't + be used with a release value of 6, 7, or 8. + +`--full-version` +: Prints out the full version string of the tool. + +`--help` or `-h` +: Prints out a full help message. + +`--list` or `-l` +: Prints the set of deprecated APIs. No scanning is done, so no directory, + jar, or class arguments should be provided. + +`--release` `6`\|`7`\|`8`\|`9` +: Specifies the Java SE release that provides the set of deprecated APIs for + scanning. + +`--verbose` or `-v` +: Enables additional message output during processing. + +`--version` +: Prints out the abbreviated version string of the tool. + +## Example of jdeprscan Output + +The JAR file for this library will be named something similar to +`commons-math3-3.6.1.jar`. To scan this JAR file for the use of deprecated +APIs, run the following command: + +> `jdeprscan commons-math3-3.6.1.jar` + +This command produces several lines of output. For example, one line of output +might be: + +``` +class org/apache/commons/math3/util/MathUtils uses deprecated method java/lang/Double::<init>(D)V +``` + +**Note:** + +The class name is specified using the slash-separated binary name as described +in JVMS 4.2.1. This is the form used internally in class files. + +The deprecated API it uses is a method on the `java.lang.Double` class. + +The name of the deprecated method is `<init>`, which is a special name that +means that the method is actually a constructor. Another special name is +`<clinit>`, which indicates a class static initializer. + +Other methods are listed just by their method name. Following the method name +is the argument list and return type: + +> `(D)V` + +This indicates that it takes just one double value (a primitive) and returns +void. The argument and return types can become cryptic. For example, another +line of output might be: + +``` +class org/apache/commons/math3/util/Precision uses deprecated method java/math/BigDecimal::setScale(II)Ljava/math/BigDecimal; +``` + +In this line of output, the deprecated method is on class +`java.math.BigDecimal`, and the method is `setScale()`. In this case, the +`(II)` means that it takes two `int` arguments. The `Ljava/math/BigDecimal;` +after the parentheses means that it returns a reference to +`java.math.BigDecimal`. + +## jdeprscan Analysis Can Be Version-Specific + +You can use `jdeprscan` relative to the previous three JDK releases. For +example, if you are running JDK 9, then you can check against JDK 8, 7, and 6. + +As an example, look at this code snippet: + +``` +public class Deprecations { + SecurityManager sm = new RMISecurityManager(); // deprecated in 8 + Boolean b2 = new Boolean(true); // deprecated in 9 +} +``` + +The complete class compiles without warnings in JDK 7. + +If you run `jdeprscan` on a system with JDK 9, then you see: + +``` +$ jdeprscan --class-path classes --release 7 example.Deprecations +(no output) +``` + +Run `jdeprscan` with a release value of 8: + +``` +$ jdeprscan --class-path classes --release 8 example.Deprecations +class example/Deprecations uses type java/rmi/RMISecurityManager deprecated +class example/Deprecations uses method in type java/rmi/RMISecurityManager deprecated +``` + +Run `jdeprscan` on JDK 9: + +``` +$ jdeprscan --class-path classes example.Deprecations +class example/Deprecations uses type java/rmi/RMISecurityManager deprecated +class example/Deprecations uses method in type java/rmi/RMISecurityManager deprecated +class example/Deprecations uses method java/lang/Boolean <init> (Z)V deprecated +``` diff --git a/src/jdk.jdeps/share/man/jdeps.1 b/src/jdk.jdeps/share/man/jdeps.1 deleted file mode 100644 index d3dde37e3b9..00000000000 --- a/src/jdk.jdeps/share/man/jdeps.1 +++ /dev/null @@ -1,338 +0,0 @@ -.\" Copyright (c) 2013, 2023, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JDEPS" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jdeps - launch the Java class dependency analyzer -.SH SYNOPSIS -.PP -\f[V]jdeps\f[R] [\f[I]options\f[R]] \f[I]path\f[R] ... -.TP -\f[I]options\f[R] -Command-line options. -For detailed descriptions of the options that can be used, see -.RS -.IP \[bu] 2 -\f[B]Possible Options\f[R] -.IP \[bu] 2 -\f[B]Module Dependence Analysis Options\f[R] -.IP \[bu] 2 -\f[B]Options to Filter Dependences\f[R] -.IP \[bu] 2 -\f[B]Options to Filter Classes to be Analyzed\f[R] -.RE -.TP -\f[I]path\f[R] -A pathname to the \f[V].class\f[R] file, directory, or JAR file to -analyze. -.SH DESCRIPTION -.PP -The \f[V]jdeps\f[R] command shows the package-level or class-level -dependencies of Java class files. -The input class can be a path name to a \f[V].class\f[R] file, a -directory, a JAR file, or it can be a fully qualified class name to -analyze all class files. -The options determine the output. -By default, the \f[V]jdeps\f[R] command writes the dependencies to the -system output. -The command can generate the dependencies in DOT language (see the -\f[V]-dotoutput\f[R] option). -.SH POSSIBLE OPTIONS -.TP -\f[V]-?\f[R] or \f[V]-h\f[R] or \f[V]--help\f[R] -Prints the help message. -.TP -\f[V]-dotoutput\f[R] \f[I]dir\f[R] or \f[V]--dot-output\f[R] \f[I]dir\f[R] -Specifies the destination directory for DOT file output. -If this option is specified, then the \f[V]jdeps\f[R]command generates -one \f[V].dot\f[R] file for each analyzed archive named -\f[V]archive-file-name.dot\f[R] that lists the dependencies, and also a -summary file named \f[V]summary.dot\f[R] that lists the dependencies -among the archive files. -.TP -\f[V]-s\f[R] or \f[V]-summary\f[R] -Prints a dependency summary only. -.TP -\f[V]-v\f[R] or \f[V]-verbose\f[R] -Prints all class-level dependencies. -This is equivalent to -.RS -.RS -.PP -\f[V]-verbose:class -filter:none\f[R] -.RE -.RE -.TP -\f[V]-verbose:package\f[R] -Prints package-level dependencies excluding, by default, dependences -within the same package. -.TP -\f[V]-verbose:class\f[R] -Prints class-level dependencies excluding, by default, dependencies -within the same archive. -.TP -\f[V]-apionly\f[R] or \f[V]--api-only\f[R] -Restricts the analysis to APIs, for example, dependences from the -signature of \f[V]public\f[R] and \f[V]protected\f[R] members of public -classes including field type, method parameter types, returned type, and -checked exception types. -.TP -\f[V]-jdkinternals\f[R] or \f[V]--jdk-internals\f[R] -Finds class-level dependences in the JDK internal APIs. -By default, this option analyzes all classes specified in the -\f[V]--classpath\f[R] option and input files unless you specified the -\f[V]-include\f[R] option. -You can\[aq]t use this option with the \f[V]-p\f[R], \f[V]-e\f[R], and -\f[V]-s\f[R] options. -.RS -.PP -\f[B]Warning\f[R]: The JDK internal APIs are inaccessible. -.RE -.TP -\f[V]-cp\f[R] \f[I]path\f[R], \f[V]-classpath\f[R] \f[I]path\f[R], or \f[V]--class-path\f[R] \f[I]path\f[R] -Specifies where to find class files. -.TP -\f[V]--module-path\f[R] \f[I]module-path\f[R] -Specifies the module path. -.TP -\f[V]--upgrade-module-path\f[R] \f[I]module-path\f[R] -Specifies the upgrade module path. -.TP -\f[V]--system\f[R] \f[I]java-home\f[R] -Specifies an alternate system module path. -.TP -\f[V]--add-modules\f[R] \f[I]module-name\f[R][\f[V],\f[R] \f[I]module-name\f[R]...] -Adds modules to the root set for analysis. -.TP -\f[V]--multi-release\f[R] \f[I]version\f[R] -Specifies the version when processing multi-release JAR files. -\f[I]version\f[R] should be an integer >=9 or base. -.TP -\f[V]-q\f[R] or \f[V]-quiet\f[R] -Doesn\[aq]t show missing dependencies from -\f[V]-generate-module-info\f[R] output. -.TP -\f[V]-version\f[R] or \f[V]--version\f[R] -Prints version information. -.SH MODULE DEPENDENCE ANALYSIS OPTIONS -.TP -\f[V]-m\f[R] \f[I]module-name\f[R] or \f[V]--module\f[R] \f[I]module-name\f[R] -Specifies the root module for analysis. -.TP -\f[V]--generate-module-info\f[R] \f[I]dir\f[R] -Generates \f[V]module-info.java\f[R] under the specified directory. -The specified JAR files will be analyzed. -This option cannot be used with \f[V]--dot-output\f[R] or -\f[V]--class-path\f[R] options. -Use the \f[V]--generate-open-module\f[R] option for open modules. -.TP -\f[V]--generate-open-module\f[R] \f[I]dir\f[R] -Generates \f[V]module-info.java\f[R] for the specified JAR files under -the specified directory as open modules. -This option cannot be used with the \f[V]--dot-output\f[R] or -\f[V]--class-path\f[R] options. -.TP -\f[V]--check\f[R] \f[I]module-name\f[R] [\f[V],\f[R] \f[I]module-name\f[R]...] -Analyzes the dependence of the specified modules. -It prints the module descriptor, the resulting module dependences after -analysis and the graph after transition reduction. -It also identifies any unused qualified exports. -.TP -\f[V]--list-deps\f[R] -Lists the module dependences and also the package names of JDK internal -APIs (if referenced). -This option transitively analyzes libraries on class path and module -path if referenced. -Use \f[V]--no-recursive\f[R] option for non-transitive dependency -analysis. -.TP -\f[V]--list-reduced-deps\f[R] -Same as \f[V]--list-deps\f[R] without listing the implied reads edges -from the module graph. -If module M1 reads M2, and M2 requires transitive on M3, then M1 reading -M3 is implied and is not shown in the graph. -.TP -\f[V]--print-module-deps\f[R] -Same as \f[V]--list-reduced-deps\f[R] with printing a comma-separated -list of module dependences. -The output can be used by \f[V]jlink --add-modules\f[R] to create a -custom image that contains those modules and their transitive -dependences. -.TP -\f[V]--ignore-missing-deps\f[R] -Ignore missing dependences. -.SH OPTIONS TO FILTER DEPENDENCES -.TP -\f[V]-p\f[R] \f[I]pkg_name\f[R], \f[V]-package\f[R] \f[I]pkg_name\f[R], or \f[V]--package\f[R] \f[I]pkg_name\f[R] -Finds dependences matching the specified package name. -You can specify this option multiple times for different packages. -The \f[V]-p\f[R] and \f[V]-e\f[R] options are mutually exclusive. -.TP -\f[V]-e\f[R] \f[I]regex\f[R], \f[V]-regex\f[R] \f[I]regex\f[R], or \f[V]--regex\f[R] \f[I]regex\f[R] -Finds dependences matching the specified pattern. -The \f[V]-p\f[R] and \f[V]-e\f[R] options are mutually exclusive. -.TP -\f[V]--require\f[R] \f[I]module-name\f[R] -Finds dependences matching the given module name (may be given multiple -times). -The \f[V]--package\f[R], \f[V]--regex\f[R], and \f[V]--require\f[R] -options are mutually exclusive. -.TP -\f[V]-f\f[R] \f[I]regex\f[R] or \f[V]-filter\f[R] \f[I]regex\f[R] -Filters dependences matching the given pattern. -If give multiple times, the last one will be selected. -.TP -\f[V]-filter:package\f[R] -Filters dependences within the same package. -This is the default. -.TP -\f[V]-filter:archive\f[R] -Filters dependences within the same archive. -.TP -\f[V]-filter:module\f[R] -Filters dependences within the same module. -.TP -\f[V]-filter:none\f[R] -No \f[V]-filter:package\f[R] and \f[V]-filter:archive\f[R] filtering. -Filtering specified via the \f[V]-filter\f[R] option still applies. -.TP -\f[V]--missing-deps\f[R] -Finds missing dependences. -This option cannot be used with \f[V]-p\f[R], \f[V]-e\f[R] and -\f[V]-s\f[R] options. -.SH OPTIONS TO FILTER CLASSES TO BE ANALYZED -.TP -\f[V]-include\f[R] \f[I]regex\f[R] -Restricts analysis to the classes matching pattern. -This option filters the list of classes to be analyzed. -It can be used together with \f[V]-p\f[R] and \f[V]-e\f[R], which apply -the pattern to the dependencies. -.TP -\f[V]-R\f[R] or \f[V]--recursive\f[R] -Recursively traverses all run-time dependences. -The \f[V]-R\f[R] option implies \f[V]-filter:none\f[R]. -If \f[V]-p\f[R], \f[V]-e\f[R], or \f[V]-f\f[R] options are specified, -only the matching dependences are analyzed. -.TP -\f[V]--no-recursive\f[R] -Do not recursively traverse dependences. -.TP -\f[V]-I\f[R] or \f[V]--inverse\f[R] -Analyzes the dependences per other given options and then finds all -artifacts that directly and indirectly depend on the matching nodes. -This is equivalent to the inverse of the compile-time view analysis and -the print dependency summary. -This option must be used with the \f[V]--require\f[R], -\f[V]--package\f[R], or \f[V]--regex\f[R] options. -.TP -\f[V]--compile-time\f[R] -Analyzes the compile-time view of transitive dependencies, such as the -compile-time view of the \f[V]-R\f[R] option. -Analyzes the dependences per other specified options. -If a dependency is found from a directory, a JAR file or a module, all -classes in that containing archive are analyzed. -.SH EXAMPLE OF ANALYZING DEPENDENCIES -.PP -The following example demonstrates analyzing the dependencies of the -\f[V]Notepad.jar\f[R] file. -.PP -\f[B]Linux and macOS:\f[R] -.IP -.nf -\f[CB] -$ jdeps demo/jfc/Notepad/Notepad.jar -Notepad.jar -> java.base -Notepad.jar -> java.desktop -Notepad.jar -> java.logging - <unnamed> (Notepad.jar) - -> java.awt - -> java.awt.event - -> java.beans - -> java.io - -> java.lang - -> java.net - -> java.util - -> java.util.logging - -> javax.swing - -> javax.swing.border - -> javax.swing.event - -> javax.swing.text - -> javax.swing.tree - -> javax.swing.undo -\f[R] -.fi -.PP -\f[B]Windows:\f[R] -.IP -.nf -\f[CB] -C:\[rs]Java\[rs]jdk1.9.0>jdeps demo\[rs]jfc\[rs]Notepad\[rs]Notepad.jar -Notepad.jar -> java.base -Notepad.jar -> java.desktop -Notepad.jar -> java.logging - <unnamed> (Notepad.jar) - -> java.awt - -> java.awt.event - -> java.beans - -> java.io - -> java.lang - -> java.net - -> java.util - -> java.util.logging - -> javax.swing - -> javax.swing.border - -> javax.swing.event - -> javax.swing.text - -> javax.swing.tree - -> javax.swing.undo -\f[R] -.fi -.SH EXAMPLE USING THE --INVERSE OPTION -.IP -.nf -\f[CB] - $ jdeps --inverse --require java.xml.bind -Inverse transitive dependences on [java.xml.bind] -java.xml.bind <- java.se.ee -java.xml.bind <- jdk.xml.ws -java.xml.bind <- java.xml.ws <- java.se.ee -java.xml.bind <- java.xml.ws <- jdk.xml.ws -java.xml.bind <- jdk.xml.bind <- jdk.xml.ws -\f[R] -.fi diff --git a/src/jdk.jdeps/share/man/jdeps.md b/src/jdk.jdeps/share/man/jdeps.md new file mode 100644 index 00000000000..cb936bf3e01 --- /dev/null +++ b/src/jdk.jdeps/share/man/jdeps.md @@ -0,0 +1,297 @@ +--- +# Copyright (c) 2013, 2023, 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. +# + +title: 'JDEPS(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jdeps - launch the Java class dependency analyzer + +## Synopsis + +`jdeps` \[*options*\] *path* ... + +*options* +: Command-line options. For detailed descriptions of the options that can be + used, see + + - [Possible Options] + + - [Module Dependence Analysis Options] + + - [Options to Filter Dependences] + + - [Options to Filter Classes to be Analyzed] + +*path* +: A pathname to the `.class` file, directory, or JAR file to analyze. + +## Description + +The `jdeps` command shows the package-level or class-level dependencies of Java +class files. The input class can be a path name to a `.class` file, a +directory, a JAR file, or it can be a fully qualified class name to analyze all +class files. The options determine the output. By default, the `jdeps` command +writes the dependencies to the system output. The command can generate the +dependencies in DOT language (see the `-dotoutput` option). + +## Possible Options + +`-?` or `-h` or `--help` +: Prints the help message. + +`-dotoutput` *dir* or `--dot-output` *dir* +: Specifies the destination directory for DOT file output. If this option is + specified, then the `jdeps`command generates one `.dot` file for each + analyzed archive named `archive-file-name.dot` that lists the dependencies, + and also a summary file named `summary.dot` that lists the dependencies + among the archive files. + +`-s` or `-summary` +: Prints a dependency summary only. + +`-v` or `-verbose` +: Prints all class-level dependencies. This is equivalent to + + > `-verbose:class -filter:none` + +`-verbose:package` +: Prints package-level dependencies excluding, by default, dependences within + the same package. + +`-verbose:class` +: Prints class-level dependencies excluding, by default, dependencies within + the same archive. + +`-apionly` or `--api-only` +: Restricts the analysis to APIs, for example, dependences from the signature + of `public` and `protected` members of public classes including field type, + method parameter types, returned type, and checked exception types. + +`-jdkinternals` or `--jdk-internals` +: Finds class-level dependences in the JDK internal APIs. By default, this + option analyzes all classes specified in the `--classpath` option and input + files unless you specified the `-include` option. You can't use this option + with the `-p`, `-e`, and `-s` options. + + **Warning**: The JDK internal APIs are inaccessible. + +`-cp` *path*, `-classpath` *path*, or `--class-path` *path* +: Specifies where to find class files. + +`--module-path` *module-path* +: Specifies the module path. + +`--upgrade-module-path` *module-path* +: Specifies the upgrade module path. + +`--system` *java-home* +: Specifies an alternate system module path. + +`--add-modules` *module-name*\[`,` *module-name*...\] +: Adds modules to the root set for analysis. + +`--multi-release` *version* +: Specifies the version when processing multi-release JAR files. *version* + should be an integer \>=9 or base. + +`-q` or `-quiet` +: Doesn't show missing dependencies from `-generate-module-info` output. + +`-version` or `--version` +: Prints version information. + +## Module Dependence Analysis Options + +`-m` *module-name* or `--module` *module-name* +: Specifies the root module for analysis. + +`--generate-module-info` *dir* +: Generates `module-info.java` under the specified directory. The specified + JAR files will be analyzed. This option cannot be used with `--dot-output` + or `--class-path` options. Use the `--generate-open-module` option for open + modules. + +`--generate-open-module` *dir* +: Generates `module-info.java` for the specified JAR files under the + specified directory as open modules. This option cannot be used with the + `--dot-output` or `--class-path` options. + +`--check` *module-name* \[`,` *module-name*...\] +: Analyzes the dependence of the specified modules. It prints the module + descriptor, the resulting module dependences after analysis and the graph + after transition reduction. It also identifies any unused qualified + exports. + +`--list-deps` +: Lists the module dependences and also the package names of JDK internal + APIs (if referenced). This option transitively analyzes libraries on + class path and module path if referenced. Use `--no-recursive` option for + non-transitive dependency analysis. + +`--list-reduced-deps` +: Same as `--list-deps` without listing the implied reads edges from the + module graph. If module M1 reads M2, and M2 requires transitive on M3, then + M1 reading M3 is implied and is not shown in the graph. + +`--print-module-deps` +: Same as `--list-reduced-deps` with printing a comma-separated list of + module dependences. The output can be used by `jlink --add-modules` to + create a custom image that contains those modules and their transitive + dependences. + +`--ignore-missing-deps` +: Ignore missing dependences. + +## Options to Filter Dependences + +`-p` *pkg\_name*, `-package` *pkg\_name*, or `--package` *pkg\_name* +: Finds dependences matching the specified package name. You can specify this + option multiple times for different packages. The `-p` and `-e` options are + mutually exclusive. + +`-e` *regex*, `-regex` *regex*, or `--regex` *regex* +: Finds dependences matching the specified pattern. The `-p` and `-e` options + are mutually exclusive. + +`--require` *module-name* +: Finds dependences matching the given module name (may be given multiple + times). The `--package`, `--regex`, and `--require` options are mutually + exclusive. + +`-f` *regex* or `-filter` *regex* +: Filters dependences matching the given pattern. If give multiple times, the + last one will be selected. + +`-filter:package` +: Filters dependences within the same package. This is the default. + +`-filter:archive` +: Filters dependences within the same archive. + +`-filter:module` +: Filters dependences within the same module. + +`-filter:none` +: No `-filter:package` and `-filter:archive` filtering. Filtering specified + via the `-filter` option still applies. + +`--missing-deps` +: Finds missing dependences. This option cannot be used with `-p`, `-e` and + `-s` options. + +## Options to Filter Classes to be Analyzed + +`-include` *regex* +: Restricts analysis to the classes matching pattern. This option filters the + list of classes to be analyzed. It can be used together with `-p` and `-e`, + which apply the pattern to the dependencies. + +`-R` or `--recursive` +: Recursively traverses all run-time dependences. The `-R` option implies + `-filter:none`. If `-p`, `-e`, or `-f` options are specified, only the + matching dependences are analyzed. + +`--no-recursive` +: Do not recursively traverse dependences. + +`-I` or `--inverse` +: Analyzes the dependences per other given options and then finds all + artifacts that directly and indirectly depend on the matching nodes. This + is equivalent to the inverse of the compile-time view analysis and the + print dependency summary. This option must be used with the `--require`, + `--package`, or `--regex` options. + +`--compile-time` +: Analyzes the compile-time view of transitive dependencies, such as the + compile-time view of the `-R` option. Analyzes the dependences per other + specified options. If a dependency is found from a directory, a JAR file or + a module, all classes in that containing archive are analyzed. + +## Example of Analyzing Dependencies + +The following example demonstrates analyzing the dependencies of the +`Notepad.jar` file. + +**Linux and macOS:** + +``` +$ jdeps demo/jfc/Notepad/Notepad.jar +Notepad.jar -> java.base +Notepad.jar -> java.desktop +Notepad.jar -> java.logging + <unnamed> (Notepad.jar) + -> java.awt + -> java.awt.event + -> java.beans + -> java.io + -> java.lang + -> java.net + -> java.util + -> java.util.logging + -> javax.swing + -> javax.swing.border + -> javax.swing.event + -> javax.swing.text + -> javax.swing.tree + -> javax.swing.undo +``` + +**Windows:** + +``` +C:\Java\jdk1.9.0>jdeps demo\jfc\Notepad\Notepad.jar +Notepad.jar -> java.base +Notepad.jar -> java.desktop +Notepad.jar -> java.logging + <unnamed> (Notepad.jar) + -> java.awt + -> java.awt.event + -> java.beans + -> java.io + -> java.lang + -> java.net + -> java.util + -> java.util.logging + -> javax.swing + -> javax.swing.border + -> javax.swing.event + -> javax.swing.text + -> javax.swing.tree + -> javax.swing.undo +``` + +## Example Using the --inverse Option + +``` + $ jdeps --inverse --require java.xml.bind +Inverse transitive dependences on [java.xml.bind] +java.xml.bind <- java.se.ee +java.xml.bind <- jdk.xml.ws +java.xml.bind <- java.xml.ws <- java.se.ee +java.xml.bind <- java.xml.ws <- jdk.xml.ws +java.xml.bind <- jdk.xml.bind <- jdk.xml.ws +``` diff --git a/src/jdk.jdeps/share/man/jnativescan.1 b/src/jdk.jdeps/share/man/jnativescan.1 deleted file mode 100644 index ff7f18277f2..00000000000 --- a/src/jdk.jdeps/share/man/jnativescan.1 +++ /dev/null @@ -1,220 +0,0 @@ -.\" Copyright (c) 2024, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JNATIVESCAN" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jnativescan - static analysis tool that scans one or more jar files for -uses of native functionalities, such as restricted method calls or -\f[V]native\f[R] method declarations. -.SH SYNOPSIS -.PP -\f[V]jnativescan\f[R] [\f[I]options\f[R]] -.TP -\f[I]options\f[R] -See \f[B]Options for the jnativescan Command\f[R] -.SH DESCRIPTION -.PP -The \f[V]jnative\f[R] tool is a static analysis tool provided by the JDK -that scans a JAR file for uses of native functionalities, such as -restricted method calls or \f[V]native\f[R] method declarations. -.PP -\f[V]jnativescan\f[R] accepts a runtime class path and module path -configuration, as well as a set of root modules, and a target release. -It scans the jars on the class and module paths, and reports uses of -native functionalities either in a tree like structure, which also -identifies that calling classes and methods, or as a list of module -names when the \f[V]--print-native-access\f[R] flag is specified. -.SH OPTIONS FOR THE JNATIVESCAN COMMAND -.PP -The following options are available: -.TP -\f[V]--class-path\f[R] \f[I]path\f[R] -Used to specify a list of paths pointing to jar files to be scanned. -.PP -All jar files specified through this list will be scanned. -If a jar file contains a \f[V]Class-Path\f[R] attribute in its manifest, -jar files listed there will be scanned as well. -Jar files listed in the \f[V]Class-Path\f[R] manifest attribute that can -not be found are ignored. -All the jar files found are treated as if they belonged to the unnamed -module. -.TP -\f[V]--module-path\f[R] \f[I]path\f[R] -Used to specify a list of paths pointing to jar files or directories -containing jar files, that the tool can use to find modules that need to -be scanned. -The list of jar files that will be scanned depends on the -\f[V]--add-modules\f[R] option. -.RS -.PP -For both the \f[V]--class-path\f[R] and \f[V]--module-path\f[R] options, -\f[I]path\f[R] should be a search path that consists of one or more jar -files, separated by the system-specific path separator. -For example: -.IP \[bu] 2 -\f[B]Linux and macOS:\f[R] -.RS 2 -.RS -.PP -\f[V]--class-path /some/foo.jar:/another/different/bar.jar\f[R] -.RE -.RE -.PP -\f[B]Note:\f[R] -.PP -On Windows, use a semicolon (\f[V];\f[R]) as the separator instead of a -colon (\f[V]:\f[R]). -.IP \[bu] 2 -\f[B]Windows:\f[R] -.RS 2 -.RS -.PP -\f[V]--class-path C:\[rs]some\[rs]foo.jar;C:\[rs]another\[rs]different\[rs]bar.jar\f[R] -.RE -.RE -.RE -.TP -\f[V]--add-modules\f[R] \f[I]module[,module...]\f[R] -Used to specify a comma-separated list of module names that indicate the -root modules to scan. -All the root modules will be scanned, as well as any modules that they -depend on. -This includes dependencies on service implementations specified through -the \f[V]uses\f[R] directive in a module\[aq]s \f[V]module-info\f[R] -file. -All modules found on the module path that provide an implementation of -such a service will be scanned as well. -.TP -\f[V]--release\f[R] \f[I]version\f[R] -Used to specify the Java SE release that specifies the set of restricted -methods to scan for. -For multi-release jar files, this option also indicates the version of -class file that should be loaded from the jar. -This option should be set to the version of the runtime under which the -application is eventually intended to be run. -If this flag is omitted, the version of \f[V]jnativescan\f[R] is used as -release version, which is the same as the version of the JDK that the -tool belongs to. -.TP -\f[V]--print-native-access\f[R] -Print a comma-separated list of module names that use native -functionalities, instead of the default tree structure. -.TP -\f[V]--help\f[R] or \f[V]-h\f[R] -Prints out a full help message. -.TP -\f[V]--version\f[R] -Prints out the abbreviated version string of the tool. -.SH EXAMPLE OF \f[V]jnativescan\f[R] USE -.PP -\f[V]jnativescan\f[R] accepts a runtime configuration in the form of a -class path, module path, set of root modules, and a target release -version. -For the class path, the tool will scan all jar files, including those -found recursively through the \f[V]Class-Path\f[R] manifest attribute. -For the module path, the tool scans all root modules specified through -\f[V]--add-modules\f[R], and any (transitive) dependence of the root -modules, including any modules that contain service implementations that -are used by a scanned module. -.PP -By default, the tool prints out which jars, classes, and methods use -native functionalities, in a tree-like structure. -The following is an example output: -.IP -.nf -\f[CB] -$ jnativescan --class-path app.jar -app.jar (ALL-UNNAMED): - foo.Main: - foo.Main::main(String[])void references restricted methods: - java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment - foo.Main::nativeMethod()void is a native method declaration -\f[R] -.fi -.PP -\f[V]app.jar (ALL-UNNAMED)\f[R] is the path to the jar file, with the -module name in parentheses behind it. -Since in this case the jar file appears on the class path, -\f[V]ALL-UNNAMED\f[R] is printed to indicate the unnamed module. -The second line of the output, \f[V]foo.Main\f[R], indicates that -methods using native functionalities were found in the -\f[V]foo.Main\f[R] class. -The next line: -.IP -.nf -\f[CB] - foo.Main::main(String[])void references restricted methods: -\f[R] -.fi -.PP -Indicates that the \f[V]main(String[])\f[R] method in the -\f[V]foo.Main\f[R] class references a restricted method, which is listed -on the following line as: -.IP -.nf -\f[CB] - java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment -\f[R] -.fi -.PP -Lastly, the text: -.IP -.nf -\f[CB] - foo.Main::nativeMethod()void is a native method declaration -\f[R] -.fi -.PP -Indicates that the \f[V]foo.Main\f[R] class contains a declaration of a -\f[V]native\f[R] method named \f[V]nativeMethod\f[R]. -.PP -If we add \f[V]--print-native-access\f[R] to the example command line, -we instead get a list of the names of modules that contain accesses to -native functionalities: -.IP -.nf -\f[CB] -$ jnativescan --class-path app.jar --print-native-access -ALL-UNNAMED -\f[R] -.fi -.PP -In this case the output consists of just \f[V]ALL-UNNAMED\f[R], which -indicates a jar file on the class path, that is, in the unnamed module, -contains an access to native functionalities. diff --git a/src/jdk.jdeps/share/man/jnativescan.md b/src/jdk.jdeps/share/man/jnativescan.md new file mode 100644 index 00000000000..73c2429fc89 --- /dev/null +++ b/src/jdk.jdeps/share/man/jnativescan.md @@ -0,0 +1,175 @@ +--- +# Copyright (c) 2024, 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. +# + +title: 'JNATIVESCAN(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jnativescan - static analysis tool that scans one or more jar files for uses of +native functionalities, such as restricted method calls or `native` method declarations. + +## Synopsis + +`jnativescan` \[*options*\] + +*options* +: See [Options for the jnativescan Command] + +## Description + +The `jnative` tool is a static analysis tool provided by the JDK that scans a +JAR file for uses of native functionalities, such as restricted method calls +or `native` method declarations. + +`jnativescan` accepts a runtime class path and module path configuration, as +well as a set of root modules, and a target release. It scans the jars on the +class and module paths, and reports uses of native functionalities either in a tree +like structure, which also identifies that calling classes and methods, or as a list +of module names when the `--print-native-access` flag is specified. + +## Options for the jnativescan Command + +The following options are available: + +`--class-path` *path* +: Used to specify a list of paths pointing to jar files to be scanned. + +All jar files specified through this list will be scanned. If a jar file +contains a `Class-Path` attribute in its manifest, jar files listed there +will be scanned as well. Jar files listed in the `Class-Path` manifest +attribute that can not be found are ignored. All the jar files found are +treated as if they belonged to the unnamed module. + +`--module-path` *path* +: Used to specify a list of paths pointing to jar files or directories +containing jar files, that the tool can use to find modules that need +to be scanned. The list of jar files that will be scanned depends on the +`--add-modules` option. + + For both the `--class-path` and `--module-path` options, *path* should + be a search path that consists of one or more jar files, separated by + the system-specific path separator. For example: + + - **Linux and macOS:** + + > `--class-path /some/foo.jar:/another/different/bar.jar` + + **Note:** + + On Windows, use a semicolon (`;`) as the separator instead of a colon + (`:`). + + - **Windows:** + + > `--class-path C:\some\foo.jar;C:\another\different\bar.jar` + +`--add-modules` *module[,module...]* +: Used to specify a comma-separated list of module names that indicate +the root modules to scan. All the root modules will be scanned, +as well as any modules that they depend on. This includes dependencies on +service implementations specified through the `uses` directive in a module's +`module-info` file. All modules found on the module path that provide an +implementation of such a service will be scanned as well. + +`--release` *version* +: Used to specify the Java SE release that specifies the set of restricted +methods to scan for. For multi-release jar files, this option also indicates +the version of class file that should be loaded from the jar. This option +should be set to the version of the runtime under which the application is +eventually intended to be run. If this flag is omitted, the version of +`jnativescan` is used as release version, which is the same as the version of +the JDK that the tool belongs to. + +`--print-native-access` +: Print a comma-separated list of module names that use native functionalities, +instead of the default tree structure. + +`--help` or `-h` +: Prints out a full help message. + +`--version` +: Prints out the abbreviated version string of the tool. + +## Example of `jnativescan` use + +`jnativescan` accepts a runtime configuration in the form of a class path, module +path, set of root modules, and a target release version. For the class path, the +tool will scan all jar files, including those found recursively through the +`Class-Path` manifest attribute. For the module path, the tool scans all root +modules specified through `--add-modules`, and any (transitive) dependence of +the root modules, including any modules that contain service implementations that +are used by a scanned module. + +By default, the tool prints out which jars, classes, and methods use native +functionalities, in a tree-like structure. The following is an example output: + +``` +$ jnativescan --class-path app.jar +app.jar (ALL-UNNAMED): + foo.Main: + foo.Main::main(String[])void references restricted methods: + java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment + foo.Main::nativeMethod()void is a native method declaration +``` + +`app.jar (ALL-UNNAMED)` is the path to the jar file, with the module name in +parentheses behind it. Since in this case the jar file appears on the class +path, `ALL-UNNAMED` is printed to indicate the unnamed module. The second line +of the output, `foo.Main`, indicates that methods using native functionalities +were found in the `foo.Main` class. The next line: + +``` + foo.Main::main(String[])void references restricted methods: +``` + +Indicates that the `main(String[])` method in the `foo.Main` class references +a restricted method, which is listed on the following line as: + +``` + java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment +``` + +Lastly, the text: + +``` + foo.Main::nativeMethod()void is a native method declaration +``` + +Indicates that the `foo.Main` class contains a declaration of a `native` +method named `nativeMethod`. + +If we add `--print-native-access` to the example command line, we instead +get a list of the names of modules that contain accesses to native +functionalities: + +``` +$ jnativescan --class-path app.jar --print-native-access +ALL-UNNAMED +``` + +In this case the output consists of just `ALL-UNNAMED`, which indicates +a jar file on the class path, that is, in the unnamed module, contains an access +to native functionalities. diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java index c17c46237b6..d49e718db60 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java @@ -59,13 +59,6 @@ public class VirtualMachineManagerImpl implements VirtualMachineManagerService { private static VirtualMachineManagerImpl vmm; public static VirtualMachineManager virtualMachineManager() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - JDIPermission vmmPermission = - new JDIPermission("virtualMachineManager"); - sm.checkPermission(vmmPermission); - } synchronized (lock) { if (vmm == null) { vmm = new VirtualMachineManagerImpl(); diff --git a/src/jdk.jdi/share/man/jdb.1 b/src/jdk.jdi/share/man/jdb.1 deleted file mode 100644 index 88097ffeae4..00000000000 --- a/src/jdk.jdi/share/man/jdb.1 +++ /dev/null @@ -1,277 +0,0 @@ -.\" Copyright (c) 1995, 2023, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JDB" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jdb - find and fix bugs in Java platform programs -.SH SYNOPSIS -.PP -\f[V]jdb\f[R] [\f[I]options\f[R]] [\f[I]classname\f[R]] -[\f[I]arguments\f[R]] -.TP -\f[I]options\f[R] -This represents the \f[V]jdb\f[R] command-line options. -See \f[B]Options for the jdb command\f[R]. -.TP -\f[I]classname\f[R] -This represents the name of the main class to debug. -.TP -\f[I]arguments\f[R] -This represents the arguments that are passed to the \f[V]main()\f[R] -method of the class. -.SH DESCRIPTION -.PP -The Java Debugger (JDB) is a simple command-line debugger for Java -classes. -The \f[V]jdb\f[R] command and its options call the JDB. -The \f[V]jdb\f[R] command demonstrates the Java Platform Debugger -Architecture and provides inspection and debugging of a local or remote -JVM. -.SH START A JDB SESSION -.PP -There are many ways to start a JDB session. -The most frequently used way is to have the JDB launch a new JVM with -the main class of the application to be debugged. -Do this by substituting the \f[V]jdb\f[R] command for the \f[V]java\f[R] -command in the command line. -For example, if your application\[aq]s main class is \f[V]MyClass\f[R], -then use the following command to debug it under the JDB: -.RS -.PP -\f[V]jdb MyClass\f[R] -.RE -.PP -When started this way, the \f[V]jdb\f[R] command calls a second JVM with -the specified parameters, loads the specified class, and stops the JVM -before executing that class\[aq]s first instruction. -.PP -Another way to use the \f[V]jdb\f[R] command is by attaching it to a JVM -that\[aq]s already running. -Syntax for starting a JVM to which the \f[V]jdb\f[R] command attaches -when the JVM is running is as follows. -This loads in-process debugging libraries and specifies the kind of -connection to be made. -.RS -.PP -\f[V]java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n MyClass\f[R] -.RE -.PP -You can then attach the \f[V]jdb\f[R] command to the JVM with the -following command: -.RS -.PP -\f[V]jdb -attach 8000\f[R] -.RE -.PP -8000 is the address of the running JVM. -.PP -The \f[V]MyClass\f[R] argument isn\[aq]t specified in the \f[V]jdb\f[R] -command line in this case because the \f[V]jdb\f[R] command is -connecting to an existing JVM instead of launching a new JVM. -.PP -There are many other ways to connect the debugger to a JVM, and all of -them are supported by the \f[V]jdb\f[R] command. -The Java Platform Debugger Architecture has additional documentation on -these connection options. -.SH BREAKPOINTS -.PP -Breakpoints can be set in the JDB at line numbers or at the first -instruction of a method, for example: -.IP \[bu] 2 -The command \f[V]stop at MyClass:22\f[R] sets a breakpoint at the first -instruction for line 22 of the source file containing \f[V]MyClass\f[R]. -.IP \[bu] 2 -The command \f[V]stop in java.lang.String.length\f[R] sets a breakpoint -at the beginning of the method \f[V]java.lang.String.length\f[R]. -.IP \[bu] 2 -The command \f[V]stop in MyClass.<clinit>\f[R] uses \f[V]<clinit>\f[R] -to identify the static initialization code for \f[V]MyClass\f[R]. -.PP -When a method is overloaded, you must also specify its argument types so -that the proper method can be selected for a breakpoint. -For example, \f[V]MyClass.myMethod(int,java.lang.String)\f[R] or -\f[V]MyClass.myMethod()\f[R]. -.PP -The \f[V]clear\f[R] command removes breakpoints using the following -syntax: \f[V]clear MyClass:45\f[R]. -Using the \f[V]clear\f[R] or \f[V]stop\f[R] command with no argument -displays a list of all breakpoints currently set. -The \f[V]cont\f[R] command continues execution. -.SH STEPPING -.PP -The \f[V]step\f[R] command advances execution to the next line whether -it\[aq]s in the current stack frame or a called method. -The \f[V]next\f[R] command advances execution to the next line in the -current stack frame. -.SH EXCEPTIONS -.PP -When an exception occurs for which there isn\[aq]t a \f[V]catch\f[R] -statement anywhere in the throwing thread\[aq]s call stack, the JVM -typically prints an exception trace and exits. -When running under the JDB, however, control returns to the JDB at the -offending throw. -You can then use the \f[V]jdb\f[R] command to diagnose the cause of the -exception. -.PP -Use the \f[V]catch\f[R] command to cause the debugged application to -stop at other thrown exceptions, for example: -\f[V]catch java.io.FileNotFoundException\f[R] or \f[V]catch\f[R] -\f[V]mypackage.BigTroubleException\f[R]. -Any exception that\[aq]s an instance of the specified class or subclass -stops the application at the point where the exception is thrown. -.PP -The \f[V]ignore\f[R] command negates the effect of an earlier -\f[V]catch\f[R] command. -The \f[V]ignore\f[R] command doesn\[aq]t cause the debugged JVM to -ignore specific exceptions, but only to ignore the debugger. -.SH OPTIONS FOR THE JDB COMMAND -.PP -When you use the \f[V]jdb\f[R] command instead of the \f[V]java\f[R] -command on the command line, the \f[V]jdb\f[R] command accepts many of -the same options as the \f[V]java\f[R] command. -.PP -The following options are accepted by the \f[V]jdb\f[R] command: -.TP -\f[V]-help\f[R] -Displays a help message. -.TP -\f[V]-sourcepath\f[R] \f[I]dir1\f[R]\f[V]:\f[R]\f[I]dir2\f[R]\f[V]:\f[R]... -Uses the specified path to search for source files in the specified -path. -If this option is not specified, then use the default path of dot -(\f[V].\f[R]). -.TP -\f[V]-attach\f[R] \f[I]address\f[R] -Attaches the debugger to a running JVM with the default connection -mechanism. -.TP -\f[V]-listen\f[R] \f[I]address\f[R] -Waits for a running JVM to connect to the specified address with a -standard connector. -.TP -\f[V]-listenany\f[R] -Waits for a running JVM to connect at any available address using a -standard connector. -.TP -\f[V]-launch\f[R] -Starts the debugged application immediately upon startup of the -\f[V]jdb\f[R] command. -The \f[V]-launch\f[R] option removes the need for the \f[V]run\f[R] -command. -The debugged application is launched and then stopped just before the -initial application class is loaded. -At that point, you can set any necessary breakpoints and use the -\f[V]cont\f[R] command to continue execution. -.TP -\f[V]-listconnectors\f[R] -Lists the connectors available in this JVM. -.TP -\f[V]-connect\f[R] \f[I]connector-name\f[R]\f[V]:\f[R]\f[I]name1\f[R]\f[V]=\f[R]\f[I]value1\f[R].... -Connects to the target JVM with the named connector and listed argument -values. -.TP -\f[V]-dbgtrace\f[R] [\f[I]flags\f[R]] -Prints information for debugging the \f[V]jdb\f[R] command. -.TP -\f[V]-tclient\f[R] -Runs the application in the Java HotSpot VM client. -.TP -\f[V]-trackallthreads\f[R] -Track all threads as they are created, including virtual threads. -See \f[B]Working With Virtual Threads\f[R] below. -.TP -\f[V]-tserver\f[R] -Runs the application in the Java HotSpot VM server. -.TP -\f[V]-J\f[R]\f[I]option\f[R] -Passes \f[I]option\f[R] to the JDB JVM, where option is one of the -options described on the reference page for the Java application -launcher. -For example, \f[V]-J-Xms48m\f[R] sets the startup memory to 48 MB. -See \f[I]Overview of Java Options\f[R] in \f[B]java\f[R]. -.PP -The following options are forwarded to the debuggee process: -.TP -\f[V]-R\f[R]\f[I]option\f[R] -Passes \f[I]option\f[R] to the debuggee JVM, where option is one of the -options described on the reference page for the Java application -launcher. -For example, \f[V]-R-Xms48m\f[R] sets the startup memory to 48 MB. -See \f[I]Overview of Java Options\f[R] in \f[B]java\f[R]. -.TP -\f[V]-v\f[R] or \f[V]-verbose\f[R][\f[V]:\f[R]\f[I]class\f[R]|\f[V]gc\f[R]|\f[V]jni\f[R]] -Turns on the verbose mode. -.TP -\f[V]-D\f[R]\f[I]name\f[R]\f[V]=\f[R]\f[I]value\f[R] -Sets a system property. -.TP -\f[V]-classpath\f[R] \f[I]dir\f[R] -Lists directories separated by colons in which to look for classes. -.TP -\f[V]-X\f[R] \f[I]option\f[R] -A nonstandard target JVM option. -.PP -Other options are supported to provide alternate mechanisms for -connecting the debugger to the JVM that it\[aq]s to debug. -.SH WORKING WITH VIRTUAL THREADS -.PP -Often virtual theads are created in such large numbers and frequency -that they can overwhelm a debugger. -For this reason by default JDB does not keep track of virtual threads as -they are created. -It will only keep track of virtual threads that an event has arrived on, -such as a breakpoint event. -The \f[V]-trackallthreads\f[R] option can be used to make JDB track all -virtual threads as they are created. -.PP -When JDB first connects, it requests a list of all known threads from -the Debug Agent. -By default the debug agent does not return any virtual threads in this -list, once again because the list could be so large that it overwhelms -the debugger. -The Debug Agent has an \f[V]includevirtualthreads\f[R] option that can -be enabled to change this behavior so all known virtual threads will be -included in the list. -The JDB \f[V]-trackallthreads\f[R] option will cause JDB to -automatically enable the Debug Agent\[aq]s -\f[V]includevirtualthreads\f[R] option when JDB launches an application -to debug. -However, keep in mind that the Debug Agent may not know about any -virtual threads that were created before JDB attached to the debugged -application. diff --git a/src/jdk.jdi/share/man/jdb.md b/src/jdk.jdi/share/man/jdb.md new file mode 100644 index 00000000000..e163cbf5e23 --- /dev/null +++ b/src/jdk.jdi/share/man/jdb.md @@ -0,0 +1,237 @@ +--- +# Copyright (c) 1995, 2023, 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. +# + +title: 'JDB(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jdb - find and fix bugs in Java platform programs + +## Synopsis + +`jdb` \[*options*\] \[*classname*\] \[*arguments*\] + +*options* +: This represents the `jdb` command-line options. See [Options for the jdb + command]. + +*classname* +: This represents the name of the main class to debug. + +*arguments* +: This represents the arguments that are passed to the `main()` method of the + class. + +## Description + +The Java Debugger (JDB) is a simple command-line debugger for Java classes. The +`jdb` command and its options call the JDB. The `jdb` command demonstrates the +Java Platform Debugger Architecture and provides inspection and debugging of a +local or remote JVM. + +## Start a JDB Session + +There are many ways to start a JDB session. The most frequently used way is to +have the JDB launch a new JVM with the main class of the application to be +debugged. Do this by substituting the `jdb` command for the `java` command in +the command line. For example, if your application's main class is `MyClass`, +then use the following command to debug it under the JDB: + +> `jdb MyClass` + +When started this way, the `jdb` command calls a second JVM with the specified +parameters, loads the specified class, and stops the JVM before executing that +class's first instruction. + +Another way to use the `jdb` command is by attaching it to a JVM that's already +running. Syntax for starting a JVM to which the `jdb` command attaches when the +JVM is running is as follows. This loads in-process debugging libraries and +specifies the kind of connection to be made. + +> `java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n MyClass` + +You can then attach the `jdb` command to the JVM with the following command: + +> `jdb -attach 8000` + +8000 is the address of the running JVM. + +The `MyClass` argument isn't specified in the `jdb` command line in this case +because the `jdb` command is connecting to an existing JVM instead of launching +a new JVM. + +There are many other ways to connect the debugger to a JVM, and all of them are +supported by the `jdb` command. The Java Platform Debugger Architecture has +additional documentation on these connection options. + +## Breakpoints + +Breakpoints can be set in the JDB at line numbers or at the first instruction +of a method, for example: + +- The command `stop at MyClass:22` sets a breakpoint at the first instruction + for line 22 of the source file containing `MyClass`. + +- The command `stop in java.lang.String.length` sets a breakpoint at the + beginning of the method `java.lang.String.length`. + +- The command `stop in MyClass.<clinit>` uses `<clinit>` to identify the + static initialization code for `MyClass`. + +When a method is overloaded, you must also specify its argument types so that +the proper method can be selected for a breakpoint. For example, +`MyClass.myMethod(int,java.lang.String)` or `MyClass.myMethod()`. + +The `clear` command removes breakpoints using the following syntax: +`clear MyClass:45`. Using the `clear` or `stop` command with no argument +displays a list of all breakpoints currently set. The `cont` command continues +execution. + +## Stepping + +The `step` command advances execution to the next line whether it's in the +current stack frame or a called method. The `next` command advances execution +to the next line in the current stack frame. + +## Exceptions + +When an exception occurs for which there isn't a `catch` statement anywhere in +the throwing thread's call stack, the JVM typically prints an exception trace +and exits. When running under the JDB, however, control returns to the JDB at +the offending throw. You can then use the `jdb` command to diagnose the cause +of the exception. + +Use the `catch` command to cause the debugged application to stop at other +thrown exceptions, for example: `catch java.io.FileNotFoundException` or +`catch` `mypackage.BigTroubleException`. Any exception that's an instance of +the specified class or subclass stops the application at the point where the +exception is thrown. + +The `ignore` command negates the effect of an earlier `catch` command. The +`ignore` command doesn't cause the debugged JVM to ignore specific exceptions, +but only to ignore the debugger. + +## Options for the jdb command + +When you use the `jdb` command instead of the `java` command on the command +line, the `jdb` command accepts many of the same options as the `java` +command. + +The following options are accepted by the `jdb` command: + +`-help` +: Displays a help message. + +`-sourcepath` *dir1*`:`*dir2*`:`... +: Uses the specified path to search for source files in the specified path. + If this option is not specified, then use the default path of dot (`.`). + +`-attach` *address* +: Attaches the debugger to a running JVM with the default connection + mechanism. + +`-listen` *address* +: Waits for a running JVM to connect to the specified address with a standard + connector. + +`-listenany` +: Waits for a running JVM to connect at any available address using a + standard connector. + +`-launch` +: Starts the debugged application immediately upon startup of the `jdb` + command. The `-launch` option removes the need for the `run` command. The + debugged application is launched and then stopped just before the initial + application class is loaded. At that point, you can set any necessary + breakpoints and use the `cont` command to continue execution. + +`-listconnectors` +: Lists the connectors available in this JVM. + +`-connect` *connector-name*`:`*name1*`=`*value1*.... +: Connects to the target JVM with the named connector and listed argument + values. + +`-dbgtrace` \[*flags*\] +: Prints information for debugging the `jdb` command. + +`-tclient` +: Runs the application in the Java HotSpot VM client. + +`-trackallthreads` +: Track all threads as they are created, including virtual threads. + See [Working With Virtual Threads](#working-with-virtual-threads) below. + +`-tserver` +: Runs the application in the Java HotSpot VM server. + +`-J`*option* +: Passes *option* to the JDB JVM, where option is one of the options described on + the reference page for the Java application launcher. For example, + `-J-Xms48m` sets the startup memory to 48 MB. See *Overview of Java + Options* in [java](java.html). + +The following options are forwarded to the debuggee process: + +`-R`*option* +: Passes *option* to the debuggee JVM, where option is one of the options described on + the reference page for the Java application launcher. For example, + `-R-Xms48m` sets the startup memory to 48 MB. See *Overview of Java + Options* in [java](java.html). + +`-v` or `-verbose`\[`:`*class*\|`gc`\|`jni`\] +: Turns on the verbose mode. + +`-D`*name*`=`*value* +: Sets a system property. + +`-classpath` *dir* +: Lists directories separated by colons in which to look for classes. + +`-X` *option* +: A nonstandard target JVM option. + +Other options are supported to provide alternate mechanisms for connecting the +debugger to the JVM that it's to debug. + +## Working With Virtual Threads + +Often virtual theads are created in such large numbers and frequency that they +can overwhelm a debugger. For this reason by default JDB does not keep track +of virtual threads as they are created. It will only keep track of virtual +threads that an event has arrived on, such as a breakpoint event. The +`-trackallthreads` option can be used to make JDB track all virtual threads +as they are created. + +When JDB first connects, it requests a list of all known threads from the Debug Agent. +By default the debug agent does not return any virtual threads in this list, once +again because the list could be so large that it overwhelms the debugger. The +Debug Agent has an `includevirtualthreads` option that can be enabled to change +this behavior so all known virtual threads will be included in the list. The +JDB `-trackallthreads` option will cause JDB to automatically enable the Debug Agent's +`includevirtualthreads` option when JDB launches an application to debug. However, keep in mind +that the Debug Agent may not know about any virtual threads that were created +before JDB attached to the debugged application. diff --git a/src/jdk.jfr/share/man/jfr.1 b/src/jdk.jfr/share/man/jfr.1 deleted file mode 100644 index 71a487f558e..00000000000 --- a/src/jdk.jfr/share/man/jfr.1 +++ /dev/null @@ -1,438 +0,0 @@ -.\" Copyright (c) 2019, 2023, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JFR" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jfr - print and manipulate Flight Recorder files -.SH SYNOPSIS -.PP -To print the contents of a flight recording to standard out: -.PP -\f[V]jfr\f[R] \f[V]print\f[R] [\f[I]options\f[R]] \f[I]file\f[R] -.PP -To display aggregated event data on standard out: -.PP -\f[V]jfr\f[R] \f[V]view\f[R] [\f[I]options\f[R]] \f[I]file\f[R] -.PP -To configure a .jfc settings file: -.PP -\f[V]jfr\f[R] \f[V]configure\f[R] [\f[I]options\f[R]] -.PP -To print metadata information about flight recording events: -.PP -\f[V]jfr\f[R] \f[V]metadata\f[R] [\f[I]file\f[R]] -.PP -To view the summary statistics for a flight recording file: -.PP -\f[V]jfr\f[R] \f[V]summary\f[R] \f[I]file\f[R] -.PP -To remove events from a flight recording file: -.PP -\f[V]jfr\f[R] \f[V]scrub\f[R] [\f[I]options\f[R]] \f[I]file\f[R] -.PP -To assemble chunk files into a flight recording file: -.PP -\f[V]jfr\f[R] \f[V]assemble\f[R] \f[I]repository\f[R] \f[I]file\f[R] -.PP -To disassemble a flight recording file into chunk files: -.PP -\f[V]jfr\f[R] \f[V]disassmble\f[R] [\f[I]options\f[R]] \f[I]file\f[R] -.TP -\f[I]options\f[R] -Optional: Specifies command-line options separated by spaces. -See the individual subcomponent sections for descriptions of the -available options. -.TP -\f[I]file\f[R] -Specifies the name of the target flight recording file (\f[V].jfr\f[R]). -.TP -\f[I]repository\f[R] -Specifies the location of the chunk files which are to be assembled into -a flight recording. -.SH DESCRIPTION -.PP -The \f[V]jfr\f[R] command provides a tool for interacting with flight -recorder files (\f[V].jfr\f[R]). -The main function is to filter, summarize and output flight recording -files into human readable format. -There is also support for scrubbing, merging and splitting recording -files. -.PP -Flight recording files are created and saved as binary formatted files. -Having a tool that can extract the contents from a flight recording and -manipulate the contents and translate them into human readable format -helps developers to debug performance issues with Java applications. -.SS Subcommands -.PP -The \f[V]jfr\f[R] command has several subcommands: -.IP \[bu] 2 -\f[V]print\f[R] -.IP \[bu] 2 -\f[V]view\f[R] -.IP \[bu] 2 -\f[V]configure\f[R] -.IP \[bu] 2 -\f[V]metadata\f[R] -.IP \[bu] 2 -\f[V]summary\f[R] -.IP \[bu] 2 -\f[V]scrub\f[R] -.IP \[bu] 2 -\f[V]assemble\f[R] -.IP \[bu] 2 -\f[V]disassemble\f[R] -.SS \f[V]jfr print\f[R] subcommand -.PP -Use \f[V]jfr print\f[R] to print the contents of a flight recording file -to standard out. -.PP -The syntax is: -.PP -\f[V]jfr print\f[R] [\f[V]--xml\f[R]|\f[V]--json\f[R]] -[\f[V]--categories\f[R] <\f[I]filters\f[R]>] [\f[V]--events\f[R] -<\f[I]filters\f[R]>] [\f[V]--stack-depth\f[R] <\f[I]depth\f[R]>] -<\f[I]file\f[R]> -.PP -where: -.TP -\f[V]--xml\f[R] -Print the recording in XML format. -.TP -\f[V]--json\f[R] -Print the recording in JSON format. -.TP -\f[V]--categories\f[R] <\f[I]filters\f[R]> -Select events matching a category name. -The filter is a comma-separated list of names, simple and/or qualified, -and/or quoted glob patterns. -.TP -\f[V]--events\f[R] <\f[I]filters\f[R]> -Select events matching an event name. -The filter is a comma-separated list of names, simple and/or qualified, -and/or quoted glob patterns. -.TP -\f[V]--stack-depth\f[R] <\f[I]depth\f[R]> -Number of frames in stack traces, by default 5. -.TP -<\f[I]file\f[R]> -Location of the recording file (\f[V].jfr\f[R]) -.PP -The default format for printing the contents of the flight recording -file is human readable form unless either \f[V]xml\f[R] or -\f[V]json\f[R] is specified. -These options provide machine-readable output that can be further parsed -or processed by user created scripts. -.PP -Use \f[V]jfr --help print\f[R] to see example usage of filters. -.PP -To reduce the amount of data displayed, it is possible to filter out -events or categories of events. -The filter operates on the symbolic name of an event, set by using the -\f[V]\[at]Name\f[R] annotation, or the category name, set by using the -\f[V]\[at]Category\f[R] annotation. -If multiple filters are used, events from both filters will be included. -If no filter is used, all the events will be printed. -If a combination of a category filter and event filter is used, the -selected events will be the union of the two filters. -.PP -For example, to show all GC events and the CPULoad event, the following -command could be used: -.PP -\f[V]jfr print --categories GC --events CPULoad recording.jfr\f[R] -.PP -Event values are formatted according to the content types that are being -used. -For example, a field with the \f[V]jdk.jfr.Percentage\f[R] annotation -that has the value 0.52 is formatted as 52%. -.PP -Stack traces are by default truncated to 5 frames, but the number can be -increased/decreased using the \f[V]--stack-depth\f[R] command-line -option. -.SS \f[V]jfr view\f[R] subcommand -.PP -Use \f[V]jfr view\f[R] to aggregate and display event data on standard -out. -.PP -The syntax is: -.PP -\f[V]jfr view\f[R] [\f[V]--verbose\f[R]] [\f[V]--width\f[R] -<\f[I]integer\f[R]>] [\f[V]--truncate\f[R] <\f[I]mode\f[R]>] -[\f[V]--cell-height\f[R] <\f[I]integer\f[R]>] <\f[I]view\f[R]> -<\f[I]file\f[R]> -.PP -where: -.TP -\f[V]--verbose\f[R] -Displays the query that makes up the view. -.TP -\f[V]--width\f[R] <\f[I]integer\f[R]> -The width of the view in characters. -Default value depends on the view. -.TP -\f[V]--truncate\f[R] <\f[I]mode\f[R]> -How to truncate content that exceeds space in a table cell. -Mode can be \[aq]beginning\[aq] or \[aq]end\[aq]. -Default value is \[aq]end\[aq]. -.TP -\f[V]--cell-height\f[R] <\f[I]integer\f[R]> -Maximum number of rows in a table cell. -Default value depends on the view. -.TP -<\f[I]view\f[R]> -Name of the view or event type to display. -Use \f[V]jfr --help view\f[R] to see a list of available views. -.TP -<\f[I]file\f[R]> -Location of the recording file (.jfr) -.PP -The <\f[I]view\f[R]> parameter can be an event type name. -Use the \f[V]jfr view types <file>\f[R] to see a list. -To display all views, use \f[V]jfr view all-views <file>\f[R]. -To display all events, use \f[V]jfr view all-events <file>\f[R]. -.SS \f[V]jfr configure\f[R] subcommand -.PP -Use \f[V]jfr configure\f[R] to configure a .jfc settings file. -.PP -The syntax is: -.PP -\f[V]jfr configure\f[R] [--interactive] [--verbose] [--input ] [--output -] [option=value]* [event-setting=value]* -.TP -\f[V]--interactive\f[R] -Interactive mode where the configuration is determined by a set of -questions. -.TP -\f[V]--verbose\f[R] -Displays the modified settings. -.TP -\f[V]--input\f[R] <\f[I]files\f[R]> -A comma-separated list of .jfc files from which the new configuration is -based. -If no file is specified, the default file in the JDK is used -(default.jfc). -If \[aq]none\[aq] is specified, the new configuration starts empty. -.TP -\f[V]--output\f[R] <\f[I]file\f[R]> -The filename of the generated output file. -If not specified, the filename custom.jfc will be used. -.TP -\f[I]option=value\f[R] -The option value to modify. -To see available options, use \f[V]jfr help configure\f[R] -.TP -\f[I]event-setting=value\f[R] -The event setting value to modify. -Use the form: -<\f[I]event-name\f[R]>#<\f[I]setting-name\f[R]>=<\f[I]value\f[R]> To add -a new event setting, prefix the event name with \[aq]+\[aq]. -.PP -The whitespace delimiter can be omitted for timespan values, i.e. -20ms. -For more information about the settings syntax, see Javadoc of the -jdk.jfr package. -.SS \f[V]jfr metadata\f[R] subcommand -.PP -Use \f[V]jfr metadata\f[R] to display information about events, such as -event names, categories and field layout within a flight recording file. -.PP -The syntax is: -.PP -\f[V]jfr metadata\f[R] [--categories ] [--events ] [] -.TP -\f[V]--categories\f[R] <\f[I]filter\f[R]> -Select events matching a category name. -The filter is a comma-separated list of names, simple and/or qualified, -and/or quoted glob patterns. -.TP -\f[V]--events\f[R] <\f[I]filter\f[R]> -Select events matching an event name. -The filter is a comma-separated list of names, simple and/or qualified, -and/or quoted glob patterns. -.TP -<\f[I]file\f[R]> -Location of the recording file (.jfr) -.PP -If the parameter is omitted, metadata from the JDK where the -\[aq]jfr\[aq] tool is located will be used. -.SS \f[V]jfr summary\f[R] subcommand -.PP -Use \f[V]jfr summary\f[R] to print statistics for a recording. -For example, a summary can illustrate the number of recorded events and -how much disk space they used. -This is useful for troubleshooting and understanding the impact of event -settings. -.PP -The syntax is: -.PP -\f[V]jfr summary\f[R] <\f[I]file\f[R]> -.PP -where: -.TP -<\f[I]file\f[R]> -Location of the flight recording file (\f[V].jfr\f[R]) -.SS \f[V]jfr scrub\f[R] subcommand -.PP -Use \f[V]jfr scrub\f[R] to remove sensitive contents from a file or to -reduce its size. -.PP -The syntax is: -.PP -\f[V]jfr scrub\f[R] [--include-events <\f[I]filter\f[R]>] -[--exclude-events <\f[I]filter\f[R]>] [--include-categories -<\f[I]filter\f[R]>] [--exclude-categories <\f[I]filter\f[R]>] -[--include-threads <\f[I]filter\f[R]>] [--exclude-threads -<\f[I]filter\f[R]>] <\f[I]input-file\f[R]> [<\f[I]output-file\f[R]>] -.TP -\f[V]--include-events\f[R] <\f[I]filter\f[R]> -Select events matching an event name. -.TP -\f[V]--exclude-events\f[R] <\f[I]filter\f[R]> -Exclude events matching an event name. -.TP -\f[V]--include-categories\f[R] <\f[I]filter\f[R]> -Select events matching a category name. -.TP -\f[V]--exclude-categories\f[R] <\f[I]filter\f[R]> -Exclude events matching a category name. -.TP -\f[V]--include-threads\f[R] <\f[I]filter\f[R]> -Select events matching a thread name. -.TP -\f[V]--exclude-threads\f[R] <\f[I]filter\f[R]> -Exclude events matching a thread name. -.TP -<\f[I]input-file\f[R]> -The input file to read events from. -.TP -<\f[I]output-file\f[R]> -The output file to write filter events to. -If no file is specified, it will be written to the same path as the -input file, but with \[dq]-scrubbed\[dq] appended to the filename. -.PP -The filter is a comma-separated list of names, simple and/or qualified, -and/or quoted glob patterns. -If multiple filters are used, they are applied in the specified order. -.SS \f[V]jfr assemble\f[R] subcommand -.PP -Use jfr \f[V]assemble\f[R] to assemble chunk files into a recording -file. -.PP -The syntax is: -.PP -\f[V]jfr assemble\f[R] <\f[I]repository\f[R]> <\f[I]file\f[R]> -.PP -where: -.TP -<\f[I]repository\f[R]> -Directory where the repository containing chunk files is located. -.TP -<\f[I]file\f[R]> -Location of the flight recording file (\f[V].jfr\f[R]). -.PP -Flight recording information is written in chunks. -A chunk contains all of the information necessary for parsing. -A chunk typically contains events useful for troubleshooting. -If a JVM should crash, these chunks can be recovered and used to create -a flight recording file using this \f[V]jfr assemble\f[R] command. -These chunk files are concatenated in chronological order and chunk -files that are not finished (.part) are excluded. -.SS \f[V]jfr disassemble\f[R] subcommand -.PP -Use \f[V]jfr disassemble\f[R] to decompose a flight recording file into -its chunk file pieces. -.PP -The syntax is: -.PP -\f[V]jfr disassemble\f[R] [\f[V]--max-chunks\f[R] <\f[I]chunks\f[R]>] -[\f[V]--output\f[R] <\f[I]directory\f[R]>] <\f[I]file\f[R]> -.PP -where: -.TP -\f[V]--output\f[R] <\f[I]directory\f[R]> -The location to write the disassembled file, by default the current -directory -.TP -\f[V]--max-chunks\f[R] <\f[I]chunks\f[R]> -Maximum number of chunks per file, by default 5. -The chunk size varies, but is typically around 15 MB. -.TP -\f[V]--max-size\f[R] <\f[I]size\f[R]> -Maximum number of bytes per file. -.TP -<\f[I]file\f[R]> -Location of the flight recording file (\f[V].jfr\f[R]) -.PP -This function can be useful for repairing a broken file by removing the -faulty chunk. -It can also be used to reduce the size of a file that is too large to -transfer. -The resulting chunk files are named \f[V]myfile_1.jfr\f[R], -\f[V]myfile_2.jfr\f[R], etc. -If needed, the resulting file names will be padded with zeros to -preserve chronological order. -For example, the chunk file name is \f[V]myfile_001.jfr\f[R] if the -recording consists of more than 100 chunks. -.SS jfr version and help subcommands -.PP -Use \f[V]jfr --version\f[R] or \f[V]jfr version\f[R] to view the version -string information for this jfr command. -.PP -To get help on any of the jfr subcommands, use: -.PP -\f[V]jfr <--help|help>\f[R] [\f[I]subcommand\f[R]] -.PP -where: -.PP -[\f[I]subcommand\f[R]] is any of: -.IP \[bu] 2 -\f[V]print\f[R] -.IP \[bu] 2 -\f[V]view\f[R] -.IP \[bu] 2 -\f[V]configure\f[R] -.IP \[bu] 2 -\f[V]metadata\f[R] -.IP \[bu] 2 -\f[V]summary\f[R] -.IP \[bu] 2 -\f[V]scrub\f[R] -.IP \[bu] 2 -\f[V]assemble\f[R] -.IP \[bu] 2 -\f[V]disassemble\f[R] diff --git a/src/jdk.jfr/share/man/jfr.md b/src/jdk.jfr/share/man/jfr.md new file mode 100644 index 00000000000..f942b97dd99 --- /dev/null +++ b/src/jdk.jfr/share/man/jfr.md @@ -0,0 +1,399 @@ +--- +# Copyright (c) 2019, 2023, 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. +# + +title: 'JFR(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jfr - print and manipulate Flight Recorder files + +## Synopsis + +To print the contents of a flight recording to standard out: + +`jfr` `print` \[*options*\] *file* + +To display aggregated event data on standard out: + +`jfr` `view` \[*options*\] *file* + +To configure a .jfc settings file: + +`jfr` `configure` \[*options*\] + +To print metadata information about flight recording events: + +`jfr` `metadata` \[*file*\] + +To view the summary statistics for a flight recording file: + +`jfr` `summary` *file* + +To remove events from a flight recording file: + +`jfr` `scrub` \[*options*\] *file* + +To assemble chunk files into a flight recording file: + +`jfr` `assemble` *repository* *file* + +To disassemble a flight recording file into chunk files: + +`jfr` `disassmble` \[*options*\] *file* + +*options* +: Optional: Specifies command-line options separated by spaces. See the +individual subcomponent sections for descriptions of the available options. + +*file* +: Specifies the name of the target flight recording file (`.jfr`). + +*repository* +: Specifies the location of the chunk files which are to be assembled into +a flight recording. + +## Description + +The `jfr` command provides a tool for interacting with flight recorder files +(`.jfr`). The main function is to filter, summarize and output flight +recording files into human readable format. There is also support for scrubbing, +merging and splitting recording files. + +Flight recording files are created and saved as binary formatted files. Having +a tool that can extract the contents from a flight recording and manipulate the +contents and translate them into human readable format helps developers to debug +performance issues with Java applications. + +### Subcommands + +The `jfr` command has several subcommands: + +- `print` +- `view` +- `configure` +- `metadata` +- `summary` +- `scrub` +- `assemble` +- `disassemble` + +#### `jfr print` subcommand + +Use `jfr print` to print the contents of a flight recording file to standard out. + +The syntax is: + +`jfr print` \[`--xml`|`--json`\] + \[`--categories` <*filters*>\] + \[`--events` <*filters*>\] + \[`--stack-depth` <*depth*>\] + <*file*> + +where: + +<a id="print-option-xml">`--xml`</a> +: Print the recording in XML format. + +<a id="print-option-json">`--json`</a> +: Print the recording in JSON format. + +<a id="print-option-categories">`--categories` <*filters*></a> +: Select events matching a category name. +The filter is a comma-separated list of names, +simple and/or qualified, and/or quoted glob patterns. + +<a id="print-option-events">`--events` <*filters*></a> +: Select events matching an event name. +The filter is a comma-separated list of names, +simple and/or qualified, and/or quoted glob patterns. + +<a id="print-option-stack-depth">`--stack-depth` <*depth*></a> +: Number of frames in stack traces, by default 5. + +<a id="print-option-file"><*file*></a> +: Location of the recording file (`.jfr`) + +The default format for printing the contents of the flight recording file is human +readable form unless either `xml` or `json` is specified. These options provide +machine-readable output that can be further parsed or processed by user created scripts. + +Use `jfr --help print` to see example usage of filters. + +To reduce the amount of data displayed, it is possible to filter out events or +categories of events. The filter operates on the symbolic name of an event, +set by using the `@Name` annotation, or the category name, set by using +the `@Category` annotation. If multiple filters are used, events from both +filters will be included. If no filter is used, all the events will be printed. +If a combination of a category filter and event filter is used, the selected events +will be the union of the two filters. + +For example, to show all GC events and the CPULoad event, the following command could be used: + +`jfr print --categories GC --events CPULoad recording.jfr` + +Event values are formatted according to the content types that are being used. +For example, a field with the `jdk.jfr.Percentage` annotation that has the value 0.52 +is formatted as 52%. + +Stack traces are by default truncated to 5 frames, but the number can be +increased/decreased using the `--stack-depth` command-line option. + +#### `jfr view` subcommand + +Use `jfr view` to aggregate and display event data on standard out. + +The syntax is: + + `jfr view` \[`--verbose`\] + \[`--width` <*integer*>\] + \[`--truncate` <*mode*>\] + \[`--cell-height` <*integer*>\] + <*view*> + <*file*> + +where: + +<a id="view-option-verbose">`--verbose`</a> +: Displays the query that makes up the view. + +<a id="view-option-width">`--width` <*integer*></a> +: The width of the view in characters. Default value depends on the view. + +<a id="view-option-truncate">`--truncate` <*mode*></a> +: How to truncate content that exceeds space in a table cell. +Mode can be 'beginning' or 'end'. Default value is 'end'. + +<a id="view-option-cell-height">`--cell-height` <*integer*></a> +: Maximum number of rows in a table cell. Default value depends on the view. + +<a id="view-option-view"><*view*></a> +: Name of the view or event type to display. Use `jfr --help view` to see a +list of available views. + +<a id="view-option-file"><*file*></a> +: Location of the recording file (.jfr) + +The <*view*> parameter can be an event type name. Use the `jfr view types <file>` +to see a list. To display all views, use `jfr view all-views <file>`. To display +all events, use `jfr view all-events <file>`. + +#### `jfr configure` subcommand + +Use `jfr configure` to configure a .jfc settings file. + +The syntax is: + + `jfr configure` \[--interactive\] \[--verbose\] + \[--input <files>\] [--output <file>\] + \[option=value\]* \[event-setting=value\]* + +<a id="configure-option-interactive">`--interactive`</a> +: Interactive mode where the configuration is determined by a set of questions. + +<a id="configure-option-verbose">`--verbose`</a> +: Displays the modified settings. + +<a id="configure-option-input">`--input` <*files*></a> +: A comma-separated list of .jfc files from which the new configuration is +based. If no file is specified, the default file in the JDK is used +(default.jfc). If 'none' is specified, the new configuration starts empty. + +<a id="configure-option-output">`--output` <*file*></a> +: The filename of the generated output file. If not specified, the filename +custom.jfc will be used. + +<a id="configure-option-value">*option=value*</a> +: The option value to modify. To see available options, +use `jfr help configure` + +<a id="configure-option-event-setting">*event-setting=value*</a> +: The event setting value to modify. Use the form: + <*event-name*>#<*setting-name*>=<*value*> +To add a new event setting, prefix the event name with '+'. + +The whitespace delimiter can be omitted for timespan values, i.e. 20ms. For +more information about the settings syntax, see Javadoc of the jdk.jfr package. + +#### `jfr metadata` subcommand + +Use `jfr metadata` to display information about events, such as event +names, categories and field layout within a flight recording file. + +The syntax is: + +`jfr metadata` \[--categories <filter>\] + \[--events <filter>\] + \[<file>\] + +<a id="metadata-option-categories">`--categories` <*filter*></a> +: Select events matching a category name. The filter is a comma-separated +list of names, simple and/or qualified, and/or quoted glob patterns. + +<a id="metadata-option-events">`--events` <*filter*></a> +: Select events matching an event name. The filter is a comma-separated +list of names, simple and/or qualified, and/or quoted glob patterns. + +<a id="metadata-option-file"><*file*></a> +: Location of the recording file (.jfr) + +If the <file> parameter is omitted, metadata from the JDK where +the 'jfr' tool is located will be used. + +#### `jfr summary` subcommand + +Use `jfr summary` to print statistics for a recording. For example, a summary can +illustrate the number of recorded events and how much disk space they used. This +is useful for troubleshooting and understanding the impact of event settings. + +The syntax is: + +`jfr summary` <*file*> + +where: + +<a id="summary-option-file"><*file*></a> +: Location of the flight recording file (`.jfr`) + +#### `jfr scrub` subcommand + +Use `jfr scrub` to remove sensitive contents from a file or to reduce its size. + +The syntax is: + +`jfr scrub` \[--include-events <*filter*>\] + \[--exclude-events <*filter*>\] + \[--include-categories <*filter*>\] + \[--exclude-categories <*filter*>\] + \[--include-threads <*filter*>\] + \[--exclude-threads <*filter*>\] + <*input-file*> + \[<*output-file*>\] + +<a id="scrub-option-include-events">`--include-events` <*filter*></a> +: Select events matching an event name. + +<a id="scrub-option-exclude-events">`--exclude-events` <*filter*></a> +: Exclude events matching an event name. + +<a id="scrub-option-include-categories">`--include-categories` <*filter*></a> +: Select events matching a category name. + +<a id="scrub-option-exclude-categories">`--exclude-categories` <*filter*></a> +: Exclude events matching a category name. + +<a id="scrub-option-include-threads">`--include-threads` <*filter*></a> +: Select events matching a thread name. + +<a id="scrub-option-exclude-threads">`--exclude-threads` <*filter*></a> +: Exclude events matching a thread name. + +<a id="scrub-option-input-file"><*input-file*></a> +: The input file to read events from. + +<a id="scrub-option-output-file"><*output-file*></a> +: The output file to write filter events to. If no file is specified, +it will be written to the same path as the input file, but with +"-scrubbed" appended to the filename. + +The filter is a comma-separated list of names, simple and/or qualified, +and/or quoted glob patterns. If multiple filters are used, they +are applied in the specified order. + +#### `jfr assemble` subcommand + +Use jfr `assemble` to assemble chunk files into a recording file. + +The syntax is: + +`jfr assemble` <*repository*> + <*file*> + +where: + +<a id="assemble-option-repository"><*repository*></a> +: Directory where the repository containing chunk files is located. + +<a id="assemble-option-file"><*file*></a> +: Location of the flight recording file (`.jfr`). + +Flight recording information is written in chunks. A chunk contains all of the information +necessary for parsing. A chunk typically contains events useful for troubleshooting. +If a JVM should crash, these chunks can be recovered and used to create a flight +recording file using this `jfr assemble` command. These chunk files are concatenated in +chronological order and chunk files that are not finished (.part) are excluded. + +#### `jfr disassemble` subcommand + +Use `jfr disassemble` to decompose a flight recording file into its chunk file pieces. + +The syntax is: + +`jfr disassemble` \[`--max-chunks` <*chunks*>\] + \[`--output` <*directory*>\] + <*file*> + +where: + +<a id="disassemble-option-output">`--output` <*directory*></a> +: The location to write the disassembled file, +by default the current directory + +<a id="disassemble-option-max-chunks">`--max-chunks` <*chunks*></a> +: Maximum number of chunks per file, by default 5. +The chunk size varies, but is typically around 15 MB. + +<a id="disassemble-option-max-size">`--max-size` <*size*></a> +: Maximum number of bytes per file. + +<a id="disassemble-option-file"><*file*></a> +: Location of the flight recording file (`.jfr`) + +This function can be useful for repairing a broken file by removing the faulty chunk. +It can also be used to reduce the size of a file that is too large to transfer. +The resulting chunk files are named `myfile_1.jfr`, `myfile_2.jfr`, etc. If needed, the +resulting file names will be padded with zeros to preserve chronological order. For example, +the chunk file name is `myfile_001.jfr` if the recording consists of more than 100 chunks. + +#### jfr version and help subcommands + +Use `jfr --version` or `jfr version` to view the version string information for this jfr command. + +To get help on any of the jfr subcommands, use: + +`jfr <--help|help>` \[*subcommand*\] + +where: + +\[*subcommand*\] is any of: + +- `print` +- `view` +- `configure` +- `metadata` +- `summary` +- `scrub` +- `assemble` +- `disassemble` diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java index 465a1cae8d9..99029651bfb 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java @@ -242,18 +242,6 @@ public String toString() { } } - /** - * Jlink instance constructor, if a security manager is set, the jlink - * permission is checked. - */ - @SuppressWarnings("removal") - public Jlink() { - if (System.getSecurityManager() != null) { - System.getSecurityManager(). - checkPermission(new JlinkPermission("jlink")); - } - } - /** * Build the image. * diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java index df08b2b54a4..eb743bc4dad 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -44,13 +44,7 @@ public static void main(String... args) throws Exception { * @param args command line arguments * @return an exit code. 0 means success, non-zero means an error occurred. */ - @SuppressWarnings("removal") public static int run(PrintWriter out, PrintWriter err, String... args) { - if (System.getSecurityManager() != null) { - System.getSecurityManager(). - checkPermission(new JlinkPermission("jlink")); - } - JlinkTask t = new JlinkTask(); t.setLog(out, err); return t.run(args); diff --git a/src/jdk.jlink/share/man/jlink.1 b/src/jdk.jlink/share/man/jlink.1 deleted file mode 100644 index 5cadc153a37..00000000000 --- a/src/jdk.jlink/share/man/jlink.1 +++ /dev/null @@ -1,409 +0,0 @@ -.\" Copyright (c) 2017, 2019, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JLINK" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jlink - assemble and optimize a set of modules and their dependencies -into a custom runtime image -.SH SYNOPSIS -.PP -\f[V]jlink\f[R] [\f[I]options\f[R]] \f[V]--module-path\f[R] -\f[I]modulepath\f[R] \f[V]--add-modules\f[R] -\f[I]module\f[R][,\f[I]module\f[R]...] -.TP -\f[I]options\f[R] -Command-line options separated by spaces. -See \f[B]jlink Options\f[R]. -.TP -\f[I]modulepath\f[R] -The path where the \f[V]jlink\f[R] tool discovers observable modules. -These modules can be modular JAR files, JMOD files, or exploded modules. -.TP -\f[I]module\f[R] -The names of the modules to add to the runtime image. -The \f[V]jlink\f[R] tool adds these modules and their transitive -dependencies. -.SH DESCRIPTION -.PP -The \f[V]jlink\f[R] tool links a set of modules, along with their -transitive dependences, to create a custom runtime image. -.PP -\f[B]Note:\f[R] -.PP -Developers are responsible for updating their custom runtime images. -.SH JLINK OPTIONS -.TP -\f[V]--add-modules\f[R] \f[I]mod\f[R][\f[V],\f[R]\f[I]mod\f[R]...] -Adds the named modules, \f[I]mod\f[R], to the default set of root -modules. -The default set of root modules is empty. -.TP -\f[V]--bind-services\f[R] -Link service provider modules and their dependencies. -.TP -\f[V]-c ={0|1|2}\f[R] or \f[V]--compress={0|1|2}\f[R] -Enable compression of resources: -.RS -.IP \[bu] 2 -\f[V]0\f[R]: No compression -.IP \[bu] 2 -\f[V]1\f[R]: Constant string sharing -.IP \[bu] 2 -\f[V]2\f[R]: ZIP -.RE -.TP -\f[V]--disable-plugin\f[R] \f[I]pluginname\f[R] -Disables the specified plug-in. -See \f[B]jlink Plug-ins\f[R] for the list of supported plug-ins. -.TP -\f[V]--endian\f[R] {\f[V]little\f[R]|\f[V]big\f[R]} -Specifies the byte order of the generated image. -The default value is the format of your system\[aq]s architecture. -.TP -\f[V]-h\f[R] or \f[V]--help\f[R] -Prints the help message. -.TP -\f[V]--ignore-signing-information\f[R] -Suppresses a fatal error when signed modular JARs are linked in the -runtime image. -The signature-related files of the signed modular JARs aren\[aq]t copied -to the runtime image. -.TP -\f[V]--launcher\f[R] \f[I]command\f[R]\f[V]=\f[R]\f[I]module\f[R] or \f[V]--launcher\f[R] \f[I]command\f[R]\f[V]=\f[R]\f[I]module\f[R]\f[V]/\f[R]\f[I]main\f[R] -Specifies the launcher command name for the module or the command name -for the module and main class (the module and the main class names are -separated by a slash (\f[V]/\f[R])). -.TP -\f[V]--limit-modules\f[R] \f[I]mod\f[R][\f[V],\f[R]\f[I]mod\f[R]...] -Limits the universe of observable modules to those in the transitive -closure of the named modules, \f[V]mod\f[R], plus the main module, if -any, plus any further modules specified in the \f[V]--add-modules\f[R] -option. -.TP -\f[V]--list-plugins\f[R] -Lists available plug-ins, which you can access through command-line -options; see \f[B]jlink Plug-ins\f[R]. -.TP -\f[V]-p\f[R] or \f[V]--module-path\f[R] \f[I]modulepath\f[R] -Specifies the module path. -.RS -.PP -If this option is not specified, then the default module path is -\f[V]$JAVA_HOME/jmods\f[R]. -This directory contains the \f[V]java.base\f[R] module and the other -standard and JDK modules. -If this option is specified but the \f[V]java.base\f[R] module cannot be -resolved from it, then the \f[V]jlink\f[R] command appends -\f[V]$JAVA_HOME/jmods\f[R] to the module path. -.RE -.TP -\f[V]--no-header-files\f[R] -Excludes header files. -.TP -\f[V]--no-man-pages\f[R] -Excludes man pages. -.TP -\f[V]--output\f[R] \f[I]path\f[R] -Specifies the location of the generated runtime image. -.TP -\f[V]--save-opts\f[R] \f[I]filename\f[R] -Saves \f[V]jlink\f[R] options in the specified file. -.TP -\f[V]--suggest-providers\f[R] [\f[I]name\f[R]\f[V],\f[R] ...] -Suggest providers that implement the given service types from the module -path. -.TP -\f[V]--version\f[R] -Prints version information. -.TP -\f[V]\[at]\f[R]\f[I]filename\f[R] -Reads options from the specified file. -.RS -.PP -An options file is a text file that contains the options and values that -you would typically enter in a command prompt. -Options may appear on one line or on several lines. -You may not specify environment variables for path names. -You may comment out lines by prefixing a hash symbol (\f[V]#\f[R]) to -the beginning of the line. -.PP -The following is an example of an options file for the \f[V]jlink\f[R] -command: -.IP -.nf -\f[CB] -#Wed Dec 07 00:40:19 EST 2016 ---module-path mlib ---add-modules com.greetings ---output greetingsapp -\f[R] -.fi -.RE -.SH JLINK PLUG-INS -.PP -\f[B]Note:\f[R] -.PP -Plug-ins not listed in this section aren\[aq]t supported and are subject -to change. -.PP -For plug-in options that require a \f[I]pattern-list\f[R], the value is -a comma-separated list of elements, with each element using one the -following forms: -.IP \[bu] 2 -\f[I]glob-pattern\f[R] -.IP \[bu] 2 -\f[V]glob:\f[R]\f[I]glob-pattern\f[R] -.IP \[bu] 2 -\f[V]regex:\f[R]\f[I]regex-pattern\f[R] -.IP \[bu] 2 -\f[V]\[at]\f[R]\f[I]filename\f[R] -.RS 2 -.IP \[bu] 2 -\f[I]filename\f[R] is the name of a file that contains patterns to be -used, one pattern per line. -.RE -.PP -For a complete list of all available plug-ins, run the command -\f[V]jlink --list-plugins\f[R]. -.SS Plugin \f[V]compress\f[R] -.TP -Options -\f[V]--compress=\f[R]{\f[V]0\f[R]|\f[V]1\f[R]|\f[V]2\f[R]}[\f[V]:filter=\f[R]\f[I]pattern-list\f[R]] -.TP -Description -Compresses all resources in the output image. -.RS -.IP \[bu] 2 -Level 0: No compression -.IP \[bu] 2 -Level 1: Constant string sharing -.IP \[bu] 2 -Level 2: ZIP -.PP -An optional \f[I]pattern-list\f[R] filter can be specified to list the -pattern of files to include. -.RE -.SS Plugin \f[V]include-locales\f[R] -.TP -Options -\f[V]--include-locales=\f[R]\f[I]langtag\f[R][\f[V],\f[R]\f[I]langtag\f[R]]* -.TP -Description -Includes the list of locales where \f[I]langtag\f[R] is a BCP 47 -language tag. -This option supports locale matching as defined in RFC 4647. -Ensure that you add the module jdk.localedata when using this option. -.RS -.PP -Example: -.RS -.PP -\f[V]--add-modules jdk.localedata --include-locales=en,ja,*-IN\f[R] -.RE -.RE -.SS Plugin \f[V]order-resources\f[R] -.TP -Options -\f[V]--order-resources=\f[R]\f[I]pattern-list\f[R] -.TP -Description -Orders the specified paths in priority order. -If \f[V]\[at]\f[R]\f[I]filename\f[R] is specified, then each line in -\f[I]pattern-list\f[R] must be an exact match for the paths to be -ordered. -.RS -.PP -Example: -.RS -.PP -\f[V]--order-resources=/module-info.class,\[at]classlist,/java.base/java/lang/\f[R] -.RE -.RE -.SS Plugin \f[V]strip-debug\f[R] -.TP -Options -\f[V]--strip-debug\f[R] -.TP -Description -Strips debug information from the output image. -.SS Plugin \f[V]generate-cds-archive\f[R] -.TP -Options -\f[V]--generate-cds-archive\f[R] -.TP -Description -Generate CDS archive if the runtime image supports the CDS feature. -.SH JLINK EXAMPLES -.PP -The following command creates a runtime image in the directory -\f[V]greetingsapp\f[R]. -This command links the module \f[V]com.greetings\f[R], whose module -definition is contained in the directory \f[V]mlib\f[R]. -.IP -.nf -\f[CB] -jlink --module-path mlib --add-modules com.greetings --output greetingsapp -\f[R] -.fi -.PP -The following command lists the modules in the runtime image -\f[V]greetingsapp\f[R]: -.IP -.nf -\f[CB] -greetingsapp/bin/java --list-modules -com.greetings -java.base\[at]11 -java.logging\[at]11 -org.astro\[at]1.0 -\f[R] -.fi -.PP -The following command creates a runtime image in the directory -compressedrt that\[aq]s stripped of debug symbols, uses compression to -reduce space, and includes French language locale information: -.IP -.nf -\f[CB] -jlink --add-modules jdk.localedata --strip-debug --compress=2 --include-locales=fr --output compressedrt -\f[R] -.fi -.PP -The following example compares the size of the runtime image -\f[V]compressedrt\f[R] with \f[V]fr_rt\f[R], which isn\[aq]t stripped of -debug symbols and doesn\[aq]t use compression: -.IP -.nf -\f[CB] -jlink --add-modules jdk.localedata --include-locales=fr --output fr_rt - -du -sh ./compressedrt ./fr_rt -23M ./compressedrt -36M ./fr_rt -\f[R] -.fi -.PP -The following example lists the providers that implement -\f[V]java.security.Provider\f[R]: -.IP -.nf -\f[CB] -jlink --suggest-providers java.security.Provider - -Suggested providers: - java.naming provides java.security.Provider used by java.base - java.security.jgss provides java.security.Provider used by java.base - java.security.sasl provides java.security.Provider used by java.base - java.smartcardio provides java.security.Provider used by java.base - java.xml.crypto provides java.security.Provider used by java.base - jdk.crypto.cryptoki provides java.security.Provider used by java.base - jdk.crypto.ec provides java.security.Provider used by java.base - jdk.crypto.mscapi provides java.security.Provider used by java.base - jdk.security.jgss provides java.security.Provider used by java.base -\f[R] -.fi -.PP -The following example creates a custom runtime image named -\f[V]mybuild\f[R] that includes only \f[V]java.naming\f[R] and -\f[V]jdk.crypto.cryptoki\f[R] and their dependencies but no other -providers. -Note that these dependencies must exist in the module path: -.IP -.nf -\f[CB] -jlink --add-modules java.naming,jdk.crypto.cryptoki --output mybuild -\f[R] -.fi -.PP -The following command is similar to the one that creates a runtime image -named \f[V]greetingsapp\f[R], except that it will link the modules -resolved from root modules with service binding; see the -\f[B]\f[VB]Configuration.resolveAndBind\f[B]\f[R] method. -.IP -.nf -\f[CB] -jlink --module-path mlib --add-modules com.greetings --output greetingsapp --bind-services -\f[R] -.fi -.PP -The following command lists the modules in the runtime image -greetingsapp created by this command: -.IP -.nf -\f[CB] -greetingsapp/bin/java --list-modules -com.greetings -java.base\[at]11 -java.compiler\[at]11 -java.datatransfer\[at]11 -java.desktop\[at]11 -java.logging\[at]11 -java.management\[at]11 -java.management.rmi\[at]11 -java.naming\[at]11 -java.prefs\[at]11 -java.rmi\[at]11 -java.security.jgss\[at]11 -java.security.sasl\[at]11 -java.smartcardio\[at]11 -java.xml\[at]11 -java.xml.crypto\[at]11 -jdk.accessibility\[at]11 -jdk.charsets\[at]11 -jdk.compiler\[at]11 -jdk.crypto.cryptoki\[at]11 -jdk.crypto.ec\[at]11 -jdk.crypto.mscapi\[at]11 -jdk.internal.opt\[at]11 -jdk.jartool\[at]11 -jdk.javadoc\[at]11 -jdk.jdeps\[at]11 -jdk.jfr\[at]11 -jdk.jlink\[at]11 -jdk.localedata\[at]11 -jdk.management\[at]11 -jdk.management.jfr\[at]11 -jdk.naming.dns\[at]11 -jdk.naming.rmi\[at]11 -jdk.security.auth\[at]11 -jdk.security.jgss\[at]11 -jdk.zipfs\[at]11 -org.astro\[at]1.0 -\f[R] -.fi diff --git a/src/jdk.jlink/share/man/jlink.md b/src/jdk.jlink/share/man/jlink.md new file mode 100644 index 00000000000..8c344a692cb --- /dev/null +++ b/src/jdk.jlink/share/man/jlink.md @@ -0,0 +1,347 @@ +--- +# Copyright (c) 2017, 2019, 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. +# + +title: 'JLINK(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jlink - assemble and optimize a set of modules and their dependencies into a +custom runtime image + +## Synopsis + +`jlink` \[*options*\] `--module-path` *modulepath* `--add-modules` *module*\[,*module*...\] + +*options* +: Command-line options separated by spaces. See [jlink Options]. + +*modulepath* +: The path where the `jlink` tool discovers observable modules. These modules + can be modular JAR files, JMOD files, or exploded modules. + +*module* +: The names of the modules to add to the runtime image. The `jlink` tool adds + these modules and their transitive dependencies. + +## Description + +The `jlink` tool links a set of modules, along with their transitive +dependences, to create a custom runtime image. + +**Note:** + +Developers are responsible for updating their custom runtime images. + +## jlink Options + +`--add-modules` *mod*\[`,`*mod*...\] +: Adds the named modules, *mod*, to the default set of root modules. The + default set of root modules is empty. + +`--bind-services` +: Link service provider modules and their dependencies. + +`-c ={0|1|2}` or `--compress={0|1|2}` +: Enable compression of resources: + + - `0`: No compression + - `1`: Constant string sharing + - `2`: ZIP + +`--disable-plugin` *pluginname* +: Disables the specified plug-in. See [jlink Plug-ins] for the list of + supported plug-ins. + +`--endian` {`little`\|`big`} +: Specifies the byte order of the generated image. The default value is the + format of your system's architecture. + +`-h` or `--help` +: Prints the help message. + +`--ignore-signing-information` +: Suppresses a fatal error when signed modular JARs are linked in the runtime + image. The signature-related files of the signed modular JARs aren't copied + to the runtime image. + +`--launcher` *command*`=`*module* or `--launcher` *command*`=`*module*`/`*main* +: Specifies the launcher command name for the module or the command name for + the module and main class (the module and the main class names are + separated by a slash (`/`)). + +`--limit-modules` *mod*\[`,`*mod*...\] +: Limits the universe of observable modules to those in the transitive + closure of the named modules, `mod`, plus the main module, if any, plus any + further modules specified in the `--add-modules` option. + +`--list-plugins` +: Lists available plug-ins, which you can access through command-line + options; see [jlink Plug-ins]. + +`-p` or `--module-path` *modulepath* +: Specifies the module path. + + If this option is not specified, then the default module path is + `$JAVA_HOME/jmods`. This directory contains the `java.base` module and the + other standard and JDK modules. If this option is specified but the + `java.base` module cannot be resolved from it, then the `jlink` command + appends `$JAVA_HOME/jmods` to the module path. + +`--no-header-files` +: Excludes header files. + +`--no-man-pages` +: Excludes man pages. + +`--output` *path* +: Specifies the location of the generated runtime image. + +`--save-opts` *filename* +: Saves `jlink` options in the specified file. + +`--suggest-providers` \[*name*`,` ...\] +: Suggest providers that implement the given service types from the module + path. + +`--version` +: Prints version information. + +`@`*filename* +: Reads options from the specified file. + + An options file is a text file that contains the options and values that + you would typically enter in a command prompt. Options may appear on one + line or on several lines. You may not specify environment variables for + path names. You may comment out lines by prefixing a hash symbol (`#`) to + the beginning of the line. + + The following is an example of an options file for the `jlink` command: + + ``` + #Wed Dec 07 00:40:19 EST 2016 + --module-path mlib + --add-modules com.greetings + --output greetingsapp + ``` + +## jlink Plug-ins + +**Note:** + +Plug-ins not listed in this section aren't supported and are subject to change. + +For plug-in options that require a *pattern-list*, the value is a +comma-separated list of elements, with each element using one the following +forms: + +- *glob-pattern* +- `glob:`*glob-pattern* +- `regex:`*regex-pattern* +- `@`*filename* + - *filename* is the name of a file that contains patterns to be used, one + pattern per line. + +For a complete list of all available plug-ins, run the command +`jlink --list-plugins`. + +### Plugin `compress` + +Options +: `--compress=`{`0`\|`1`\|`2`}\[`:filter=`*pattern-list*\] + +Description +: Compresses all resources in the output image. + + - Level 0: No compression + - Level 1: Constant string sharing + - Level 2: ZIP + + An optional *pattern-list* filter can be specified to list the pattern of + files to include. + +### Plugin `include-locales` + +Options +: `--include-locales=`*langtag*\[`,`*langtag*\]\* + +Description +: Includes the list of locales where *langtag* is a BCP 47 language tag. + This option supports locale matching as defined in RFC 4647. Ensure that + you add the module jdk.localedata when using this option. + + Example: + + > `--add-modules jdk.localedata --include-locales=en,ja,*-IN` + +### Plugin `order-resources` + +Options +: `--order-resources=`*pattern-list* + +Description +: Orders the specified paths in priority order. If `@`*filename* is + specified, then each line in *pattern-list* must be an exact match for the + paths to be ordered. + + Example: + + > `--order-resources=/module-info.class,@classlist,/java.base/java/lang/` + +### Plugin `strip-debug` + +Options +: `--strip-debug` + +Description +: Strips debug information from the output image. + +### Plugin `generate-cds-archive` + +Options +: `--generate-cds-archive` + +Description +: Generate CDS archive if the runtime image supports the CDS feature. + +## jlink Examples + +The following command creates a runtime image in the directory `greetingsapp`. +This command links the module `com.greetings`, whose module definition is +contained in the directory `mlib`. + +``` +jlink --module-path mlib --add-modules com.greetings --output greetingsapp +``` + +The following command lists the modules in the runtime image `greetingsapp`: + +``` +greetingsapp/bin/java --list-modules +com.greetings +java.base@11 +java.logging@11 +org.astro@1.0 +``` + +The following command creates a runtime image in the directory compressedrt +that's stripped of debug symbols, uses compression to reduce space, and +includes French language locale information: + +``` +jlink --add-modules jdk.localedata --strip-debug --compress=2 --include-locales=fr --output compressedrt +``` + +The following example compares the size of the runtime image `compressedrt` +with `fr_rt`, which isn't stripped of debug symbols and doesn't use +compression: + +``` +jlink --add-modules jdk.localedata --include-locales=fr --output fr_rt + +du -sh ./compressedrt ./fr_rt +23M ./compressedrt +36M ./fr_rt +``` + +The following example lists the providers that implement +`java.security.Provider`: + +``` +jlink --suggest-providers java.security.Provider + +Suggested providers: + java.naming provides java.security.Provider used by java.base + java.security.jgss provides java.security.Provider used by java.base + java.security.sasl provides java.security.Provider used by java.base + java.smartcardio provides java.security.Provider used by java.base + java.xml.crypto provides java.security.Provider used by java.base + jdk.crypto.cryptoki provides java.security.Provider used by java.base + jdk.crypto.ec provides java.security.Provider used by java.base + jdk.crypto.mscapi provides java.security.Provider used by java.base + jdk.security.jgss provides java.security.Provider used by java.base +``` + +The following example creates a custom runtime image named `mybuild` that +includes only `java.naming` and `jdk.crypto.cryptoki` and their dependencies but no +other providers. Note that these dependencies must exist in the module path: + +``` +jlink --add-modules java.naming,jdk.crypto.cryptoki --output mybuild +``` + +The following command is similar to the one that creates a runtime image named +`greetingsapp`, except that it will link the modules resolved from root modules +with service binding; see the [`Configuration.resolveAndBind`]( +../../api/java.base/java/lang/module/Configuration.html#resolveAndBind(java.lang.module.ModuleFinder,java.util.List,java.lang.module.ModuleFinder,java.util.Collection)) +method. + +``` +jlink --module-path mlib --add-modules com.greetings --output greetingsapp --bind-services +``` + +The following command lists the modules in the runtime image greetingsapp +created by this command: + +``` +greetingsapp/bin/java --list-modules +com.greetings +java.base@11 +java.compiler@11 +java.datatransfer@11 +java.desktop@11 +java.logging@11 +java.management@11 +java.management.rmi@11 +java.naming@11 +java.prefs@11 +java.rmi@11 +java.security.jgss@11 +java.security.sasl@11 +java.smartcardio@11 +java.xml@11 +java.xml.crypto@11 +jdk.accessibility@11 +jdk.charsets@11 +jdk.compiler@11 +jdk.crypto.cryptoki@11 +jdk.crypto.ec@11 +jdk.crypto.mscapi@11 +jdk.internal.opt@11 +jdk.jartool@11 +jdk.javadoc@11 +jdk.jdeps@11 +jdk.jfr@11 +jdk.jlink@11 +jdk.localedata@11 +jdk.management@11 +jdk.management.jfr@11 +jdk.naming.dns@11 +jdk.naming.rmi@11 +jdk.security.auth@11 +jdk.security.jgss@11 +jdk.zipfs@11 +org.astro@1.0 +``` diff --git a/src/jdk.jlink/share/man/jmod.1 b/src/jdk.jlink/share/man/jmod.1 deleted file mode 100644 index 4475505e524..00000000000 --- a/src/jdk.jlink/share/man/jmod.1 +++ /dev/null @@ -1,423 +0,0 @@ -.\" Copyright (c) 2017, 2023, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JMOD" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jmod - create JMOD files and list the content of existing JMOD files -.SH SYNOPSIS -.PP -\f[V]jmod\f[R] -(\f[V]create\f[R]|\f[V]extract\f[R]|\f[V]list\f[R]|\f[V]describe\f[R]|\f[V]hash\f[R]) -[\f[I]options\f[R]] \f[I]jmod-file\f[R] -.PP -Includes the following: -.PP -\f[B]Main operation modes\f[R] -.TP -\f[V]create\f[R] -Creates a new JMOD archive file. -.TP -\f[V]extract\f[R] -Extracts all the files from the JMOD archive file. -.TP -\f[V]list\f[R] -Prints the names of all the entries. -.TP -\f[V]describe\f[R] -Prints the module details. -.TP -\f[V]hash\f[R] -Determines leaf modules and records the hashes of the dependencies that -directly and indirectly require them. -.PP -\f[B]Options\f[R] -.TP -\f[I]options\f[R] -See \f[B]Options for jmod\f[R]. -.PP -\f[B]Required\f[R] -.TP -\f[I]jmod-file\f[R] -Specifies the name of the JMOD file to create or from which to retrieve -information. -.SH DESCRIPTION -.PP -\f[B]Note:\f[R] For most development tasks, including deploying modules -on the module path or publishing them to a Maven repository, continue to -package modules in modular JAR files. -The \f[V]jmod\f[R] tool is intended for modules that have native -libraries or other configuration files or for modules that you intend to -link, with the \f[B]jlink\f[R] tool, to a runtime image. -.PP -The JMOD file format lets you aggregate files other than -\f[V].class\f[R] files, metadata, and resources. -This format is transportable but not executable, which means that you -can use it during compile time or link time but not at run time. -.PP -Many \f[V]jmod\f[R] options involve specifying a path whose contents are -copied into the resulting JMOD files. -These options copy all the contents of the specified path, including -subdirectories and their contents, but exclude files whose names match -the pattern specified by the \f[V]--exclude\f[R] option. -.PP -With the \f[V]--hash-modules\f[R] option or the \f[V]jmod hash\f[R] -command, you can, in each module\[aq]s descriptor, record hashes of the -content of the modules that are allowed to depend upon it, thus -\[dq]tying\[dq] together these modules. -This enables a package to be exported to one or more specifically-named -modules and to no others through qualified exports. -The runtime verifies if the recorded hash of a module matches the one -resolved at run time; if not, the runtime returns an error. -.SH OPTIONS FOR JMOD -.TP -\f[V]--class-path\f[R] \f[I]path\f[R] -Specifies the location of application JAR files or a directory -containing classes to copy into the resulting JMOD file. -.TP -\f[V]--cmds\f[R] \f[I]path\f[R] -Specifies the location of native commands to copy into the resulting -JMOD file. -.TP -\f[V]--compress\f[R] \f[I]compress\f[R] -Specifies the compression to use in creating the JMOD file. -The accepted values are \f[V]zip-[0-9]\f[R], where \f[V]zip-0\f[R] -provides no compression, and \f[V]zip-9\f[R] provides the best -compression. -Default is \f[V]zip-6\f[R]. -.TP -\f[V]--config\f[R] \f[I]path\f[R] -Specifies the location of user-editable configuration files to copy into -the resulting JMOD file. -.TP -\f[V]--date\f[R]\f[I]TIMESTAMP\f[R] -The timestamp in ISO-8601 extended offset date-time with optional -time-zone format, to use for the timestamp of the entries, e.g. -\[dq]2022-02-12T12:30:00-05:00\[dq]. -.TP -\f[V]--dir\f[R] \f[I]path\f[R] -Specifies the location where \f[V]jmod\f[R] puts extracted files from -the specified JMOD archive. -.TP -\f[V]--dry-run\f[R] -Performs a dry run of hash mode. -It identifies leaf modules and their required modules without recording -any hash values. -.TP -\f[V]--exclude\f[R] \f[I]pattern-list\f[R] -Excludes files matching the supplied comma-separated pattern list, each -element using one the following forms: -.RS -.IP \[bu] 2 -\f[I]glob-pattern\f[R] -.IP \[bu] 2 -\f[V]glob:\f[R]\f[I]glob-pattern\f[R] -.IP \[bu] 2 -\f[V]regex:\f[R]\f[I]regex-pattern\f[R] -.PP -See the \f[B]\f[VB]FileSystem.getPathMatcher\f[B]\f[R] method for the -syntax of \f[I]glob-pattern\f[R]. -See the \f[B]\f[VB]Pattern\f[B]\f[R] class for the syntax of -\f[I]regex-pattern\f[R], which represents a regular expression. -.RE -.TP -\f[V]--hash-modules\f[R] \f[I]regex-pattern\f[R] -Determines the leaf modules and records the hashes of the dependencies -directly and indirectly requiring them, based on the module graph of the -modules matching the given \f[I]regex-pattern\f[R]. -The hashes are recorded in the JMOD archive file being created, or a -JMOD archive or modular JAR on the module path specified by the -\f[V]jmod hash\f[R] command. -.TP -\f[V]--header-files\f[R] \f[I]path\f[R] -Specifies the location of header files to copy into the resulting JMOD -file. -.TP -\f[V]--help\f[R] or \f[V]-h\f[R] -Prints a usage message. -.TP -\f[V]--help-extra\f[R] -Prints help for extra options. -.TP -\f[V]--legal-notices\f[R] \f[I]path\f[R] -Specifies the location of legal notices to copy into the resulting JMOD -file. -.TP -\f[V]--libs\f[R] \f[I]path\f[R] -Specifies location of native libraries to copy into the resulting JMOD -file. -.TP -\f[V]--main-class\f[R] \f[I]class-name\f[R] -Specifies main class to record in the module-info.class file. -.TP -\f[V]--man-pages\f[R] \f[I]path\f[R] -Specifies the location of man pages to copy into the resulting JMOD -file. -.TP -\f[V]--module-version\f[R] \f[I]module-version\f[R] -Specifies the module version to record in the module-info.class file. -.TP -\f[V]--module-path\f[R] \f[I]path\f[R] or \f[V]-p\f[R] \f[I]path\f[R] -Specifies the module path. -This option is required if you also specify \f[V]--hash-modules\f[R]. -.TP -\f[V]--target-platform\f[R] \f[I]platform\f[R] -Specifies the target platform. -.TP -\f[V]--version\f[R] -Prints version information of the \f[V]jmod\f[R] tool. -.TP -\f[V]\[at]\f[R]\f[I]filename\f[R] -Reads options from the specified file. -.RS -.PP -An options file is a text file that contains the options and values that -you would ordinarily enter in a command prompt. -Options may appear on one line or on several lines. -You may not specify environment variables for path names. -You may comment out lines by prefixinga hash symbol (\f[V]#\f[R]) to the -beginning of the line. -.PP -The following is an example of an options file for the \f[V]jmod\f[R] -command: -.IP -.nf -\f[CB] -#Wed Dec 07 00:40:19 EST 2016 -create --class-path mods/com.greetings --module-path mlib - --cmds commands --config configfiles --header-files src/h - --libs lib --main-class com.greetings.Main - --man-pages man --module-version 1.0 - --os-arch \[dq]x86_x64\[dq] --os-name \[dq]macOS\[dq] - --os-version \[dq]10.10.5\[dq] greetingsmod -\f[R] -.fi -.RE -.SH EXTRA OPTIONS FOR JMOD -.PP -In addition to the options described in \f[B]Options for jmod\f[R], the -following are extra options that can be used with the command. -.TP -\f[V]--do-not-resolve-by-default\f[R] -Exclude from the default root set of modules -.TP -\f[V]--warn-if-resolved\f[R] -Hint for a tool to issue a warning if the module is resolved. -One of deprecated, deprecated-for-removal, or incubating. -.SH JMOD CREATE EXAMPLE -.PP -The following is an example of creating a JMOD file: -.IP -.nf -\f[CB] -jmod create --class-path mods/com.greetings --cmds commands - --config configfiles --header-files src/h --libs lib - --main-class com.greetings.Main --man-pages man --module-version 1.0 - --os-arch \[dq]x86_x64\[dq] --os-name \[dq]macOS\[dq] - --os-version \[dq]10.10.5\[dq] greetingsmod -\f[R] -.fi -.PP -Create a JMOD file specifying the date for the entries as -\f[V]2022 March 15 00:00:00\f[R]: -.IP -.nf -\f[CB] -jmod create --class-path build/foo/classes --date 2022-03-15T00:00:00Z - jmods/foo1.jmod -\f[R] -.fi -.SH JMOD HASH EXAMPLE -.PP -The following example demonstrates what happens when you try to link a -leaf module (in this example, \f[V]ma\f[R]) with a required module -(\f[V]mb\f[R]), and the hash value recorded in the required module -doesn\[aq]t match that of the leaf module. -.IP "1." 3 -Create and compile the following \f[V].java\f[R] files: -.RS 4 -.IP \[bu] 2 -\f[V]jmodhashex/src/ma/module-info.java\f[R] -.RS 2 -.IP -.nf -\f[CB] -module ma { - requires mb; -} -\f[R] -.fi -.RE -.IP \[bu] 2 -\f[V]jmodhashex/src/mb/module-info.java\f[R] -.RS 2 -.IP -.nf -\f[CB] -module mb { -} -\f[R] -.fi -.RE -.IP \[bu] 2 -\f[V]jmodhashex2/src/ma/module-info.java\f[R] -.RS 2 -.IP -.nf -\f[CB] -module ma { - requires mb; -} -\f[R] -.fi -.RE -.IP \[bu] 2 -\f[V]jmodhashex2/src/mb/module-info.java\f[R] -.RS 2 -.IP -.nf -\f[CB] -module mb { -} -\f[R] -.fi -.RE -.RE -.IP "2." 3 -Create a JMOD archive for each module. -Create the directories \f[V]jmodhashex/jmods\f[R] and -\f[V]jmodhashex2/jmods\f[R], and then run the following commands from -the \f[V]jmodhashex\f[R] directory, then from the \f[V]jmodhashex2\f[R] -directory: -.RS 4 -.IP \[bu] 2 -\f[V]jmod create --class-path mods/ma jmods/ma.jmod\f[R] -.IP \[bu] 2 -\f[V]jmod create --class-path mods/mb jmods/mb.jmod\f[R] -.RE -.IP "3." 3 -Optionally preview the \f[V]jmod hash\f[R] command. -Run the following command from the \f[V]jmodhashex\f[R] directory: -.RS 4 -.PP -\f[V]jmod hash --dry-run -module-path jmods --hash-modules .*\f[R] -.PP -The command prints the following: -.IP -.nf -\f[CB] -Dry run: -mb - hashes ma SHA-256 07667d5032004b37b42ec2bb81b46df380cf29e66962a16481ace2e71e74073a -\f[R] -.fi -.PP -This indicates that the \f[V]jmod hash\f[R] command (without the -\f[V]--dry-run\f[R] option) will record the hash value of the leaf -module \f[V]ma\f[R] in the module \f[V]mb\f[R]. -.RE -.IP "4." 3 -Record hash values in the JMOD archive files contained in the -\f[V]jmodhashex\f[R] directory. -Run the following command from the \f[V]jmodhashex\f[R] directory: -.RS 4 -.RS -.PP -\f[V]jmod hash --module-path jmods --hash-modules .*\f[R] -.RE -.PP -The command prints the following: -.RS -.PP -\f[V]Hashes are recorded in module mb\f[R] -.RE -.RE -.IP "5." 3 -Print information about each JMOD archive contained in the -\f[V]jmodhashex\f[R] directory. -Run the highlighted commands from the \f[V]jmodhashex\f[R] directory: -.RS 4 -.IP -.nf -\f[CB] -jmod describe jmods/ma.jmod - -ma - requires mandated java.base - requires mb - -jmod describe jmods/mb.jmod - -mb - requires mandated java.base - hashes ma SHA-256 07667d5032004b37b42ec2bb81b46df380cf29e66962a16481ace2e71e74073a -\f[R] -.fi -.RE -.IP "6." 3 -Attempt to create a runtime image that contains the module \f[V]ma\f[R] -from the directory \f[V]jmodhashex2\f[R] but the module \f[V]mb\f[R] -from the directory \f[V]jmodhashex\f[R]. -Run the following command from the \f[V]jmodhashex2\f[R] directory: -.RS 4 -.IP \[bu] 2 -\f[B]Linux and macOS:\f[R] -.RS 2 -.RS -.PP -\f[V]jlink --module-path $JAVA_HOME/jmods:jmods/ma.jmod:../jmodhashex/jmods/mb.jmod --add-modules ma --output ma-app\f[R] -.RE -.RE -.IP \[bu] 2 -\f[B]Windows:\f[R] -.RS 2 -.RS -.PP -\f[V]jlink --module-path %JAVA_HOME%/jmods;jmods/ma.jmod;../jmodhashex/jmods/mb.jmod --add-modules ma --output ma-app\f[R] -.RE -.RE -.PP -The command prints an error message similar to the following: -.IP -.nf -\f[CB] -Error: Hash of ma (a2d77889b0cb067df02a3abc39b01ac1151966157a68dc4241562c60499150d2) differs to -expected hash (07667d5032004b37b42ec2bb81b46df380cf29e66962a16481ace2e71e74073a) recorded in mb -\f[R] -.fi -.RE diff --git a/src/jdk.jlink/share/man/jmod.md b/src/jdk.jlink/share/man/jmod.md new file mode 100644 index 00000000000..273001b6a9a --- /dev/null +++ b/src/jdk.jlink/share/man/jmod.md @@ -0,0 +1,348 @@ +--- +# Copyright (c) 2017, 2023, 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. +# + +title: 'JMOD(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jmod - create JMOD files and list the content of existing JMOD files + +## Synopsis + +`jmod` (`create`\|`extract`\|`list`\|`describe`\|`hash`) \[*options*\] +*jmod-file* + +Includes the following: + +**Main operation modes** + +`create` +: Creates a new JMOD archive file. + +`extract` +: Extracts all the files from the JMOD archive file. + +`list` +: Prints the names of all the entries. + +`describe` +: Prints the module details. + +`hash` +: Determines leaf modules and records the hashes of the dependencies that + directly and indirectly require them. + +**Options** + +*options* +: See [Options for jmod]. + +**Required** + +*jmod-file* +: Specifies the name of the JMOD file to create or from which to retrieve + information. + +## Description + +**Note:** For most development tasks, including deploying modules on the module +path or publishing them to a Maven repository, continue to package modules in +modular JAR files. The `jmod` tool is intended for modules that have native +libraries or other configuration files or for modules that you intend to link, +with the [jlink](jlink.html) tool, to a runtime image. + +The JMOD file format lets you aggregate files other than `.class` files, +metadata, and resources. This format is transportable but not executable, which +means that you can use it during compile time or link time but not at run time. + +Many `jmod` options involve specifying a path whose contents are copied into +the resulting JMOD files. These options copy all the contents of the specified +path, including subdirectories and their contents, but exclude files whose +names match the pattern specified by the `--exclude` option. + +With the `--hash-modules` option or the `jmod hash` command, you can, in each +module's descriptor, record hashes of the content of the modules that are +allowed to depend upon it, thus "tying" together these modules. This enables a +package to be exported to one or more specifically-named modules and to no +others through qualified exports. The runtime verifies if the recorded hash of +a module matches the one resolved at run time; if not, the runtime returns an +error. + +## Options for jmod + +`--class-path` *path* +: Specifies the location of application JAR files or a directory containing + classes to copy into the resulting JMOD file. + +`--cmds` *path* +: Specifies the location of native commands to copy into the resulting JMOD + file. + +`--compress` *compress* +: Specifies the compression to use in creating the JMOD file. + The accepted values are `zip-[0-9]`, where `zip-0` provides no + compression, and `zip-9` provides the best compression. Default is `zip-6`. + +`--config` *path* +: Specifies the location of user-editable configuration files to copy into + the resulting JMOD file. + +`--date `*TIMESTAMP* +: The timestamp in ISO-8601 extended offset date-time with optional time-zone +format, to use for the timestamp of the entries, +e.g. "2022-02-12T12:30:00-05:00". + +`--dir` *path* +: Specifies the location where `jmod` puts extracted files from the specified + JMOD archive. + +`--dry-run` +: Performs a dry run of hash mode. It identifies leaf modules and their + required modules without recording any hash values. + +`--exclude` *pattern-list* +: Excludes files matching the supplied comma-separated pattern list, each + element using one the following forms: + + - *glob-pattern* + + - `glob:`*glob-pattern* + + - `regex:`*regex-pattern* + + See the [`FileSystem.getPathMatcher`]( + ../../api/java.base/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)) + method for the syntax of *glob-pattern*. See the [`Pattern`]( + ../../api/java.base/java/util/regex/Pattern.html) + class for the syntax of *regex-pattern*, which represents a regular + expression. + +`--hash-modules` *regex-pattern* +: Determines the leaf modules and records the hashes of the dependencies + directly and indirectly requiring them, based on the module graph of the + modules matching the given *regex-pattern*. The hashes are recorded in the + JMOD archive file being created, or a JMOD archive or modular JAR on the + module path specified by the `jmod hash` command. + +`--header-files` *path* +: Specifies the location of header files to copy into the resulting JMOD + file. + +`--help` or `-h` +: Prints a usage message. + +`--help-extra` +: Prints help for extra options. + +`--legal-notices` *path* +: Specifies the location of legal notices to copy into the resulting JMOD + file. + +`--libs` *path* +: Specifies location of native libraries to copy into the resulting JMOD + file. + +`--main-class` *class-name* +: Specifies main class to record in the module-info.class file. + +`--man-pages` *path* +: Specifies the location of man pages to copy into the resulting JMOD file. + +`--module-version` *module-version* +: Specifies the module version to record in the module-info.class file. + +`--module-path` *path* or `-p` *path* +: Specifies the module path. This option is required if you also specify + `--hash-modules`. + +`--target-platform` *platform* +: Specifies the target platform. + +`--version` +: Prints version information of the `jmod` tool. + +`@`*filename* +: Reads options from the specified file. + + An options file is a text file that contains the options and values that + you would ordinarily enter in a command prompt. Options may appear on one + line or on several lines. You may not specify environment variables for + path names. You may comment out lines by prefixinga hash symbol (`#`) to + the beginning of the line. + + The following is an example of an options file for the `jmod` command: + + ``` + #Wed Dec 07 00:40:19 EST 2016 + create --class-path mods/com.greetings --module-path mlib + --cmds commands --config configfiles --header-files src/h + --libs lib --main-class com.greetings.Main + --man-pages man --module-version 1.0 + --os-arch "x86_x64" --os-name "macOS" + --os-version "10.10.5" greetingsmod + ``` + +## Extra Options for jmod + +In addition to the options described in [Options for jmod], the following are +extra options that can be used with the command. + +`--do-not-resolve-by-default` +: Exclude from the default root set of modules + +`--warn-if-resolved` +: Hint for a tool to issue a warning if the module is resolved. One of + deprecated, deprecated-for-removal, or incubating. + +## jmod Create Example + +The following is an example of creating a JMOD file: + +``` +jmod create --class-path mods/com.greetings --cmds commands + --config configfiles --header-files src/h --libs lib + --main-class com.greetings.Main --man-pages man --module-version 1.0 + --os-arch "x86_x64" --os-name "macOS" + --os-version "10.10.5" greetingsmod +``` +Create a JMOD file specifying the date for the entries as `2022 March 15 00:00:00`: + +``` +jmod create --class-path build/foo/classes --date 2022-03-15T00:00:00Z + jmods/foo1.jmod +``` +## jmod Hash Example + +The following example demonstrates what happens when you try to link a leaf +module (in this example, `ma`) with a required module (`mb`), and the hash +value recorded in the required module doesn't match that of the leaf module. + +1. Create and compile the following `.java` files: + + - `jmodhashex/src/ma/module-info.java` + + ``` + module ma { + requires mb; + } + ``` + + - `jmodhashex/src/mb/module-info.java` + + ``` + module mb { + } + ``` + + - `jmodhashex2/src/ma/module-info.java` + + ``` + module ma { + requires mb; + } + ``` + + - `jmodhashex2/src/mb/module-info.java` + + ``` + module mb { + } + ``` + +2. Create a JMOD archive for each module. Create the directories + `jmodhashex/jmods` and `jmodhashex2/jmods`, and then run the following + commands from the `jmodhashex` directory, then from the `jmodhashex2` + directory: + + - `jmod create --class-path mods/ma jmods/ma.jmod` + + - `jmod create --class-path mods/mb jmods/mb.jmod` + +3. Optionally preview the `jmod hash` command. Run the following command from + the `jmodhashex` directory: + + `jmod hash --dry-run -module-path jmods --hash-modules .*` + + The command prints the following: + + ``` + Dry run: + mb + hashes ma SHA-256 07667d5032004b37b42ec2bb81b46df380cf29e66962a16481ace2e71e74073a + ``` + + This indicates that the `jmod hash` command (without the `--dry-run` + option) will record the hash value of the leaf module `ma` in the module + `mb`. + +4. Record hash values in the JMOD archive files contained in the `jmodhashex` + directory. Run the following command from the `jmodhashex` directory: + + > `jmod hash --module-path jmods --hash-modules .*` + + The command prints the following: + + > `Hashes are recorded in module mb` + +5. Print information about each JMOD archive contained in the `jmodhashex` + directory. Run the highlighted commands from the `jmodhashex` directory: + + ``` + jmod describe jmods/ma.jmod + + ma + requires mandated java.base + requires mb + + jmod describe jmods/mb.jmod + + mb + requires mandated java.base + hashes ma SHA-256 07667d5032004b37b42ec2bb81b46df380cf29e66962a16481ace2e71e74073a + ``` + +6. Attempt to create a runtime image that contains the module `ma` from the + directory `jmodhashex2` but the module `mb` from the directory + `jmodhashex`. Run the following command from the `jmodhashex2` directory: + + - **Linux and macOS:** + + > `jlink --module-path + $JAVA_HOME/jmods:jmods/ma.jmod:../jmodhashex/jmods/mb.jmod + --add-modules ma --output ma-app` + + - **Windows:** + + > `jlink --module-path + %JAVA_HOME%/jmods;jmods/ma.jmod;../jmodhashex/jmods/mb.jmod + --add-modules ma --output ma-app` + + The command prints an error message similar to the following: + + ``` + Error: Hash of ma (a2d77889b0cb067df02a3abc39b01ac1151966157a68dc4241562c60499150d2) differs to + expected hash (07667d5032004b37b42ec2bb81b46df380cf29e66962a16481ace2e71e74073a) recorded in mb + ``` diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java index 6a5b200f8f3..a9cf2682cd7 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -54,6 +54,8 @@ import static jdk.jpackage.internal.StandardBundlerParam.ICON; import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE; import static jdk.jpackage.internal.StandardBundlerParam.SHORTCUT_HINT; +import jdk.jpackage.internal.util.PathUtils; +import jdk.jpackage.internal.util.XmlUtils; /** * Helper to create files for desktop integration. @@ -119,7 +121,7 @@ private DesktopIntegration(PlatformPackage thePackage, if (withDesktopFile) { desktopFile = new DesktopFile(desktopFileName); iconFile = new DesktopFile(escapedAppFileName - + IOUtils.getSuffix(Path.of(DEFAULT_ICON))); + + PathUtils.getSuffix(Path.of(DEFAULT_ICON))); if (curIconResource == null) { // Create default icon. @@ -420,7 +422,7 @@ private void appendFileAssociation(XMLStreamWriter xml, } private void createFileAssociationsMimeInfoFile() throws IOException { - IOUtils.createXml(mimeInfoFile.srcPath(), xml -> { + XmlUtils.createXml(mimeInfoFile.srcPath(), xml -> { xml.writeStartElement("mime-info"); xml.writeDefaultNamespace( "http://www.freedesktop.org/standards/shared-mime-info"); @@ -451,7 +453,7 @@ private void addFileAssociationIconFiles(ShellCommands shellCommands) // Create icon name for mime type from mime type. DesktopFile faIconFile = new DesktopFile(mimeType.replace( - File.separatorChar, '-') + IOUtils.getSuffix( + File.separatorChar, '-') + PathUtils.getSuffix( assoc.data.iconPath)); IOUtils.copyFile(assoc.data.iconPath, diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java index 7291d56218a..ab97e327003 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -35,6 +35,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME; import static jdk.jpackage.internal.StandardBundlerParam.ICON; import static jdk.jpackage.internal.StandardBundlerParam.ADD_LAUNCHERS; +import jdk.jpackage.internal.util.PathUtils; public class LinuxAppImageBuilder extends AbstractAppImageBuilder { @@ -127,7 +128,7 @@ private void createLauncherForEntryPoint(Map<String, ? super Object> params, mainParams); if (iconResource != null) { Path iconTarget = appLayout.destktopIntegrationDirectory().resolve( - APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of( + APP_NAME.fetchFrom(params) + PathUtils.getSuffix(Path.of( DEFAULT_ICON))); iconResource.saveToFile(iconTarget); } diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBundler.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBundler.java index b510ed41411..5d160d4128c 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBundler.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -44,6 +44,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.VENDOR; import static jdk.jpackage.internal.StandardBundlerParam.DESCRIPTION; import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR; +import jdk.jpackage.internal.util.FileUtils; abstract class LinuxPackageBundler extends AbstractBundler { @@ -144,7 +145,7 @@ public final Path execute(Map<String, ? super Object> params, // Application image is a newly created directory tree. // Move it. srcAppLayout.move(thePackage.sourceApplicationLayout()); - IOUtils.deleteRecursive(srcAppImageRoot); + FileUtils.deleteRecursive(srcAppImageRoot); } } diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java index 8d9db0a0077..69ecce068e7 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,25 +25,20 @@ package jdk.jpackage.internal; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.PrintStream; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME; import static jdk.jpackage.internal.StandardBundlerParam.INSTALLER_NAME; import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR; import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE; import static jdk.jpackage.internal.StandardBundlerParam.VERSION; import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE; +import jdk.jpackage.internal.util.FileUtils; public abstract class MacBaseInstallerBundler extends AbstractBundler { @@ -187,7 +182,7 @@ protected Path prepareAppBundle(Map<String, ? super Object> params) StandardBundlerParam.getPredefinedAppImage(params); if (predefinedImage != null) { appDir = appImageRoot.resolve(APP_NAME.fetchFrom(params) + ".app"); - IOUtils.copyRecursive(predefinedImage, appDir, + FileUtils.copyRecursive(predefinedImage, appDir, LinkOption.NOFOLLOW_LINKS); // Create PackageFile if predefined app image is not signed diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgBundler.java index 7d100832dba..3de8ef5ee2b 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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 @@ -48,6 +48,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.TEMP_ROOT; import static jdk.jpackage.internal.StandardBundlerParam.VERBOSE; import static jdk.jpackage.internal.StandardBundlerParam.DMG_CONTENT; +import jdk.jpackage.internal.util.FileUtils; public class MacDmgBundler extends MacBaseInstallerBundler { @@ -294,7 +295,7 @@ private Path buildDMG( Map<String, ? super Object> params, MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params)); Path dest = root.resolve("Contents/Home"); - IOUtils.copyRecursive(source, dest); + FileUtils.copyRecursive(source, dest); srcFolder = newRoot; } @@ -319,7 +320,7 @@ private Path buildDMG( Map<String, ? super Object> params, List <String> dmgContent = DMG_CONTENT.fetchFrom(params); for (String content : dmgContent) { Path path = Path.of(content); - IOUtils.copyRecursive(path, srcFolder.resolve(path.getFileName())); + FileUtils.copyRecursive(path, srcFolder.resolve(path.getFileName())); } // create temp image ProcessBuilder pb = new ProcessBuilder( @@ -381,9 +382,9 @@ private Path buildDMG( Map<String, ? super Object> params, Path destPath = mountedRoot .resolve(srcFolder.getFileName()); Files.createDirectory(destPath); - IOUtils.copyRecursive(srcFolder, destPath); + FileUtils.copyRecursive(srcFolder, destPath); } else { - IOUtils.copyRecursive(srcFolder, mountedRoot); + FileUtils.copyRecursive(srcFolder, mountedRoot); } } diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacLaunchersAsServices.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacLaunchersAsServices.java index b0ee96e2ee3..4f069921f45 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacLaunchersAsServices.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacLaunchersAsServices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -33,6 +33,7 @@ import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER; import static jdk.jpackage.internal.OverridableResource.createResource; import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME; +import jdk.jpackage.internal.util.PathUtils; /** * Helper to install launchers as services using "launchd". @@ -95,7 +96,7 @@ private static class Launcher extends UnixLauncherAsService { // It is recommended to set value of "label" property in launchd // .plist file equal to the name of this .plist file without the suffix. - String label = IOUtils.replaceSuffix(plistFilename.getFileName(), "").toString(); + String label = PathUtils.replaceSuffix(plistFilename.getFileName(), "").toString(); getResource() .setPublicName(plistFilename) diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java index 6ac84975451..a4345ecf764 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -62,6 +62,8 @@ import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER; import static jdk.jpackage.internal.OverridableResource.createResource; import static jdk.jpackage.internal.StandardBundlerParam.RESOURCE_DIR; +import jdk.jpackage.internal.util.FileUtils; +import jdk.jpackage.internal.util.XmlUtils; public class MacPkgBundler extends MacBaseInstallerBundler { @@ -267,7 +269,7 @@ private void prepareDistributionXMLFile(Map<String, ? super Object> params) Log.verbose(MessageFormat.format(I18N.getString( "message.preparing-distribution-dist"), f.toAbsolutePath().toString())); - IOUtils.createXml(f, xml -> { + XmlUtils.createXml(f, xml -> { xml.writeStartElement("installer-gui-script"); xml.writeAttribute("minSpecVersion", "1"); @@ -452,7 +454,7 @@ private String getRoot(Map<String, ? super Object> params, source = appLocation; dest = newRoot.resolve(appLocation.getFileName()); } - IOUtils.copyRecursive(source, dest); + FileUtils.copyRecursive(source, dest); return newRoot.toString(); } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractAppImageBuilder.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractAppImageBuilder.java index b507cc955bd..b523e43f5aa 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractAppImageBuilder.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractAppImageBuilder.java @@ -32,8 +32,6 @@ import java.util.ArrayList; import java.util.Map; import java.util.List; -import java.util.Objects; -import java.util.stream.Stream; import static jdk.jpackage.internal.OverridableResource.createResource; import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME; import static jdk.jpackage.internal.StandardBundlerParam.ICON; @@ -42,6 +40,8 @@ import static jdk.jpackage.internal.StandardBundlerParam.OUTPUT_DIR; import static jdk.jpackage.internal.StandardBundlerParam.TEMP_ROOT; import jdk.jpackage.internal.resources.ResourceLocator; +import jdk.jpackage.internal.util.FileUtils; +import jdk.jpackage.internal.util.PathUtils; /* * AbstractAppImageBuilder @@ -92,7 +92,7 @@ protected void copyApplication(Map<String, ? super Object> params) } } - IOUtils.copyRecursive(inputPath, + FileUtils.copyRecursive(inputPath, appLayout.appDirectory().toAbsolutePath(), excludes); } @@ -100,7 +100,7 @@ protected void copyApplication(Map<String, ? super Object> params) List<String> items = APP_CONTENT.fetchFrom(params); for (String item : items) { - IOUtils.copyRecursive(Path.of(item), + FileUtils.copyRecursive(Path.of(item), appLayout.contentDirectory().resolve(Path.of(item).getFileName())); } } @@ -115,7 +115,7 @@ public static OverridableResource createIconResource(String defaultIconName, } final String resourcePublicName = APP_NAME.fetchFrom(params) - + IOUtils.getSuffix(Path.of(defaultIconName)); + + PathUtils.getSuffix(Path.of(defaultIconName)); IconType iconType = getLauncherIconType(params); if (iconType == IconType.NoIcon) { diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractBundler.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractBundler.java index b615176fd15..e28a444a045 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractBundler.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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,7 @@ import java.io.IOException; import java.nio.file.Path; import java.util.Map; +import jdk.jpackage.internal.util.FileUtils; /** @@ -55,7 +56,7 @@ public String toString() { @Override public void cleanup(Map<String, ? super Object> params) { try { - IOUtils.deleteRecursive( + FileUtils.deleteRecursive( StandardBundlerParam.TEMP_ROOT.fetchFrom(params)); } catch (IOException e) { Log.verbose(e.getMessage()); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java index 31228a8f5a3..256d292350a 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -59,6 +59,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.MENU_HINT; import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE; import static jdk.jpackage.internal.StandardBundlerParam.APP_STORE; +import jdk.jpackage.internal.util.XmlUtils; public final class AppImageFile { @@ -247,7 +248,7 @@ private static void save(Path appImageDir, addLauncherInfoSave = appImage.getAddLaunchers(); } - IOUtils.createXml(getPathInAppImage(appImageDir), xml -> { + XmlUtils.createXml(getPathInAppImage(appImageDir), xml -> { xml.writeStartElement("jpackage-state"); xml.writeAttribute("version", getVersion()); xml.writeAttribute("platform", getPlatform()); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java index 573109a004b..534786ada13 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,41 +25,15 @@ package jdk.jpackage.internal; -import jdk.internal.util.OperatingSystem; - import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.io.PrintStream; -import java.io.Writer; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.nio.file.FileVisitResult; import java.nio.file.Files; -import java.nio.file.CopyOption; import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicReference; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; -import javax.xml.transform.Result; -import javax.xml.transform.Source; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.stax.StAXResult; /** * IOUtils @@ -68,107 +42,6 @@ */ public class IOUtils { - public static void deleteRecursive(Path directory) throws IOException { - final AtomicReference<IOException> exception = new AtomicReference<>(); - - if (!Files.exists(directory)) { - return; - } - - Files.walkFileTree(directory, new SimpleFileVisitor<Path>() { - @Override - public FileVisitResult visitFile(Path file, - BasicFileAttributes attr) throws IOException { - if (OperatingSystem.isWindows()) { - Files.setAttribute(file, "dos:readonly", false); - } - try { - Files.delete(file); - } catch (IOException ex) { - exception.compareAndSet(null, ex); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult preVisitDirectory(Path dir, - BasicFileAttributes attr) throws IOException { - if (OperatingSystem.isWindows()) { - Files.setAttribute(dir, "dos:readonly", false); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException e) - throws IOException { - try { - Files.delete(dir); - } catch (IOException ex) { - exception.compareAndSet(null, ex); - } - return FileVisitResult.CONTINUE; - } - }); - if (exception.get() != null) { - throw exception.get(); - } - } - - public static void copyRecursive(Path src, Path dest, CopyOption... options) - throws IOException { - copyRecursive(src, dest, List.of(), options); - } - - public static void copyRecursive(Path src, Path dest, - final List<Path> excludes, CopyOption... options) - throws IOException { - - List<CopyAction> copyActions = new ArrayList<>(); - - Files.walkFileTree(src, new SimpleFileVisitor<Path>() { - @Override - public FileVisitResult preVisitDirectory(final Path dir, - final BasicFileAttributes attrs) { - if (isPathMatch(dir, excludes)) { - return FileVisitResult.SKIP_SUBTREE; - } else { - copyActions.add(new CopyAction(null, dest.resolve(src. - relativize(dir)))); - return FileVisitResult.CONTINUE; - } - } - - @Override - public FileVisitResult visitFile(final Path file, - final BasicFileAttributes attrs) { - if (!isPathMatch(file, excludes)) { - copyActions.add(new CopyAction(file, dest.resolve(src. - relativize(file)))); - } - return FileVisitResult.CONTINUE; - } - }); - - for (var copyAction : copyActions) { - copyAction.apply(options); - } - } - - private static record CopyAction(Path src, Path dest) { - void apply(CopyOption... options) throws IOException { - if (src == null) { - Files.createDirectories(dest); - } else { - Files.copy(src, dest, options); - } - } - } - - private static boolean isPathMatch(Path what, List<Path> paths) { - return paths.stream().anyMatch(what::endsWith); - } - public static void copyFile(Path sourceFile, Path destFile) throws IOException { Files.createDirectories(getParent(destFile)); @@ -314,90 +187,6 @@ static void writableOutputDir(Path outdir) throws PackagerException { } } - public static Path replaceSuffix(Path path, String suffix) { - Path parent = path.getParent(); - String filename = getFileName(path).toString().replaceAll("\\.[^.]*$", "") - + Optional.ofNullable(suffix).orElse(""); - return parent != null ? parent.resolve(filename) : Path.of(filename); - } - - public static Path addSuffix(Path path, String suffix) { - Path parent = path.getParent(); - String filename = getFileName(path).toString() + suffix; - return parent != null ? parent.resolve(filename) : Path.of(filename); - } - - public static String getSuffix(Path path) { - String filename = replaceSuffix(getFileName(path), null).toString(); - return getFileName(path).toString().substring(filename.length()); - } - - @FunctionalInterface - public static interface XmlConsumer { - void accept(XMLStreamWriter xml) throws IOException, XMLStreamException; - } - - public static void createXml(Path dstFile, XmlConsumer xmlConsumer) throws - IOException { - XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance(); - Files.createDirectories(getParent(dstFile)); - try (Writer w = Files.newBufferedWriter(dstFile)) { - // Wrap with pretty print proxy - XMLStreamWriter xml = (XMLStreamWriter) Proxy.newProxyInstance( - XMLStreamWriter.class.getClassLoader(), new Class<?>[]{ - XMLStreamWriter.class}, new PrettyPrintHandler( - xmlFactory.createXMLStreamWriter(w))); - - xml.writeStartDocument(); - xmlConsumer.accept(xml); - xml.writeEndDocument(); - xml.flush(); - xml.close(); - } catch (XMLStreamException ex) { - throw new IOException(ex); - } catch (IOException ex) { - throw ex; - } - } - - public static void mergeXmls(XMLStreamWriter xml, Collection<Source> sources) - throws XMLStreamException, IOException { - xml = (XMLStreamWriter) Proxy.newProxyInstance( - XMLStreamWriter.class.getClassLoader(), new Class<?>[]{ - XMLStreamWriter.class}, new SkipDocumentHandler(xml)); - - try { - TransformerFactory tf = TransformerFactory.newInstance(); - Result result = new StAXResult(xml); - for (var src : sources) { - tf.newTransformer().transform(src, result); - } - } catch (TransformerException ex) { - // Should never happen - throw new RuntimeException(ex); - } - } - - public static DocumentBuilderFactory initDocumentBuilderFactory() { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); - try { - dbf.setFeature( - "http://apache.org/xml/features/nonvalidating/load-external-dtd", - false); - } catch (ParserConfigurationException ex) { - throw new IllegalStateException(ex); - } - return dbf; - } - - public static DocumentBuilder initDocumentBuilder() { - try { - return initDocumentBuilderFactory().newDocumentBuilder(); - } catch (ParserConfigurationException ex) { - throw new IllegalStateException(ex); - } - } - public static Path getParent(Path p) { Path parent = p.getParent(); if (parent == null) { @@ -430,85 +219,4 @@ public static long getPID(Process p) { return -1; } } - - private static class PrettyPrintHandler implements InvocationHandler { - - PrettyPrintHandler(XMLStreamWriter target) { - this.target = target; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws - Throwable { - switch (method.getName()) { - case "writeStartElement": - // update state of parent node - if (depth > 0) { - hasChildElement.put(depth - 1, true); - } - // reset state of current node - hasChildElement.put(depth, false); - // indent for current depth - target.writeCharacters(EOL); - target.writeCharacters(repeat(depth, INDENT)); - depth++; - break; - case "writeEndElement": - depth--; - if (hasChildElement.get(depth) == true) { - target.writeCharacters(EOL); - target.writeCharacters(repeat(depth, INDENT)); - } - break; - case "writeProcessingInstruction": - case "writeEmptyElement": - // update state of parent node - if (depth > 0) { - hasChildElement.put(depth - 1, true); - } - // indent for current depth - target.writeCharacters(EOL); - target.writeCharacters(repeat(depth, INDENT)); - break; - default: - break; - } - method.invoke(target, args); - return null; - } - - private static String repeat(int d, String s) { - StringBuilder sb = new StringBuilder(); - while (d-- > 0) { - sb.append(s); - } - return sb.toString(); - } - - private final XMLStreamWriter target; - private int depth = 0; - private final Map<Integer, Boolean> hasChildElement = new HashMap<>(); - private static final String INDENT = " "; - private static final String EOL = "\n"; - } - - private static class SkipDocumentHandler implements InvocationHandler { - - SkipDocumentHandler(XMLStreamWriter target) { - this.target = target; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws - Throwable { - switch (method.getName()) { - case "writeStartDocument", "writeEndDocument" -> { - } - default -> method.invoke(target, args); - } - return null; - } - - private final XMLStreamWriter target; - } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PathGroup.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PathGroup.java index 24fb394e100..296164551a1 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PathGroup.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PathGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -35,6 +35,7 @@ import java.util.function.BiFunction; import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.jpackage.internal.util.FileUtils; /** @@ -232,7 +233,7 @@ public void createDirectory(Path dir) throws IOException { for (var entry: entries) { Path srcFile = entry.getKey(); if (Files.isDirectory(srcFile)) { - IOUtils.deleteRecursive(srcFile); + FileUtils.deleteRecursive(srcFile); } } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java index 718f186c954..0209eea584a 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java @@ -44,6 +44,7 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Stream; +import jdk.jpackage.internal.util.FileUtils; /** * StandardBundlerParam @@ -604,7 +605,7 @@ static void copyPredefinedRuntimeImage(Map<String, ? super Object> params, // copy whole runtime, need to skip jmods and src.zip final List<Path> excludes = Arrays.asList(Path.of("jmods"), Path.of("src.zip")); - IOUtils.copyRecursive(topImage, appLayout.runtimeHomeDirectory(), + FileUtils.copyRecursive(topImage, appLayout.runtimeHomeDirectory(), excludes, LinkOption.NOFOLLOW_LINKS); // if module-path given - copy modules to appDir/mods @@ -616,7 +617,7 @@ static void copyPredefinedRuntimeImage(Map<String, ? super Object> params, for (Path mp : modulePath) { if (!defaultModulePath.contains(mp)) { Files.createDirectories(dest); - IOUtils.copyRecursive(mp, dest); + FileUtils.copyRecursive(mp, dest); } } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java new file mode 100644 index 00000000000..71b8c3d6ddc --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2024, 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.jpackage.internal.util; + +import java.io.IOException; +import java.nio.file.CopyOption; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; +import jdk.internal.util.OperatingSystem; +import jdk.jpackage.internal.util.function.ExceptionBox; +import jdk.jpackage.internal.util.function.ThrowingConsumer; + +public final class FileUtils { + + public static void deleteRecursive(Path directory) throws IOException { + if (!Files.exists(directory)) { + return; + } + + var callback = new RecursiveDeleter(); + + Files.walkFileTree(directory, callback); + + if (callback.ex != null) { + throw callback.ex; + } + } + + public static void copyRecursive(Path src, Path dest, CopyOption... options) + throws IOException { + copyRecursive(src, dest, List.of(), options); + } + + public static void copyRecursive(Path src, Path dest, + final List<Path> excludes, CopyOption... options) + throws IOException { + + List<CopyAction> copyActions = new ArrayList<>(); + + Files.walkFileTree(src, new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult preVisitDirectory(final Path dir, + final BasicFileAttributes attrs) { + if (isPathMatch(dir, excludes)) { + return FileVisitResult.SKIP_SUBTREE; + } else { + copyActions.add(new CopyAction(null, dest.resolve(src. + relativize(dir)))); + return FileVisitResult.CONTINUE; + } + } + + @Override + public FileVisitResult visitFile(final Path file, + final BasicFileAttributes attrs) { + if (!isPathMatch(file, excludes)) { + copyActions.add(new CopyAction(file, dest.resolve(src. + relativize(file)))); + } + return FileVisitResult.CONTINUE; + } + }); + + for (var copyAction : copyActions) { + copyAction.apply(options); + } + } + + private static boolean isPathMatch(Path what, List<Path> paths) { + return paths.stream().anyMatch(what::endsWith); + } + + private static record CopyAction(Path src, Path dest) { + + void apply(CopyOption... options) throws IOException { + if (src == null) { + Files.createDirectories(dest); + } else { + Files.copy(src, dest, options); + } + } + } + + private static class RecursiveDeleter extends SimpleFileVisitor<Path> { + + @Override + public FileVisitResult visitFile(Path file, + BasicFileAttributes attr) throws IOException { + adjustAttributes(file); + runActionOnPath(Files::delete, file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, + BasicFileAttributes attr) throws IOException { + adjustAttributes(dir); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException e) + throws IOException { + runActionOnPath(Files::delete, dir); + return FileVisitResult.CONTINUE; + } + + private static void adjustAttributes(Path path) throws IOException { + if (OperatingSystem.isWindows()) { + Files.setAttribute(path, "dos:readonly", false); + } + } + + private void runActionOnPath(ThrowingConsumer<Path> action, Path path) { + try { + action.accept(path); + } catch (IOException ex) { + if (this.ex == null) { + this.ex = ex; + } + } catch (Throwable t) { + throw ExceptionBox.rethrowUnchecked(t); + } + } + + private IOException ex; + } +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PathUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PathUtils.java new file mode 100644 index 00000000000..267062a2031 --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PathUtils.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024, 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.jpackage.internal.util; + +import java.nio.file.Path; +import java.util.Optional; +import jdk.jpackage.internal.IOUtils; + +public final class PathUtils { + + public static String getSuffix(Path path) { + String filename = replaceSuffix(IOUtils.getFileName(path), null).toString(); + return IOUtils.getFileName(path).toString().substring(filename.length()); + } + + public static Path addSuffix(Path path, String suffix) { + Path parent = path.getParent(); + String filename = IOUtils.getFileName(path).toString() + suffix; + return parent != null ? parent.resolve(filename) : Path.of(filename); + } + + public static Path replaceSuffix(Path path, String suffix) { + Path parent = path.getParent(); + String filename = IOUtils.getFileName(path).toString().replaceAll("\\.[^.]*$", + "") + Optional.ofNullable(suffix).orElse(""); + return parent != null ? parent.resolve(filename) : Path.of(filename); + } + + public static Path resolveNullablePath(Path base, Path path) { + return Optional.ofNullable(path).map(base::resolve).orElse(null); + } +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PrettyPrintHandler.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PrettyPrintHandler.java new file mode 100644 index 00000000000..ffd5b764103 --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PrettyPrintHandler.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import javax.xml.stream.XMLStreamWriter; + +final class PrettyPrintHandler implements InvocationHandler { + + public PrettyPrintHandler(XMLStreamWriter target) { + this.target = target; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + switch (method.getName()) { + case "writeStartElement": + // update state of parent node + if (depth > 0) { + hasChildElement.put(depth - 1, true); + } + // reset state of current node + hasChildElement.put(depth, false); + // indent for current depth + target.writeCharacters(EOL); + target.writeCharacters(repeat(depth, INDENT)); + depth++; + break; + case "writeEndElement": + depth--; + if (hasChildElement.get(depth) == true) { + target.writeCharacters(EOL); + target.writeCharacters(repeat(depth, INDENT)); + } + break; + case "writeProcessingInstruction": + case "writeEmptyElement": + // update state of parent node + if (depth > 0) { + hasChildElement.put(depth - 1, true); + } + // indent for current depth + target.writeCharacters(EOL); + target.writeCharacters(repeat(depth, INDENT)); + break; + default: + break; + } + method.invoke(target, args); + return null; + } + + private static String repeat(int d, String s) { + StringBuilder sb = new StringBuilder(); + while (d-- > 0) { + sb.append(s); + } + return sb.toString(); + } + + private final XMLStreamWriter target; + private int depth = 0; + private final Map<Integer, Boolean> hasChildElement = new HashMap<>(); + private static final String INDENT = " "; + private static final String EOL = "\n"; +} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkPermission.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/SkipDocumentHandler.java similarity index 61% rename from src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkPermission.java rename to src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/SkipDocumentHandler.java index f1725e77ee2..283dac451a2 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkPermission.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/SkipDocumentHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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,21 +22,27 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.tools.jlink.internal; +package jdk.jpackage.internal.util; -import java.security.BasicPermission; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import javax.xml.stream.XMLStreamWriter; -/** - * The permission required to use jlink API. The permission target_name is - * "jlink". e.g.: permission jdk.tools.jlink.plugins.JlinkPermission "jlink"; - * - */ -public final class JlinkPermission extends BasicPermission { +final class SkipDocumentHandler implements InvocationHandler { - private static final long serialVersionUID = -3687912306077727801L; + public SkipDocumentHandler(XMLStreamWriter target) { + this.target = target; + } - public JlinkPermission(String name) { - super(name); + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + switch (method.getName()) { + case "writeStartDocument", "writeEndDocument" -> { + } + default -> method.invoke(target, args); + } + return null; } + private final XMLStreamWriter target; } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaIOPrintWriterAccess.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlConsumer.java similarity index 69% rename from src/java.base/share/classes/jdk/internal/access/JavaIOPrintWriterAccess.java rename to src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlConsumer.java index 8be54a76b0a..429be6aba05 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaIOPrintWriterAccess.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlConsumer.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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. + * 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 @@ -22,10 +20,15 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.internal.access; +package jdk.jpackage.internal.util; -import java.io.PrintWriter; +import java.io.IOException; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +@FunctionalInterface +public interface XmlConsumer { + + void accept(XMLStreamWriter xml) throws IOException, XMLStreamException; -public interface JavaIOPrintWriterAccess { - Object lock(PrintWriter pw); } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java new file mode 100644 index 00000000000..8012384b679 --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util; + +import java.io.IOException; +import java.io.Writer; +import java.lang.reflect.Proxy; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stax.StAXResult; +import jdk.jpackage.internal.IOUtils; + + +public final class XmlUtils { + + public static void createXml(Path dstFile, XmlConsumer xmlConsumer) throws + IOException { + XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance(); + Files.createDirectories(IOUtils.getParent(dstFile)); + try (Writer w = Files.newBufferedWriter(dstFile)) { + // Wrap with pretty print proxy + XMLStreamWriter xml = (XMLStreamWriter) Proxy.newProxyInstance(XMLStreamWriter.class.getClassLoader(), + new Class<?>[]{XMLStreamWriter.class}, + new PrettyPrintHandler(xmlFactory.createXMLStreamWriter(w))); + xml.writeStartDocument(); + xmlConsumer.accept(xml); + xml.writeEndDocument(); + xml.flush(); + xml.close(); + } catch (XMLStreamException ex) { + throw new IOException(ex); + } catch (IOException ex) { + throw ex; + } + } + + public static void mergeXmls(XMLStreamWriter xml, Collection<Source> sources) + throws XMLStreamException, IOException { + xml = (XMLStreamWriter) Proxy.newProxyInstance(XMLStreamWriter.class.getClassLoader(), + new Class<?>[]{XMLStreamWriter.class}, + new SkipDocumentHandler(xml)); + try { + TransformerFactory tf = TransformerFactory.newInstance(); + Result result = new StAXResult(xml); + for (Source src : sources) { + tf.newTransformer().transform(src, result); + } + } catch (TransformerException ex) { + // Should never happen + throw new RuntimeException(ex); + } + } + + public static DocumentBuilder initDocumentBuilder() { + try { + return initDocumentBuilderFactory().newDocumentBuilder(); + } catch (ParserConfigurationException ex) { + throw new IllegalStateException(ex); + } + } + + public static DocumentBuilderFactory initDocumentBuilderFactory() { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); + try { + dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", + false); + } catch (ParserConfigurationException ex) { + throw new IllegalStateException(ex); + } + return dbf; + } +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java new file mode 100644 index 00000000000..55f2964445f --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util.function; + +import java.lang.reflect.InvocationTargetException; + +public class ExceptionBox extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public static RuntimeException rethrowUnchecked(Throwable throwable) { + if (throwable instanceof RuntimeException err) { + throw err; + } + + if (throwable instanceof Error err) { + throw err; + } + + if (throwable instanceof InvocationTargetException err) { + throw rethrowUnchecked(err.getCause()); + } + + throw new ExceptionBox(throwable); + } + + private ExceptionBox(Throwable throwable) { + super(throwable); + } +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java new file mode 100644 index 00000000000..e5b7704a92e --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util.function; + +import java.util.function.BiConsumer; + +@FunctionalInterface +public interface ThrowingBiConsumer<T, U> { + + void accept(T t, U u) throws Throwable; + + public static <T, U> BiConsumer<T, U> toBiConsumer( + ThrowingBiConsumer<T, U> v) { + return (t, u) -> { + try { + v.accept(t, u); + } catch (Throwable ex) { + throw ExceptionBox.rethrowUnchecked(ex); + } + }; + } +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java new file mode 100644 index 00000000000..a8119f25bdb --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util.function; + +import java.util.function.BiFunction; + +@FunctionalInterface +public interface ThrowingBiFunction<T, U, R> { + + R apply(T t, U u) throws Throwable; + + public static <T, U, R> BiFunction<T, U, R> toBiFunction( + ThrowingBiFunction<T, U, R> v) { + return (t, u) -> { + try { + return v.apply(t, u); + } catch (Throwable ex) { + throw ExceptionBox.rethrowUnchecked(ex); + } + }; + } + +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java new file mode 100644 index 00000000000..5ca33c22d92 --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util.function; + +import java.util.function.Consumer; + +@FunctionalInterface +public interface ThrowingConsumer<T> { + + void accept(T t) throws Throwable; + + public static <T> Consumer<T> toConsumer(ThrowingConsumer<T> v) { + return o -> { + try { + v.accept(o); + } catch (Throwable ex) { + throw ExceptionBox.rethrowUnchecked(ex); + } + }; + } + +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java new file mode 100644 index 00000000000..db6b1d26005 --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util.function; + +import java.util.function.Function; + +@FunctionalInterface +public interface ThrowingFunction<T, R> { + + R apply(T t) throws Throwable; + + public static <T, R> Function<T, R> toFunction(ThrowingFunction<T, R> v) { + return t -> { + try { + return v.apply(t); + } catch (Throwable ex) { + throw ExceptionBox.rethrowUnchecked(ex); + } + }; + } + +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java new file mode 100644 index 00000000000..7f3fcda536c --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util.function; + +@FunctionalInterface +public interface ThrowingRunnable { + + void run() throws Throwable; + + public static Runnable toRunnable(ThrowingRunnable v) { + return () -> { + try { + v.run(); + } catch (Throwable ex) { + throw ExceptionBox.rethrowUnchecked(ex); + } + }; + } + +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java new file mode 100644 index 00000000000..2f5ef135875 --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util.function; + +import java.util.function.Supplier; + +@FunctionalInterface +public interface ThrowingSupplier<T> { + + T get() throws Throwable; + + public static <T> Supplier<T> toSupplier(ThrowingSupplier<T> v) { + return () -> { + try { + return v.get(); + } catch (Throwable ex) { + throw ExceptionBox.rethrowUnchecked(ex); + } + }; + } + +} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java new file mode 100644 index 00000000000..27a3e2f30f5 --- /dev/null +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.internal.util.function; + +import java.util.function.UnaryOperator; + +@FunctionalInterface +public interface ThrowingUnaryOperator<T> { + + T apply(T t) throws Throwable; + + public static <T> UnaryOperator<T> toUnaryOperator( + ThrowingUnaryOperator<T> v) { + return t -> { + try { + return v.apply(t); + } catch (Throwable ex) { + throw ExceptionBox.rethrowUnchecked(ex); + } + }; + } + +} diff --git a/src/jdk.jpackage/share/man/jpackage.1 b/src/jdk.jpackage/share/man/jpackage.1 deleted file mode 100644 index 09d340ec033..00000000000 --- a/src/jdk.jpackage/share/man/jpackage.1 +++ /dev/null @@ -1,834 +0,0 @@ -.\" Copyright (c) 2018, 2024, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JPACKAGE" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jpackage - tool for packaging self-contained Java applications. -.SH SYNOPSIS -.PP -\f[V]jpackage\f[R] [\f[I]options\f[R]] -.TP -\f[I]options\f[R] -Command-line options separated by spaces. -See \f[B]jpackage Options\f[R]. -.SH DESCRIPTION -.PP -The \f[V]jpackage\f[R] tool will take as input a Java application and a -Java run-time image, and produce a Java application image that includes -all the necessary dependencies. -It will be able to produce a native package in a platform-specific -format, such as an exe on Windows or a dmg on macOS. -Each format must be built on the platform it runs on, there is no -cross-platform support. -The tool will have options that allow packaged applications to be -customized in various ways. -.SH JPACKAGE OPTIONS -.SS Generic Options: -.TP -\f[V]\[at]\f[R]\f[I]filename\f[R] -Read options from a file. -.RS -.PP -This option can be used multiple times. -.RE -.TP -\f[V]--type\f[R] or \f[V]-t\f[R] \f[I]type\f[R] -The type of package to create -.RS -.PP -Valid values are: {\[dq]app-image\[dq], \[dq]exe\[dq], \[dq]msi\[dq], -\[dq]rpm\[dq], \[dq]deb\[dq], \[dq]pkg\[dq], \[dq]dmg\[dq]} -.PP -If this option is not specified a platform dependent default type will -be created. -.RE -.TP -\f[V]--app-version\f[R] \f[I]version\f[R] -Version of the application and/or package -.TP -\f[V]--copyright\f[R] \f[I]copyright\f[R] -Copyright for the application -.TP -\f[V]--description\f[R] \f[I]description\f[R] -Description of the application -.TP -\f[V]--help\f[R] or \f[V]-h\f[R] -Print the usage text with a list and description of each valid option -for the current platform to the output stream, and exit. -.TP -\f[V]--icon\f[R] \f[I]path\f[R] -Path of the icon of the application package -.RS -.PP -(absolute path or relative to the current directory) -.RE -.TP -\f[V]--name\f[R] or \f[V]-n\f[R] \f[I]name\f[R] -Name of the application and/or package -.TP -\f[V]--dest\f[R] or \f[V]-d\f[R] \f[I]destination\f[R] -Path where generated output file is placed -.RS -.PP -(absolute path or relative to the current directory). -.PP -Defaults to the current working directory. -.RE -.TP -\f[V]--resource-dir\f[R] \f[I]path\f[R] -Path to override jpackage resources -.RS -.PP -(absolute path or relative to the current directory) -.PP -Icons, template files, and other resources of jpackage can be -over-ridden by adding replacement resources to this directory. -.RE -.TP -\f[V]--temp\f[R] \f[I]directory\f[R] -Path of a new or empty directory used to create temporary files -.RS -.PP -(absolute path or relative to the current directory) -.PP -If specified, the temp dir will not be removed upon the task completion -and must be removed manually. -.PP -If not specified, a temporary directory will be created and removed upon -the task completion. -.RE -.TP -\f[V]--vendor\f[R] \f[I]vendor\f[R] -Vendor of the application -.TP -\f[V]--verbose\f[R] -Enables verbose output. -.TP -\f[V]--version\f[R] -Print the product version to the output stream and exit. -.SS Options for creating the runtime image: -.TP -\f[V]--add-modules\f[R] \f[I]module-name\f[R] [\f[V],\f[R]\f[I]module-name\f[R]...] -A comma (\[dq],\[dq]) separated list of modules to add -.RS -.PP -This module list, along with the main module (if specified) will be -passed to jlink as the --add-module argument. -If not specified, either just the main module (if --module is -specified), or the default set of modules (if --main-jar is specified) -are used. -.PP -This option can be used multiple times. -.RE -.TP -\f[V]--module-path\f[R] or \f[V]-p\f[R] \f[I]module-path\f[R] [\f[V],\f[R]\f[I]module-path\f[R]...] -A File.pathSeparator separated list of paths -.RS -.PP -Each path is either a directory of modules or the path to a modular jar, -and is absolute or relative to the current directory. -.PP -This option can be used multiple times. -.RE -.TP -\f[V]--jlink-options\f[R] \f[I]options\f[R] -A space separated list of options to pass to jlink -.RS -.PP -If not specified, defaults to \[dq]--strip-native-commands --strip-debug ---no-man-pages --no-header-files\[dq] -.PP -This option can be used multiple times. -.RE -.TP -\f[V]--runtime-image\f[R] \f[I]directory\f[R] -Path of the predefined runtime image that will be copied into the -application image -.RS -.PP -(absolute path or relative to the current directory) -.PP -If --runtime-image is not specified, jpackage will run jlink to create -the runtime image using options specified by --jlink-options. -.RE -.SS Options for creating the application image: -.TP -\f[V]--input\f[R] or \f[V]-i\f[R] \f[I]directory\f[R] -Path of the input directory that contains the files to be packaged -.RS -.PP -(absolute path or relative to the current directory) -.PP -All files in the input directory will be packaged into the application -image. -.RE -.TP -\f[V]--app-content\f[R] \f[I]additional-content\f[R] [\f[V],\f[R]\f[I]additional-content\f[R]...] -A comma separated list of paths to files and/or directories to add to -the application payload. -.RS -.PP -This option can be used more than once. -.RE -.SS Options for creating the application launcher(s): -.TP -\f[V]--add-launcher\f[R] \f[I]name\f[R]=\f[I]path\f[R] -Name of launcher, and a path to a Properties file that contains a list -of key, value pairs -.RS -.PP -(absolute path or relative to the current directory) -.PP -The keys \[dq]module\[dq], \[dq]main-jar\[dq], \[dq]main-class\[dq], -\[dq]description\[dq], \[dq]arguments\[dq], \[dq]java-options\[dq], -\[dq]icon\[dq], \[dq]launcher-as-service\[dq], \[dq]win-console\[dq], -\[dq]win-shortcut\[dq], \[dq]win-menu\[dq], and \[dq]linux-shortcut\[dq] -can be used. -.PP -These options are added to, or used to overwrite, the original command -line options to build an additional alternative launcher. -The main application launcher will be built from the command line -options. -Additional alternative launchers can be built using this option, and -this option can be used multiple times to build multiple additional -launchers. -.RE -.TP -\f[V]--arguments\f[R] \f[I]arguments\f[R] -Command line arguments to pass to the main class if no command line -arguments are given to the launcher -.RS -.PP -This option can be used multiple times. -.RE -.TP -\f[V]--java-options\f[R] \f[I]options\f[R] -Options to pass to the Java runtime -.RS -.PP -This option can be used multiple times. -.RE -.TP -\f[V]--main-class\f[R] \f[I]class-name\f[R] -Qualified name of the application main class to execute -.RS -.PP -This option can only be used if --main-jar is specified. -.RE -.TP -\f[V]--main-jar\f[R] \f[I]main-jar\f[R] -The main JAR of the application; containing the main class (specified as -a path relative to the input path) -.RS -.PP -Either --module or --main-jar option can be specified but not both. -.RE -.TP -\f[V]--module\f[R] or \f[V]-m\f[R] \f[I]module-name\f[R][/\f[I]main-class\f[R]] -The main module (and optionally main class) of the application -.RS -.PP -This module must be located on the module path. -.PP -When this option is specified, the main module will be linked in the -Java runtime image. -Either --module or --main-jar option can be specified but not both. -.RE -.SS Platform dependent options for creating the application launcher: -.SS Windows platform options (available only when running on Windows): -.TP -\f[V]--win-console\f[R] -Creates a console launcher for the application, should be specified for -application which requires console interactions -.SS macOS platform options (available only when running on macOS): -.TP -\f[V]--mac-package-identifier\f[R] \f[I]identifier\f[R] -An identifier that uniquely identifies the application for macOS -.RS -.PP -Defaults to the main class name. -.PP -May only use alphanumeric (A-Z,a-z,0-9), hyphen (-), and period (.) -characters. -.RE -.TP -\f[V]--mac-package-name\f[R] \f[I]name\f[R] -Name of the application as it appears in the Menu Bar -.RS -.PP -This can be different from the application name. -.PP -This name must be less than 16 characters long and be suitable for -displaying in the menu bar and the application Info window. -Defaults to the application name. -.RE -.TP -\f[V]--mac-package-signing-prefix\f[R] \f[I]prefix\f[R] -When signing the application package, this value is prefixed to all -components that need to be signed that don\[aq]t have an existing -package identifier. -.TP -\f[V]--mac-sign\f[R] -Request that the package or the predefined application image be signed. -.TP -\f[V]--mac-signing-keychain\f[R] \f[I]keychain-name\f[R] -Name of the keychain to search for the signing identity -.RS -.PP -If not specified, the standard keychains are used. -.RE -.TP -\f[V]--mac-signing-key-user-name\f[R] \f[I]name\f[R] -Team or user name portion in Apple signing identities -.TP -\f[V]--mac-app-store\f[R] -Indicates that the jpackage output is intended for the Mac App Store. -.TP -\f[V]--mac-entitlements\f[R] \f[I]path\f[R] -Path to file containing entitlements to use when signing executables and -libraries in the bundle -.TP -\f[V]--mac-app-category\f[R] \f[I]category\f[R] -String used to construct LSApplicationCategoryType in application plist -.RS -.PP -The default value is \[dq]utilities\[dq]. -.RE -.SS Options for creating the application package: -.TP -\f[V]--about-url\f[R] \f[I]url\f[R] -URL of the application\[aq]s home page -.TP -\f[V]--app-image\f[R] \f[I]directory\f[R] -Location of the predefined application image that is used to build an -installable package (on all platforms) or to be signed (on macOS) -.RS -.PP -(absolute path or relative to the current directory) -.RE -.TP -\f[V]--file-associations\f[R] \f[I]path\f[R] -Path to a Properties file that contains list of key, value pairs -.RS -.PP -(absolute path or relative to the current directory) -.PP -The keys \[dq]extension\[dq], \[dq]mime-type\[dq], \[dq]icon\[dq], and -\[dq]description\[dq] can be used to describe the association. -.PP -This option can be used multiple times. -.RE -.TP -\f[V]--install-dir\f[R] \f[I]path\f[R] -Absolute path of the installation directory of the application (on macOS -or linux), or relative sub-path of the installation directory such as -\[dq]Program Files\[dq] or \[dq]AppData\[dq] (on Windows) -.TP -\f[V]--license-file\f[R] \f[I]path\f[R] -Path to the license file -.RS -.PP -(absolute path or relative to the current directory) -.RE -.TP -\f[V]--runtime-image\f[R] \f[I]path\f[R] -Path of the predefined runtime image to install -.RS -.PP -(absolute path or relative to the current directory) -.PP -Option is required when creating a runtime installer. -.RE -.TP -\f[V]--launcher-as-service\f[R] -Request to create an installer that will register the main application -launcher as a background service-type application. -.SS Platform dependent options for creating the application package: -.SS Windows platform options (available only when running on Windows): -.TP -\f[V]--win-dir-chooser\f[R] -Adds a dialog to enable the user to choose a directory in which the -product is installed. -.TP -\f[V]--win-help-url\f[R] \f[I]url\f[R] -URL where user can obtain further information or technical support -.TP -\f[V]--win-menu\f[R] -Request to add a Start Menu shortcut for this application -.TP -\f[V]--win-menu-group\f[R] \f[I]menu-group-name\f[R] -Start Menu group this application is placed in -.TP -\f[V]--win-per-user-install\f[R] -Request to perform an install on a per-user basis -.TP -\f[V]--win-shortcut\f[R] -Request to create a desktop shortcut for this application -.TP -\f[V]--win-shortcut-prompt\f[R] -Adds a dialog to enable the user to choose if shortcuts will be created -by installer -.TP -\f[V]--win-update-url\f[R] \f[I]url\f[R] -URL of available application update information -.TP -\f[V]--win-upgrade-uuid\f[R] \f[I]id\f[R] -UUID associated with upgrades for this package -.SS Linux platform options (available only when running on Linux): -.TP -\f[V]--linux-package-name\f[R] \f[I]name\f[R] -Name for Linux package -.RS -.PP -Defaults to the application name. -.RE -.TP -\f[V]--linux-deb-maintainer\f[R] \f[I]email-address\f[R] -Maintainer for .deb bundle -.TP -\f[V]--linux-menu-group\f[R] \f[I]menu-group-name\f[R] -Menu group this application is placed in -.TP -\f[V]--linux-package-deps\f[R] -Required packages or capabilities for the application -.TP -\f[V]--linux-rpm-license-type\f[R] \f[I]type\f[R] -Type of the license (\[dq]License: \f[I]value\f[R]\[dq] of the RPM -\&.spec) -.TP -\f[V]--linux-app-release\f[R] \f[I]release\f[R] -Release value of the RPM <name>.spec file or Debian revision value of -the DEB control file -.TP -\f[V]--linux-app-category\f[R] \f[I]category-value\f[R] -Group value of the RPM /.spec file or Section value of DEB control file -.TP -\f[V]--linux-shortcut\f[R] -Creates a shortcut for the application. -.SS macOS platform options (available only when running on macOS): -.TP -\f[V]--mac-dmg-content\f[R] \f[I]additional-content\f[R] [\f[V],\f[R]\f[I]additional-content\f[R]...] -Include all the referenced content in the dmg. -.RS -.PP -This option can be used more than once. -.RE -.SH JPACKAGE EXAMPLES -.IP -.nf -\f[CB] -Generate an application package suitable for the host system: -\f[R] -.fi -.IP -.nf -\f[CB] -For a modular application: - jpackage -n name -p modulePath -m moduleName/className -For a non-modular application: - jpackage -i inputDir -n name \[rs] - --main-class className --main-jar myJar.jar -From a pre-built application image: - jpackage -n name --app-image appImageDir -\f[R] -.fi -.IP -.nf -\f[CB] -Generate an application image: -\f[R] -.fi -.IP -.nf -\f[CB] -For a modular application: - jpackage --type app-image -n name -p modulePath \[rs] - -m moduleName/className -For a non-modular application: - jpackage --type app-image -i inputDir -n name \[rs] - --main-class className --main-jar myJar.jar -To provide your own options to jlink, run jlink separately: - jlink --output appRuntimeImage -p modulePath \[rs] - --add-modules moduleName \[rs] - --no-header-files [<additional jlink options>...] - jpackage --type app-image -n name \[rs] - -m moduleName/className --runtime-image appRuntimeImage -\f[R] -.fi -.IP -.nf -\f[CB] -Generate a Java runtime package: -\f[R] -.fi -.IP -.nf -\f[CB] -jpackage -n name --runtime-image <runtime-image> -\f[R] -.fi -.IP -.nf -\f[CB] -Sign the predefined application image (on macOS): -\f[R] -.fi -.IP -.nf -\f[CB] -jpackage --type app-image --app-image <app-image> \[rs] - --mac-sign [<additional signing options>...] - -Note: the only additional options that are permitted in this mode are: - the set of additional mac signing options and --verbose -\f[R] -.fi -.SH JPACKAGE RESOURCE DIRECTORY -.PP -Icons, template files, and other resources of jpackage can be -over-ridden by adding replacement resources to this directory. -jpackage will lookup files by specific names in the resource directory. -.SS Resource directory files considered only when running on Linux: -.TP -\f[V]<launcher-name>.png\f[R] -Application launcher icon -.RS -.PP -Default resource is \f[I]JavaApp.png\f[R] -.RE -.TP -\f[V]<launcher-name>.desktop\f[R] -A desktop file to be used with \f[V]xdg-desktop-menu\f[R] command -.RS -.PP -Considered with application launchers registered for file associations -and/or have an icon -.PP -Default resource is \f[I]template.desktop\f[R] -.RE -.SS Resource directory files considered only when building Linux DEB/RPM installer: -.TP -\f[V]<package-name>-<launcher-name>.service\f[R] -systemd unit file for application launcher registered as a background -service-type application -.RS -.PP -Default resource is \f[I]unit-template.service\f[R] -.RE -.SS Resource directory files considered only when building Linux RPM installer: -.TP -\f[V]<package-name>.spec\f[R] -RPM spec file -.RS -.PP -Default resource is \f[I]template.spec\f[R] -.RE -.SS Resource directory files considered only when building Linux DEB installer: -.TP -\f[V]control\f[R] -Control file -.RS -.PP -Default resource is \f[I]template.control\f[R] -.RE -.TP -\f[V]copyright\f[R] -Copyright file -.RS -.PP -Default resource is \f[I]template.copyright\f[R] -.RE -.TP -\f[V]preinstall\f[R] -Pre-install shell script -.RS -.PP -Default resource is \f[I]template.preinstall\f[R] -.RE -.TP -\f[V]prerm\f[R] -Pre-remove shell script -.RS -.PP -Default resource is \f[I]template.prerm\f[R] -.RE -.TP -\f[V]postinstall\f[R] -Post-install shell script -.RS -.PP -Default resource is \f[I]template.postinstall\f[R] -.RE -.TP -\f[V]postrm\f[R] -Post-remove shell script -.RS -.PP -Default resource is \f[I]template.postrm\f[R] -.RE -.SS Resource directory files considered only when running on Windows: -.TP -\f[V]<launcher-name>.ico\f[R] -Application launcher icon -.RS -.PP -Default resource is \f[I]JavaApp.ico\f[R] -.RE -.TP -\f[V]<launcher-name>.properties\f[R] -Properties file for application launcher executable -.RS -.PP -Default resource is \f[I]WinLauncher.template\f[R] -.RE -.SS Resource directory files considered only when building Windows MSI/EXE installer: -.TP -\f[V]<application-name>-post-image.wsf\f[R] -A Windows Script File (WSF) to run after building application image -.TP -\f[V]main.wxs\f[R] -Main WiX project file -.RS -.PP -Default resource is \f[I]main.wxs\f[R] -.RE -.TP -\f[V]overrides.wxi\f[R] -Overrides WiX project file -.RS -.PP -Default resource is \f[I]overrides.wxi\f[R] -.RE -.TP -\f[V]service-installer.exe\f[R] -Service installer executable -.RS -.PP -Considered if some application launchers are registered as background -service-type applications -.RE -.TP -\f[V]<launcher-name>-service-install.wxi\f[R] -Service installer WiX project file -.RS -.PP -Considered if some application launchers are registered as background -service-type applications -.PP -Default resource is \f[I]service-install.wxi\f[R] -.RE -.TP -\f[V]<launcher-name>-service-config.wxi\f[R] -Service installer WiX project file -.RS -.PP -Considered if some application launchers are registered as background -service-type applications -.PP -Default resource is \f[I]service-config.wxi\f[R] -.RE -.TP -\f[V]InstallDirNotEmptyDlg.wxs\f[R] -WiX project file for installer UI dialog checking installation directory -doesn\[aq]t exist or is empty -.RS -.PP -Default resource is \f[I]InstallDirNotEmptyDlg.wxs\f[R] -.RE -.TP -\f[V]ShortcutPromptDlg.wxs\f[R] -WiX project file for installer UI dialog configuring shortcuts -.RS -.PP -Default resource is \f[I]ShortcutPromptDlg.wxs\f[R] -.RE -.TP -\f[V]bundle.wxf\f[R] -WiX project file with the hierarchy of components of application image -.TP -\f[V]ui.wxf\f[R] -WiX project file for installer UI -.SS Resource directory files considered only when building Windows EXE installer: -.TP -\f[V]WinInstaller.properties\f[R] -Properties file for the installer executable -.RS -.PP -Default resource is \f[I]WinInstaller.template\f[R] -.RE -.TP -\f[V]<package-name>-post-msi.wsf\f[R] -A Windows Script File (WSF) to run after building embedded MSI installer -for EXE installer -.SS Resource directory files considered only when running on macOS: -.TP -\f[V]<launcher-name>.icns\f[R] -Application launcher icon -.RS -.PP -Default resource is \f[I]JavaApp.icns\f[R] -.RE -.TP -\f[V]Info.plist\f[R] -Application property list file -.RS -.PP -Default resource is \f[I]Info-lite.plist.template\f[R] -.RE -.TP -\f[V]Runtime-Info.plist\f[R] -Java Runtime property list file -.RS -.PP -Default resource is \f[I]Runtime-Info.plist.template\f[R] -.RE -.TP -\f[V]<application-name>.entitlements\f[R] -Signing entitlements property list file -.RS -.PP -Default resource is \f[I]sandbox.plist\f[R] -.RE -.SS Resource directory files considered only when building macOS PKG/DMG installer: -.TP -\f[V]<package-name>-post-image.sh\f[R] -Shell script to run after building application image -.SS Resource directory files considered only when building macOS PKG installer: -.TP -\f[V]uninstaller\f[R] -Uninstaller shell script -.RS -.PP -Considered if some application launchers are registered as background -service-type applications -.PP -Default resource is \f[I]uninstall.command.template\f[R] -.RE -.TP -\f[V]preinstall\f[R] -Pre-install shell script -.RS -.PP -Default resource is \f[I]preinstall.template\f[R] -.RE -.TP -\f[V]postinstall\f[R] -Post-install shell script -.RS -.PP -Default resource is \f[I]postinstall.template\f[R] -.RE -.TP -\f[V]services-preinstall\f[R] -Pre-install shell script for services package -.RS -.PP -Considered if some application launchers are registered as background -service-type applications -.PP -Default resource is \f[I]services-preinstall.template\f[R] -.RE -.TP -\f[V]services-postinstall\f[R] -Post-install shell script for services package -.RS -.PP -Considered if some application launchers are registered as background -service-type applications -.PP -Default resource is \f[I]services-postinstall.template\f[R] -.RE -.TP -\f[V]<package-name>-background.png\f[R] -Background image -.RS -.PP -Default resource is \f[I]background_pkg.png\f[R] -.RE -.TP -\f[V]<package-name>-background-darkAqua.png\f[R] -Dark background image -.RS -.PP -Default resource is \f[I]background_pkg.png\f[R] -.RE -.TP -\f[V]product-def.plist\f[R] -Package property list file -.RS -.PP -Default resource is \f[I]product-def.plist\f[R] -.RE -.TP -\f[V]<package-name>-<launcher-name>.plist\f[R] -launchd property list file for application launcher registered as a -background service-type application -.RS -.PP -Default resource is \f[I]launchd.plist.template\f[R] -.RE -.SS Resource directory files considered only when building macOS DMG installer: -.TP -\f[V]<package-name>-dmg-setup.scpt\f[R] -Setup AppleScript script -.RS -.PP -Default resource is \f[I]DMGsetup.scpt\f[R] -.RE -.TP -\f[V]<package-name>-license.plist\f[R] -License property list file -.RS -.PP -Default resource is \f[I]lic_template.plist\f[R] -.RE -.TP -\f[V]<package-name>-background.tiff\f[R] -Background image -.RS -.PP -Default resource is \f[I]background_dmg.tiff\f[R] -.RE -.TP -\f[V]<package-name>-volume.icns\f[R] -Volume icon -.RS -.PP -Default resource is \f[I]JavaApp.icns\f[R] -.RE diff --git a/src/jdk.jpackage/share/man/jpackage.md b/src/jdk.jpackage/share/man/jpackage.md new file mode 100644 index 00000000000..9d7a3003c24 --- /dev/null +++ b/src/jdk.jpackage/share/man/jpackage.md @@ -0,0 +1,799 @@ +--- +# Copyright (c) 2018, 2024, 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. +# + +title: 'JPACKAGE(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jpackage - tool for packaging self-contained Java applications. + +## Synopsis + +`jpackage` \[*options*\] + + +*options* +: Command-line options separated by spaces. See [jpackage Options]. + +## Description + +The `jpackage` tool will take as input a Java application and a Java run-time image, and produce a Java application image that includes all the necessary dependencies. It will be able to produce a native package in a platform-specific format, such as an exe on Windows or a dmg on macOS. Each format must be built on the platform it runs on, there is no cross-platform support. The tool will have options that allow packaged applications to be customized in various ways. + + +## jpackage Options + +### Generic Options: + +`@`*filename* + +: Read options from a file. + + This option can be used multiple times. + +<a id="option-type">`--type` or `-t` *type*</a> +: The type of package to create + + Valid values are: {"app-image", "exe", "msi", "rpm", "deb", "pkg", "dmg"} + + If this option is not specified a platform dependent + default type will be created. + +<a id="option-app-version">`--app-version` *version*</a> + +: Version of the application and/or package + +<a id="option-copyright">`--copyright` *copyright*</a> + +: Copyright for the application + +<a id="option-description">`--description` *description*</a> + +: Description of the application + +<a id="option-help">`--help` or `-h`</a> + +: Print the usage text with a list and description of each valid + option for the current platform to the output stream, and exit. + +<a id="option-icon">`--icon` *path*</a> + +: Path of the icon of the application package + + (absolute path or relative to the current directory) + +<a id="option-name">`--name` or `-n` *name*</a> + +: Name of the application and/or package + +<a id="option-dest">`--dest` or `-d` *destination*</a> + +: Path where generated output file is placed + + (absolute path or relative to the current directory). + + Defaults to the current working directory. + +<a id="option-resource-dir">`--resource-dir` *path*</a> + +: Path to override jpackage resources + + (absolute path or relative to the current directory) + + Icons, template files, and other resources of jpackage can be + over-ridden by adding replacement resources to this directory. + +<a id="option-temp">`--temp` *directory*</a> + +: Path of a new or empty directory used to create temporary files + + (absolute path or relative to the current directory) + + If specified, the temp dir will not be removed upon the task + completion and must be removed manually. + + If not specified, a temporary directory will be created and + removed upon the task completion. + +<a id="option-vendor">`--vendor` *vendor*</a> + +: Vendor of the application + +<a id="option-verbose">`--verbose`</a> + +: Enables verbose output. + +<a id="option-version">`--version`</a> + +: Print the product version to the output stream and exit. + +### Options for creating the runtime image: + + +<a id="option-add-modules">`--add-modules` *module-name* \[`,`*module-name*...\]</a> + +: A comma (",") separated list of modules to add + + This module list, along with the main module (if specified) + will be passed to jlink as the --add-module argument. + If not specified, either just the main module (if --module is + specified), or the default set of modules (if --main-jar is + specified) are used. + + This option can be used multiple times. + +<a id="option-module-path">`--module-path` or `-p` *module-path* \[`,`*module-path*...\]</a> + +: A File.pathSeparator separated list of paths + + Each path is either a directory of modules or the path to a + modular jar, and is absolute or relative to the current directory. + + This option can be used multiple times. + +<a id="option-jlink-options">`--jlink-options` *options*</a> + +: A space separated list of options to pass to jlink + + If not specified, defaults to "--strip-native-commands + --strip-debug --no-man-pages --no-header-files" + + This option can be used multiple times. + +<a id="option-runtime-image">`--runtime-image` *directory*</a> + +: Path of the predefined runtime image that will be copied into + the application image + + (absolute path or relative to the current directory) + + If --runtime-image is not specified, jpackage will run jlink to + create the runtime image using options specified by --jlink-options. + +### Options for creating the application image: + +<a id="option-input">`--input` or `-i` *directory*</a> + +: Path of the input directory that contains the files to be packaged + + (absolute path or relative to the current directory) + + All files in the input directory will be packaged into the + application image. + +<a id="option-app-content">`--app-content` *additional-content* \[`,`*additional-content*...\]</a> + +: A comma separated list of paths to files and/or directories + to add to the application payload. + + This option can be used more than once. + +### Options for creating the application launcher(s): + + +<a id="option-add-launcher">`--add-launcher` *name*=*path*</a> + +: Name of launcher, and a path to a Properties file that contains + a list of key, value pairs + + (absolute path or relative to the current directory) + + The keys "module", "main-jar", "main-class", "description", + "arguments", "java-options", "icon", "launcher-as-service", + "win-console", "win-shortcut", "win-menu", and "linux-shortcut" + can be used. + + These options are added to, or used to overwrite, the original + command line options to build an additional alternative launcher. + The main application launcher will be built from the command line + options. Additional alternative launchers can be built using + this option, and this option can be used multiple times to + build multiple additional launchers. + +<a id="option-arguments">`--arguments` *arguments*</a> + +: Command line arguments to pass to the main class if no command + line arguments are given to the launcher + + This option can be used multiple times. + +<a id="option-java-options">`--java-options` *options*</a> + +: Options to pass to the Java runtime + + This option can be used multiple times. + +<a id="option-main-class">`--main-class` *class-name*</a> + +: Qualified name of the application main class to execute + + This option can only be used if --main-jar is specified. + +<a id="option-main-jar">`--main-jar` *main-jar*</a> + +: The main JAR of the application; containing the main class + (specified as a path relative to the input path) + + Either --module or --main-jar option can be specified but not + both. + +<a id="option-module">`--module` or `-m` *module-name*[/*main-class*]</a> + +: The main module (and optionally main class) of the application + + This module must be located on the module path. + + When this option is specified, the main module will be linked + in the Java runtime image. Either --module or --main-jar + option can be specified but not both. + + +### Platform dependent options for creating the application launcher: + + +#### Windows platform options (available only when running on Windows): + +<a id="option-win-console">`--win-console`</a> + +: Creates a console launcher for the application, should be + specified for application which requires console interactions + +#### macOS platform options (available only when running on macOS): + +<a id="option-mac-package-identifier">`--mac-package-identifier` *identifier*</a> + +: An identifier that uniquely identifies the application for macOS + + Defaults to the main class name. + + May only use alphanumeric (A-Z,a-z,0-9), hyphen (-), + and period (.) characters. + +<a id="option-mac-package-name">`--mac-package-name` *name*</a> + +: Name of the application as it appears in the Menu Bar + + This can be different from the application name. + + This name must be less than 16 characters long and be suitable for + displaying in the menu bar and the application Info window. + Defaults to the application name. + +<a id="option-mac-package-signing-prefix">`--mac-package-signing-prefix` *prefix*</a> + +: When signing the application package, this value is prefixed to all + components that need to be signed that don't have + an existing package identifier. + +<a id="option-mac-sign">`--mac-sign`</a> + +: Request that the package or the predefined application image be signed. + +<a id="option-mac-signing-keychain">`--mac-signing-keychain` *keychain-name*</a> + +: Name of the keychain to search for the signing identity + + If not specified, the standard keychains are used. + +<a id="option-mac-signing-key-user-name">`--mac-signing-key-user-name` *name*</a> + +: Team or user name portion in Apple signing identities + +<a id="option-mac-app-store">`--mac-app-store`</a> + +: Indicates that the jpackage output is intended for the Mac App Store. + +<a id="option-mac-entitlements">`--mac-entitlements` *path*</a> + +: Path to file containing entitlements to use when signing executables and libraries in the bundle + +<a id="option-mac-app-category">`--mac-app-category` *category*</a> + +: String used to construct LSApplicationCategoryType in application plist + + The default value is "utilities". + +### Options for creating the application package: + +<a id="option-about-url">`--about-url` *url*</a> + +: URL of the application's home page + +<a id="option-app-image">`--app-image` *directory*</a> + +: Location of the predefined application image that is used to build an installable package + (on all platforms) or to be signed (on macOS) + + (absolute path or relative to the current directory) + +<a id="option-file-associations">`--file-associations` *path*</a> + +: Path to a Properties file that contains list of key, value pairs + + (absolute path or relative to the current directory) + + The keys "extension", "mime-type", "icon", and "description" + can be used to describe the association. + + This option can be used multiple times. + +<a id="option-install-dir">`--install-dir` *path*</a> + +: Absolute path of the installation directory of the application (on macOS + or linux), or relative sub-path of the installation directory + such as "Program Files" or "AppData" (on Windows) + +<a id="option-license-file">`--license-file` *path*</a> + +: Path to the license file + + (absolute path or relative to the current directory) + +<a id="option-application-package-runtime-image">`--runtime-image` *path*</a> + +: Path of the predefined runtime image to install + + (absolute path or relative to the current directory) + + Option is required when creating a runtime installer. + +<a id="option-launcher-as-service">`--launcher-as-service`</a> + +: Request to create an installer that will register the main + application launcher as a background service-type application. + + +### Platform dependent options for creating the application package: + + +#### Windows platform options (available only when running on Windows): + +<a id="option-win-dir-chooser">`--win-dir-chooser`</a> + +: Adds a dialog to enable the user to choose a directory in which + the product is installed. + +<a id="option-win-help-url">`--win-help-url` *url*</a> + +: URL where user can obtain further information or technical support + +<a id="option-win-menu">`--win-menu`</a> + +: Request to add a Start Menu shortcut for this application + +<a id="option-win-menu-group">`--win-menu-group` *menu-group-name*</a> + +: Start Menu group this application is placed in + +<a id="option-win-per-user-install">`--win-per-user-install`</a> + +: Request to perform an install on a per-user basis + +<a id="option-win-shortcut">`--win-shortcut`</a> + +: Request to create a desktop shortcut for this application + +<a id="option-win-shortcut-prompt">`--win-shortcut-prompt`</a> + +: Adds a dialog to enable the user to choose if shortcuts will be created by installer + +<a id="option-win-update-url">`--win-update-url` *url*</a> + +: URL of available application update information + +<a id="option-win-upgrade-uuid">`--win-upgrade-uuid` *id*</a> + +: UUID associated with upgrades for this package + +#### Linux platform options (available only when running on Linux): + +<a id="option-linux-package-name">`--linux-package-name` *name*</a> + +: Name for Linux package + + Defaults to the application name. + +<a id="option-linux-deb-maintainer">`--linux-deb-maintainer` *email-address*</a> + +: Maintainer for .deb bundle + +<a id="option-linux-menu-group">`--linux-menu-group` *menu-group-name*</a> + +: Menu group this application is placed in + +<a id="option-linux-package-deps">`--linux-package-deps`</a> + +: Required packages or capabilities for the application + +<a id="option-linux-rpm-license-type">`--linux-rpm-license-type` *type*</a> + +: Type of the license ("License: *value*" of the RPM .spec) + +<a id="option-linux-app-release">`--linux-app-release` *release*</a> + +: Release value of the RPM \<name\>.spec file or + Debian revision value of the DEB control file + +<a id="option-linux-app-category">`--linux-app-category` *category-value*</a> + +: Group value of the RPM \<name\>.spec file or + Section value of DEB control file + +<a id="option-linux-shortcut">`--linux-shortcut`</a> + +: Creates a shortcut for the application. + +#### macOS platform options (available only when running on macOS): + +<a id="option-mac-dmg-content">`--mac-dmg-content` *additional-content* \[`,`*additional-content*...\]</a> + +: Include all the referenced content in the dmg. + + This option can be used more than once. + +## jpackage Examples + +``` +Generate an application package suitable for the host system: +``` + For a modular application: + jpackage -n name -p modulePath -m moduleName/className + For a non-modular application: + jpackage -i inputDir -n name \ + --main-class className --main-jar myJar.jar + From a pre-built application image: + jpackage -n name --app-image appImageDir + +``` +Generate an application image: +``` + For a modular application: + jpackage --type app-image -n name -p modulePath \ + -m moduleName/className + For a non-modular application: + jpackage --type app-image -i inputDir -n name \ + --main-class className --main-jar myJar.jar + To provide your own options to jlink, run jlink separately: + jlink --output appRuntimeImage -p modulePath \ + --add-modules moduleName \ + --no-header-files [<additional jlink options>...] + jpackage --type app-image -n name \ + -m moduleName/className --runtime-image appRuntimeImage + +``` +Generate a Java runtime package: +``` + jpackage -n name --runtime-image <runtime-image> + +``` +Sign the predefined application image (on macOS): +``` + jpackage --type app-image --app-image <app-image> \ + --mac-sign [<additional signing options>...] + + Note: the only additional options that are permitted in this mode are: + the set of additional mac signing options and --verbose + + +## jpackage and jlink + +jpackage will use jlink to create Java Runtime unless the `--runtime-image` option is used. +The created Java Runtime image on Windows will include MS runtime libraries bundled with the JDK. +If MS runtime libraries of a different version are needed for the application, the user will need +to add/replace those themselves. + + +## jpackage resource directory + +Icons, template files, and other resources of jpackage can be over-ridden by +adding replacement resources to this directory. +jpackage will lookup files by specific names in the resource directory. + + +### Resource directory files considered only when running on Linux: + +`<launcher-name>.png` + +: Application launcher icon + + Default resource is *JavaApp.png* + +`<launcher-name>.desktop` + +: A desktop file to be used with `xdg-desktop-menu` command + + Considered with application launchers registered for file associations and/or have an icon + + Default resource is *template.desktop* + + +#### Resource directory files considered only when building Linux DEB/RPM installer: + +`<package-name>-<launcher-name>.service` + +: systemd unit file for application launcher registered as a background service-type application + + Default resource is *unit-template.service* + + +#### Resource directory files considered only when building Linux RPM installer: + +`<package-name>.spec` + +: RPM spec file + + Default resource is *template.spec* + + +#### Resource directory files considered only when building Linux DEB installer: + +`control` + +: Control file + + Default resource is *template.control* + +`copyright` + +: Copyright file + + Default resource is *template.copyright* + +`preinstall` + +: Pre-install shell script + + Default resource is *template.preinstall* + +`prerm` + +: Pre-remove shell script + + Default resource is *template.prerm* + +`postinstall` + +: Post-install shell script + + Default resource is *template.postinstall* + +`postrm` + +: Post-remove shell script + + Default resource is *template.postrm* + + +### Resource directory files considered only when running on Windows: + +`<launcher-name>.ico` + +: Application launcher icon + + Default resource is *JavaApp.ico* + +`<launcher-name>.properties` + +: Properties file for application launcher executable + + Default resource is *WinLauncher.template* + + +#### Resource directory files considered only when building Windows MSI/EXE installer: + +`<application-name>-post-image.wsf` + +: A Windows Script File (WSF) to run after building application image + +`main.wxs` + +: Main WiX project file + + Default resource is *main.wxs* + +`overrides.wxi` + +: Overrides WiX project file + + Default resource is *overrides.wxi* + +`service-installer.exe` + +: Service installer executable + + Considered if some application launchers are registered as background service-type applications + +`<launcher-name>-service-install.wxi` + +: Service installer WiX project file + + Considered if some application launchers are registered as background service-type applications + + Default resource is *service-install.wxi* + +`<launcher-name>-service-config.wxi` + +: Service installer WiX project file + + Considered if some application launchers are registered as background service-type applications + + Default resource is *service-config.wxi* + +`InstallDirNotEmptyDlg.wxs` + +: WiX project file for installer UI dialog checking installation directory doesn't exist or is empty + + Default resource is *InstallDirNotEmptyDlg.wxs* + +`ShortcutPromptDlg.wxs` + +: WiX project file for installer UI dialog configuring shortcuts + + Default resource is *ShortcutPromptDlg.wxs* + +`bundle.wxf` + +: WiX project file with the hierarchy of components of application image + +`ui.wxf` + +: WiX project file for installer UI + + +#### Resource directory files considered only when building Windows EXE installer: + +`WinInstaller.properties` + +: Properties file for the installer executable + + Default resource is *WinInstaller.template* + +`<package-name>-post-msi.wsf` + +: A Windows Script File (WSF) to run after building embedded MSI installer for EXE installer + + +### Resource directory files considered only when running on macOS: + +`<launcher-name>.icns` + +: Application launcher icon + + Default resource is *JavaApp.icns* + +`Info.plist` + +: Application property list file + + Default resource is *Info-lite.plist.template* + +`Runtime-Info.plist` + +: Java Runtime property list file + + Default resource is *Runtime-Info.plist.template* + +`<application-name>.entitlements` + +: Signing entitlements property list file + + Default resource is *sandbox.plist* + + +#### Resource directory files considered only when building macOS PKG/DMG installer: + +`<package-name>-post-image.sh` + +: Shell script to run after building application image + + +#### Resource directory files considered only when building macOS PKG installer: + +`uninstaller` + +: Uninstaller shell script + + Considered if some application launchers are registered as background service-type applications + + Default resource is *uninstall.command.template* + +`preinstall` + +: Pre-install shell script + + Default resource is *preinstall.template* + +`postinstall` + +: Post-install shell script + + Default resource is *postinstall.template* + +`services-preinstall` + +: Pre-install shell script for services package + + Considered if some application launchers are registered as background service-type applications + + Default resource is *services-preinstall.template* + +`services-postinstall` + +: Post-install shell script for services package + + Considered if some application launchers are registered as background service-type applications + + Default resource is *services-postinstall.template* + +`<package-name>-background.png` + +: Background image + + Default resource is *background_pkg.png* + +`<package-name>-background-darkAqua.png` + +: Dark background image + + Default resource is *background_pkg.png* + +`product-def.plist` + +: Package property list file + + Default resource is *product-def.plist* + +`<package-name>-<launcher-name>.plist` + +: launchd property list file for application launcher registered as a background service-type application + + Default resource is *launchd.plist.template* + + +#### Resource directory files considered only when building macOS DMG installer: + +`<package-name>-dmg-setup.scpt` + +: Setup AppleScript script + + Default resource is *DMGsetup.scpt* + +`<package-name>-license.plist` + +: License property list file + + Default resource is *lic_template.plist* + +`<package-name>-background.tiff` + +: Background image + + Default resource is *background_dmg.tiff* + +`<package-name>-volume.icns` + +: Volume icon + + Default resource is *JavaApp.icns* diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java index a297f507da8..166675b5893 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.text.MessageFormat; import java.util.ArrayList; @@ -40,6 +41,7 @@ import java.util.ResourceBundle; import java.util.function.Supplier; import static jdk.jpackage.internal.OverridableResource.createResource; +import static jdk.jpackage.internal.ShortPathUtils.adjustPath; import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME; import static jdk.jpackage.internal.StandardBundlerParam.COPYRIGHT; import static jdk.jpackage.internal.StandardBundlerParam.DESCRIPTION; @@ -112,7 +114,7 @@ ExecutableRebrander addAction(UpdateResourceAction action) { } private void rebrandExecutable(Map<String, ? super Object> params, - Path target, UpdateResourceAction action) throws IOException { + final Path target, UpdateResourceAction action) throws IOException { try { String tempDirectory = TEMP_ROOT.fetchFrom(params) .toAbsolutePath().toString(); @@ -125,10 +127,11 @@ private void rebrandExecutable(Map<String, ? super Object> params, target.toFile().setWritable(true, true); - long resourceLock = lockResource(target.toString()); + var shortTargetPath = ShortPathUtils.toShortPath(target); + long resourceLock = lockResource(shortTargetPath.orElse(target).toString()); if (resourceLock == 0) { throw new RuntimeException(MessageFormat.format( - I18N.getString("error.lock-resource"), target)); + I18N.getString("error.lock-resource"), shortTargetPath.orElse(target))); } final boolean resourceUnlockedSuccess; @@ -144,6 +147,14 @@ private void rebrandExecutable(Map<String, ? super Object> params, resourceUnlockedSuccess = true; } else { resourceUnlockedSuccess = unlockResource(resourceLock); + if (shortTargetPath.isPresent()) { + // Windows will rename the excuatble in the unlock operation. + // Should restore executable's name. + var tmpPath = target.getParent().resolve( + target.getFileName().toString() + ".restore"); + Files.move(shortTargetPath.get(), tmpPath); + Files.move(tmpPath, target); + } } } @@ -236,6 +247,7 @@ private static void validateValueAndPut( private static void iconSwapWrapper(long resourceLock, String iconTarget) { + iconTarget = adjustPath(iconTarget); if (iconSwap(resourceLock, iconTarget) != 0) { throw new RuntimeException(MessageFormat.format(I18N.getString( "error.icon-swap"), iconTarget)); diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ShortPathUtils.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ShortPathUtils.java new file mode 100644 index 00000000000..21dc2a1c3ff --- /dev/null +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ShortPathUtils.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024, 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.jpackage.internal; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.MessageFormat; +import java.util.Objects; +import java.util.Optional; + + +@SuppressWarnings("restricted") +final class ShortPathUtils { + static String adjustPath(String path) { + return toShortPath(path).orElse(path); + } + + static Path adjustPath(Path path) { + return toShortPath(path).orElse(path); + } + + static Optional<String> toShortPath(String path) { + Objects.requireNonNull(path); + return toShortPath(Path.of(path)).map(Path::toString); + } + + static Optional<Path> toShortPath(Path path) { + if (!Files.exists(path)) { + throw new IllegalArgumentException(String.format("[%s] path does not exist", path)); + } + + var normPath = path.normalize().toAbsolutePath().toString(); + if (normPath.length() > MAX_PATH) { + return Optional.of(Path.of(getShortPathWrapper(normPath))); + } else { + return Optional.empty(); + } + } + + private static String getShortPathWrapper(final String longPath) { + String effectivePath; + if (!longPath.startsWith(LONG_PATH_PREFIX)) { + effectivePath = LONG_PATH_PREFIX + longPath; + } else { + effectivePath = longPath; + } + + return Optional.ofNullable(getShortPath(effectivePath)).orElseThrow( + () -> new ShortPathException(MessageFormat.format(I18N.getString( + "error.short-path-conv-fail"), effectivePath))); + } + + static final class ShortPathException extends RuntimeException { + + ShortPathException(String msg) { + super(msg); + } + + private static final long serialVersionUID = 1L; + } + + private static native String getShortPath(String longPath); + + private static final int MAX_PATH = 240; + // See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getshortpathnamew + private static final String LONG_PATH_PREFIX = "\\\\?\\"; + + static { + System.loadLibrary("jpackage"); + } +} diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java index fa81b4278b0..cc2e9298e99 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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.nio.file.Path; import java.text.MessageFormat; import java.util.Map; +import jdk.jpackage.internal.util.PathUtils; @SuppressWarnings("restricted") public class WinExeBundler extends AbstractBundler { @@ -127,7 +128,7 @@ private Path buildEXE(Map<String, ? super Object> params, Path msi, outdir.toAbsolutePath().toString())); // Copy template msi wrapper next to msi file - final Path exePath = IOUtils.replaceSuffix(msi, ".exe"); + final Path exePath = PathUtils.replaceSuffix(msi, ".exe"); try (InputStream is = OverridableResource.readDefault(EXE_WRAPPER_NAME)) { Files.copy(is, exePath); } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java index c0ae65b3b0b..f724e08fc89 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java @@ -36,7 +36,6 @@ import java.nio.file.PathMatcher; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; @@ -67,7 +66,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.TEMP_ROOT; import static jdk.jpackage.internal.StandardBundlerParam.VENDOR; import static jdk.jpackage.internal.StandardBundlerParam.VERSION; -import jdk.jpackage.internal.WixToolset.WixToolsetType; +import jdk.jpackage.internal.util.FileUtils; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -367,7 +366,7 @@ private void prepareProto(Map<String, ? super Object> params) if (appImage != null) { appDir = MSI_IMAGE_DIR.fetchFrom(params).resolve(appName); // copy everything from appImage dir into appDir/name - IOUtils.copyRecursive(appImage, appDir); + FileUtils.copyRecursive(appImage, appDir); } else { appDir = appImageBundler.execute(params, MSI_IMAGE_DIR.fetchFrom( params)); @@ -527,9 +526,10 @@ private Path buildMSI(Map<String, ? super Object> params, "message.preparing-msi-config"), msiOut.toAbsolutePath() .toString())); - WixPipeline wixPipeline = new WixPipeline() - .setToolset(wixToolset) - .setWixObjDir(TEMP_ROOT.fetchFrom(params).resolve("wixobj")) + var wixObjDir = TEMP_ROOT.fetchFrom(params).resolve("wixobj"); + + var wixPipeline = WixPipeline.build() + .setWixObjDir(wixObjDir) .setWorkDir(WIN_APP_IMAGE.fetchFrom(params)) .addSource(CONFIG_ROOT.fetchFrom(params).resolve("main.wxs"), wixVars); @@ -606,13 +606,13 @@ private Path buildMSI(Map<String, ? super Object> params, // Cultures from custom files and a single primary Culture are // included into "-cultures" list for (var wxl : primaryWxlFiles) { - wixPipeline.addLightOptions("-loc", wxl.toAbsolutePath().normalize().toString()); + wixPipeline.addLightOptions("-loc", wxl.toString()); } List<String> cultures = new ArrayList<>(); for (var wxl : customWxlFiles) { wxl = configDir.resolve(wxl.getFileName()); - wixPipeline.addLightOptions("-loc", wxl.toAbsolutePath().normalize().toString()); + wixPipeline.addLightOptions("-loc", wxl.toString()); cultures.add(getCultureFromWxlFile(wxl)); } @@ -639,7 +639,8 @@ private Path buildMSI(Map<String, ? super Object> params, } } - wixPipeline.buildMsi(msiOut.toAbsolutePath()); + Files.createDirectories(wixObjDir); + wixPipeline.create(wixToolset).buildMsi(msiOut.toAbsolutePath()); return msiOut; } @@ -679,14 +680,14 @@ private static String getCultureFromWxlFile(Path wxlPath) throws IOException { if (nodes.getLength() != 1) { throw new IOException(MessageFormat.format(I18N.getString( "error.extract-culture-from-wix-l10n-file"), - wxlPath.toAbsolutePath())); + wxlPath.toAbsolutePath().normalize())); } return nodes.item(0).getNodeValue(); } catch (XPathExpressionException | ParserConfigurationException | SAXException ex) { throw new IOException(MessageFormat.format(I18N.getString( - "error.read-wix-l10n-file"), wxlPath.toAbsolutePath()), ex); + "error.read-wix-l10n-file"), wxlPath.toAbsolutePath().normalize()), ex); } } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java index 5bc20c1413c..a5d9a5de141 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java @@ -42,7 +42,6 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -56,7 +55,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import jdk.jpackage.internal.AppImageFile.LauncherInfo; -import jdk.jpackage.internal.IOUtils.XmlConsumer; +import jdk.jpackage.internal.util.XmlConsumer; import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME; import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR; import static jdk.jpackage.internal.StandardBundlerParam.VENDOR; @@ -65,6 +64,8 @@ import static jdk.jpackage.internal.WinMsiBundler.SERVICE_INSTALLER; import static jdk.jpackage.internal.WinMsiBundler.WIN_APP_IMAGE; import jdk.jpackage.internal.WixToolset.WixToolsetType; +import jdk.jpackage.internal.util.PathUtils; +import jdk.jpackage.internal.util.XmlUtils; import org.w3c.dom.NodeList; /** @@ -202,7 +203,7 @@ private void normalizeFileAssociation(FileAssociation fa) { } private static Path addExeSuffixToPath(Path path) { - return IOUtils.addSuffix(path, ".exe"); + return PathUtils.addSuffix(path, ".exe"); } private Path getInstalledFaIcoPath(FileAssociation fa) { @@ -524,7 +525,7 @@ private String addShortcutComponent(XMLStreamWriter xml, Path launcherPath, throw throwInvalidPathException(launcherPath); } - String launcherBasename = IOUtils.replaceSuffix( + String launcherBasename = PathUtils.replaceSuffix( IOUtils.getFileName(launcherPath), "").toString(); Path shortcutPath = folder.getPath(this).resolve(launcherBasename); @@ -774,7 +775,7 @@ private List<String> addServiceConfigs(XMLStreamWriter xml) throws } try { - var buffer = new DOMResult(IOUtils.initDocumentBuilder().newDocument()); + var buffer = new DOMResult(XmlUtils.initDocumentBuilder().newDocument()); var bufferWriter = XMLOutputFactory.newInstance().createXMLStreamWriter( buffer); diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java index 0276cc96e65..48a1d04f8dc 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java @@ -37,13 +37,14 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.stream.XMLStreamWriter; -import jdk.jpackage.internal.IOUtils.XmlConsumer; +import jdk.jpackage.internal.util.XmlConsumer; import jdk.jpackage.internal.OverridableResource.Source; import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT; import jdk.internal.util.Architecture; import static jdk.jpackage.internal.OverridableResource.createResource; import jdk.jpackage.internal.WixSourceConverter.ResourceGroup; import jdk.jpackage.internal.WixToolset.WixToolsetType; +import jdk.jpackage.internal.util.XmlUtils; /** * Creates WiX fragment. @@ -73,7 +74,7 @@ List<String> getLoggableWixFeatures() { return List.of(); } - void configureWixPipeline(WixPipeline wixPipeline) { + void configureWixPipeline(WixPipeline.Builder wixPipeline) { wixPipeline.addSource(configRoot.resolve(outputFileName), Optional.ofNullable(wixVariables).map(WixVariables::getValues).orElse( null)); @@ -159,7 +160,7 @@ final protected void addResource(OverridableResource resource, String saveAsName } private void createWixSource(Path file, XmlConsumer xmlConsumer) throws IOException { - IOUtils.createXml(file, xml -> { + XmlUtils.createXml(file, xml -> { xml.writeStartElement("Wix"); for (var ns : getWixNamespaces().entrySet()) { switch (ns.getKey()) { diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixLauncherAsService.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixLauncherAsService.java index 9b737c8e1a4..ffd5e35b15c 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixLauncherAsService.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixLauncherAsService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -39,6 +39,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import static jdk.jpackage.internal.OverridableResource.createResource; +import jdk.jpackage.internal.util.XmlUtils; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -95,7 +96,7 @@ private void writeResource(OverridableResource resource, XMLStreamWriter xml) resource.saveToStream(buffer); try { - Document doc = IOUtils.initDocumentBuilder().parse( + Document doc = XmlUtils.initDocumentBuilder().parse( new ByteArrayInputStream(buffer.toByteArray())); XPath xPath = XPathFactory.newInstance().newXPath(); @@ -109,7 +110,7 @@ private void writeResource(OverridableResource resource, XMLStreamWriter xml) sources.add(new DOMSource(n)); } - IOUtils.mergeXmls(xml, sources); + XmlUtils.mergeXmls(xml, sources); } catch (SAXException ex) { throw new IOException(ex); diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java index 835247ed1de..d7c1b54a48c 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java @@ -29,64 +29,130 @@ import java.nio.file.Path; 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.Optional; +import java.util.Set; import java.util.function.Function; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; +import static jdk.jpackage.internal.ShortPathUtils.adjustPath; +import jdk.jpackage.internal.util.PathUtils; /** * WiX pipeline. Compiles and links WiX sources. */ -public class WixPipeline { - WixPipeline() { - sources = new ArrayList<>(); - lightOptions = new ArrayList<>(); - } +final class WixPipeline { - WixPipeline setToolset(WixToolset v) { - toolset = v; - return this; - } + static final class Builder { + Builder() { + } - WixPipeline setWixVariables(Map<String, String> v) { - wixVariables = v; - return this; - } + WixPipeline create(WixToolset toolset) { + Objects.requireNonNull(toolset); + Objects.requireNonNull(workDir); + Objects.requireNonNull(wixObjDir); + if (sources.isEmpty()) { + throw new IllegalArgumentException("no sources"); + } - WixPipeline setWixObjDir(Path v) { - wixObjDir = v; - return this; - } + final var absWorkDir = workDir.normalize().toAbsolutePath(); + + final UnaryOperator<Path> normalizePath = path -> { + return path.normalize().toAbsolutePath(); + }; + + final var absObjWorkDir = normalizePath.apply(wixObjDir); + + var relSources = sources.stream().map(source -> { + return source.overridePath(normalizePath.apply(source.path)); + }).toList(); + + return new WixPipeline(toolset, adjustPath(absWorkDir), absObjWorkDir, + wixVariables, mapLightOptions(normalizePath), relSources); + } + + Builder setWixObjDir(Path v) { + wixObjDir = v; + return this; + } + + Builder setWorkDir(Path v) { + workDir = v; + return this; + } + + Builder setWixVariables(Map<String, String> v) { + wixVariables.clear(); + wixVariables.putAll(v); + return this; + } + + Builder addSource(Path source, Map<String, String> wixVariables) { + sources.add(new WixSource(source, wixVariables)); + return this; + } + + Builder addLightOptions(String ... v) { + lightOptions.addAll(List.of(v)); + return this; + } - WixPipeline setWorkDir(Path v) { - workDir = v; - return this; + private List<String> mapLightOptions(UnaryOperator<Path> normalizePath) { + var pathOptions = Set.of("-b", "-loc"); + List<String> reply = new ArrayList<>(); + boolean convPath = false; + for (var opt : lightOptions) { + if (convPath) { + opt = normalizePath.apply(Path.of(opt)).toString(); + convPath = false; + } else if (pathOptions.contains(opt)) { + convPath = true; + } + reply.add(opt); + } + return reply; + } + + private Path workDir; + private Path wixObjDir; + private final Map<String, String> wixVariables = new HashMap<>(); + private final List<String> lightOptions = new ArrayList<>(); + private final List<WixSource> sources = new ArrayList<>(); } - WixPipeline addSource(Path source, Map<String, String> wixVariables) { - WixSource entry = new WixSource(); - entry.source = source; - entry.variables = wixVariables; - sources.add(entry); - return this; + static Builder build() { + return new Builder(); } - WixPipeline addLightOptions(String ... v) { - lightOptions.addAll(List.of(v)); - return this; + private WixPipeline(WixToolset toolset, Path workDir, Path wixObjDir, + Map<String, String> wixVariables, List<String> lightOptions, + List<WixSource> sources) { + this.toolset = toolset; + this.workDir = workDir; + this.wixObjDir = wixObjDir; + this.wixVariables = wixVariables; + this.lightOptions = lightOptions; + this.sources = sources; } void buildMsi(Path msi) throws IOException { Objects.requireNonNull(workDir); + // Use short path to the output msi to workaround + // WiX limitations of handling long paths. + var transientMsi = wixObjDir.resolve("a.msi"); + switch (toolset.getType()) { - case Wix3 -> buildMsiWix3(msi); - case Wix4 -> buildMsiWix4(msi); + case Wix3 -> buildMsiWix3(transientMsi); + case Wix4 -> buildMsiWix4(transientMsi); default -> throw new IllegalArgumentException(); } + + IOUtils.copyFile(workDir.resolve(transientMsi), msi); } private void addWixVariblesToCommandLine( @@ -140,7 +206,7 @@ private void buildMsiWix4(Path msi) throws IOException { "build", "-nologo", "-pdbtype", "none", - "-intermediatefolder", wixObjDir.toAbsolutePath().toString(), + "-intermediatefolder", wixObjDir.toString(), "-ext", "WixToolset.Util.wixext", "-arch", WixFragmentBuilder.is64Bit() ? "x64" : "x86" )); @@ -150,7 +216,7 @@ private void buildMsiWix4(Path msi) throws IOException { addWixVariblesToCommandLine(mergedSrcWixVars, cmdline); cmdline.addAll(sources.stream().map(wixSource -> { - return wixSource.source.toAbsolutePath().toString(); + return wixSource.path.toString(); }).toList()); cmdline.addAll(List.of("-out", msi.toString())); @@ -180,16 +246,16 @@ private void buildMsiWix3(Path msi) throws IOException { } private Path compileWix3(WixSource wixSource) throws IOException { - Path wixObj = wixObjDir.toAbsolutePath().resolve(IOUtils.replaceSuffix( - IOUtils.getFileName(wixSource.source), ".wixobj")); + Path wixObj = wixObjDir.toAbsolutePath().resolve(PathUtils.replaceSuffix( + wixSource.path.getFileName(), ".wixobj")); List<String> cmdline = new ArrayList<>(List.of( toolset.getToolPath(WixTool.Candle3).toString(), "-nologo", - wixSource.source.toAbsolutePath().toString(), + wixSource.path.toString(), "-ext", "WixUtilExtension", "-arch", WixFragmentBuilder.is64Bit() ? "x64" : "x86", - "-out", wixObj.toAbsolutePath().toString() + "-out", wixObj.toString() )); addWixVariblesToCommandLine(wixSource.variables, cmdline); @@ -200,19 +266,19 @@ private Path compileWix3(WixSource wixSource) throws IOException { } private void execute(List<String> cmdline) throws IOException { - Executor.of(new ProcessBuilder(cmdline).directory(workDir.toFile())). - executeExpectSuccess(); + Executor.of(new ProcessBuilder(cmdline).directory(workDir.toFile())).executeExpectSuccess(); } - private static final class WixSource { - Path source; - Map<String, String> variables; + private record WixSource(Path path, Map<String, String> variables) { + WixSource overridePath(Path path) { + return new WixSource(path, variables); + } } - private WixToolset toolset; - private Map<String, String> wixVariables; - private List<String> lightOptions; - private Path wixObjDir; - private Path workDir; - private List<WixSource> sources; + private final WixToolset toolset; + private final Map<String, String> wixVariables; + private final List<String> lightOptions; + private final Path wixObjDir; + private final Path workDir; + private final List<WixSource> sources; } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java index 7786d64a786..86ef70442dc 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java @@ -52,6 +52,7 @@ import javax.xml.transform.stax.StAXResult; import javax.xml.transform.stream.StreamSource; import jdk.jpackage.internal.WixToolset.WixToolsetType; +import jdk.jpackage.internal.util.XmlUtils; import org.w3c.dom.Document; import org.xml.sax.SAXException; @@ -98,7 +99,7 @@ Status appyTo(OverridableResource resource, Path resourceSaveAsFile) throws IOEx Document inputXmlDom; try { - inputXmlDom = IOUtils.initDocumentBuilder().parse(new ByteArrayInputStream(buf)); + inputXmlDom = XmlUtils.initDocumentBuilder().parse(new ByteArrayInputStream(buf)); } catch (SAXException ex) { // Malformed XML, don't run converter, save as is. resource.saveToFile(resourceSaveAsFile); diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java index f16b28edf24..ee98327b032 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java @@ -41,6 +41,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.WixToolset.WixToolsetType; +import jdk.jpackage.internal.util.PathUtils; /** * WiX tool. @@ -51,7 +52,7 @@ public enum WixTool { Wix4("wix", DottedVersion.lazy("4.0.4")); WixTool(String commandName, DottedVersion minimalVersion) { - this.toolFileName = IOUtils.addSuffix(Path.of(commandName), ".exe"); + this.toolFileName = PathUtils.addSuffix(Path.of(commandName), ".exe"); this.minimalVersion = minimalVersion; } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixUiFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixUiFragmentBuilder.java index 4f39a65e3b6..25db6e6ab0b 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixUiFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixUiFragmentBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -39,7 +39,7 @@ import java.util.stream.Stream; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; -import jdk.jpackage.internal.IOUtils.XmlConsumer; +import jdk.jpackage.internal.util.XmlConsumer; import static jdk.jpackage.internal.OverridableResource.createResource; import static jdk.jpackage.internal.StandardBundlerParam.LICENSE_FILE; import jdk.jpackage.internal.WixAppImageFragmentBuilder.ShortcutsFolder; @@ -97,7 +97,7 @@ void initFromParams(Map<String, ? super Object> params) { } @Override - void configureWixPipeline(WixPipeline wixPipeline) { + void configureWixPipeline(WixPipeline.Builder wixPipeline) { super.configureWixPipeline(wixPipeline); if (withShortcutPromptDlg || withInstallDirChooserDlg || withLicenseDlg) { @@ -518,7 +518,7 @@ private final class CustomDialog { wxsFileName), wxsFileName); } - void addToWixPipeline(WixPipeline wixPipeline) { + void addToWixPipeline(WixPipeline.Builder wixPipeline) { wixPipeline.addSource(getConfigRoot().toAbsolutePath().resolve( wxsFileName), wixVariables.getValues()); } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties index 9e7504364d3..584342397a6 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties @@ -56,6 +56,7 @@ error.lock-resource=Failed to lock: {0} error.unlock-resource=Failed to unlock: {0} error.read-wix-l10n-file=Failed to parse {0} file error.extract-culture-from-wix-l10n-file=Failed to read value of culture from {0} file +error.short-path-conv-fail=Failed to get short version of "{0}" path message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place. message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}". diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties index a7212d9640a..dce8ca6176d 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties @@ -56,6 +56,7 @@ error.lock-resource=Sperren nicht erfolgreich: {0} error.unlock-resource=Aufheben der Sperre nicht erfolgreich: {0} error.read-wix-l10n-file=Datei {0} konnte nicht geparst werden error.extract-culture-from-wix-l10n-file=Kulturwert konnte nicht aus Datei {0} gelesen werden +error.short-path-conv-fail=Failed to get short version of "{0}" path message.icon-not-ico=Das angegebene Symbol "{0}" ist keine ICO-Datei und wird nicht verwendet. Stattdessen wird das Standardsymbol verwendet. message.potential.windows.defender.issue=Warnung: Windows Defender verhindert eventuell die korrekte Ausführung von jpackage. Wenn ein Problem auftritt, deaktivieren Sie das Echtzeitmonitoring, oder fügen Sie einen Ausschluss für das Verzeichnis "{0}" hinzu. diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties index 352aab7a493..47e5b585869 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties @@ -56,6 +56,7 @@ error.lock-resource=ロックに失敗しました: {0} error.unlock-resource=ロック解除に失敗しました: {0} error.read-wix-l10n-file={0}ファイルの解析に失敗しました error.extract-culture-from-wix-l10n-file={0}ファイルからのカルチャの値の読取りに失敗しました +error.short-path-conv-fail=Failed to get short version of "{0}" path message.icon-not-ico=指定したアイコン"{0}"はICOファイルではなく、使用されません。デフォルト・アイコンがその位置に使用されます。 message.potential.windows.defender.issue=警告: Windows Defenderが原因でjpackageが機能しないことがあります。問題が発生した場合は、リアルタイム・モニタリングを無効にするか、ディレクトリ"{0}"の除外を追加することにより、問題に対処できます。 diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties index a8d4a4471d6..abd3d13a667 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties @@ -56,6 +56,7 @@ error.lock-resource=无法锁定:{0} error.unlock-resource=无法解锁:{0} error.read-wix-l10n-file=无法解析 {0} 文件 error.extract-culture-from-wix-l10n-file=无法从 {0} 文件读取文化值 +error.short-path-conv-fail=Failed to get short version of "{0}" path message.icon-not-ico=指定的图标 "{0}" 不是 ICO 文件, 不会使用。将使用默认图标代替。 message.potential.windows.defender.issue=警告:Windows Defender 可能会阻止 jpackage 正常工作。如果存在问题,可以通过禁用实时监视或者为目录 "{0}" 添加排除项来解决。 diff --git a/src/jdk.jpackage/windows/native/common/WinFileUtils.cpp b/src/jdk.jpackage/windows/native/common/WinFileUtils.cpp index 993aed8bb13..f801009ed94 100644 --- a/src/jdk.jpackage/windows/native/common/WinFileUtils.cpp +++ b/src/jdk.jpackage/windows/native/common/WinFileUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -668,4 +668,23 @@ tstring stripExeSuffix(const tstring& path) { return path.substr(0, pos); } +tstring toShortPath(const tstring& path) { + const DWORD len = GetShortPathName(path.c_str(), nullptr, 0); + if (0 == len) { + JP_THROW(SysError(tstrings::any() << "GetShortPathName(" + << path << ") failed", GetShortPathName)); + } + + std::vector<TCHAR> buf; + buf.resize(len); + const DWORD copied = GetShortPathName(path.c_str(), buf.data(), + static_cast<DWORD>(buf.size())); + if (copied != buf.size() - 1) { + JP_THROW(SysError(tstrings::any() << "GetShortPathName(" + << path << ") failed", GetShortPathName)); + } + + return tstring(buf.data(), buf.size() - 1); +} + } // namespace FileUtils diff --git a/src/jdk.jpackage/windows/native/common/WinFileUtils.h b/src/jdk.jpackage/windows/native/common/WinFileUtils.h index 2dfb32fa088..ba07efec78e 100644 --- a/src/jdk.jpackage/windows/native/common/WinFileUtils.h +++ b/src/jdk.jpackage/windows/native/common/WinFileUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -315,6 +315,8 @@ namespace FileUtils { std::ofstream tmp; tstring dstPath; }; + + tstring toShortPath(const tstring& path); } // FileUtils #endif // WINFILEUTILS_H diff --git a/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp b/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp index 6317842787e..66fa92e3563 100644 --- a/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp +++ b/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp @@ -25,6 +25,8 @@ #include "ResourceEditor.h" #include "ErrorHandling.h" +#include "FileUtils.h" +#include "WinFileUtils.h" #include "IconSwap.h" #include "VersionInfo.h" #include "JniUtils.h" @@ -162,4 +164,25 @@ extern "C" { return 1; } + /* + * Class: jdk_jpackage_internal_ShortPathUtils + * Method: getShortPath + * Signature: (Ljava/lang/String;)Ljava/lang/String; + */ + JNIEXPORT jstring JNICALL + Java_jdk_jpackage_internal_ShortPathUtils_getShortPath( + JNIEnv *pEnv, jclass c, jstring jLongPath) { + + JP_TRY; + + const std::wstring longPath = jni::toUnicodeString(pEnv, jLongPath); + std::wstring shortPath = FileUtils::toShortPath(longPath); + + return jni::toJString(pEnv, shortPath); + + JP_CATCH_ALL; + + return NULL; + } + } // extern "C" \ No newline at end of file diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java index f4ca58d6af4..c92e6e11f1f 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java @@ -1001,6 +1001,11 @@ public synchronized String readUserLine(String prompt) throws IOException { return doReadUserLine(prompt, null); } + @Override + public String readUserLine() throws IOException { + return readUserLine(""); + } + private synchronized String doReadUserLine(String prompt, Character mask) throws IOException { History prevHistory = in.getHistory(); boolean prevDisableCr = Display.DISABLE_CR; diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java index 339a3005d7d..7a1234628de 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java @@ -64,6 +64,12 @@ public char readUserInputChar() throws IOException { } public String readUserLine(String prompt) throws IOException { + userOutput().write(prompt); + userOutput().flush(); + throw new UserInterruptException(""); + } + + public String readUserLine() throws IOException { throw new UserInterruptException(""); } @@ -72,6 +78,8 @@ public Writer userOutput() { } public char[] readPassword(String prompt) throws IOException { + userOutput().write(prompt); + userOutput().flush(); throw new UserInterruptException(""); } diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 2d06ffc529d..1adcb472b77 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -35,6 +35,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; import java.io.Reader; @@ -1192,7 +1193,7 @@ private void initFeedback(String initMode) { //where private void startUpRun(String start) { - try (IOContext suin = new ScannerIOContext(new StringReader(start))) { + try (IOContext suin = new ScannerIOContext(new StringReader(start), userout)) { while (run(suin)) { if (!live) { resetState(); @@ -3125,7 +3126,7 @@ private boolean runFile(String filename, String context) { throw new FileNotFoundException(filename); } } - try (var scannerIOContext = new ScannerIOContext(scanner)) { + try (var scannerIOContext = new ScannerIOContext(scanner, userout)) { run(scannerIOContext); } return true; @@ -3288,8 +3289,10 @@ private boolean doReload(ReplayableHistory history, boolean echo, Options oldOpt resetState(); } if (history != null) { - run(new ReloadIOContext(history.iterable(), - echo ? cmdout : null)); + try (ReloadIOContext ctx = new ReloadIOContext(history.iterable(), + echo ? cmdout : null, userout)) { + run(ctx); + } } return true; } @@ -4107,6 +4110,17 @@ public void close() throws IOException { public String readLine(String prompt) { try { return input.readUserLine(prompt); + } catch (UserInterruptException ex) { + return null; + } catch (IOException ex) { + throw new IOError(ex); + } + } + + @Override + public String readLine() throws IOError { + try { + return input.readUserLine(); } catch (IOException ex) { throw new IOError(ex); } @@ -4116,6 +4130,8 @@ public String readLine(String prompt) { public char[] readPassword(String prompt) { try { return input.readPassword(prompt); + } catch (UserInterruptException ex) { + return null; } catch (IOException ex) { throw new IOError(ex); } @@ -4135,6 +4151,12 @@ public Charset charset() { abstract class NonInteractiveIOContext extends IOContext { + private final Writer userOutput; + + public NonInteractiveIOContext(PrintStream userOutput) { + this.userOutput = new OutputStreamWriter(userOutput); + } + @Override public boolean interactiveOutput() { return false; @@ -4169,17 +4191,33 @@ public void afterUserCode() { @Override public void replaceLastHistoryEntry(String source) { } + + @Override + public Writer userOutput() { + return userOutput; + } + + @Override + public void close() { + try { + userOutput.flush(); + } catch (IOException _) { + //ignore + } + } + } class ScannerIOContext extends NonInteractiveIOContext { private final Scanner scannerIn; - ScannerIOContext(Scanner scannerIn) { + ScannerIOContext(Scanner scannerIn, PrintStream userOutput) { + super(userOutput); this.scannerIn = scannerIn; } - ScannerIOContext(Reader rdr) throws FileNotFoundException { - this(new Scanner(rdr)); + ScannerIOContext(Reader rdr, PrintStream userOutput) throws FileNotFoundException { + this(new Scanner(rdr), userOutput); } @Override @@ -4193,6 +4231,7 @@ public String readLine(String firstLinePrompt, String continuationPrompt, boolea @Override public void close() { + super.close(); scannerIn.close(); } @@ -4206,7 +4245,8 @@ class ReloadIOContext extends NonInteractiveIOContext { private final Iterator<String> it; private final PrintStream echoStream; - ReloadIOContext(Iterable<String> history, PrintStream echoStream) { + ReloadIOContext(Iterable<String> history, PrintStream echoStream, PrintStream userOutput) { + super(userOutput); this.it = history.iterator(); this.echoStream = echoStream; } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/JShellConsole.java b/src/jdk.jshell/share/classes/jdk/jshell/JShellConsole.java index fe73d6965cb..014766f9ff7 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/JShellConsole.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/JShellConsole.java @@ -28,6 +28,7 @@ import java.io.PrintWriter; import java.io.Reader; import java.nio.charset.Charset; +import jdk.internal.javac.PreviewFeature; /** * An interface providing functionality for {@link java.io.Console} in the user's snippet. @@ -75,6 +76,21 @@ public interface JShellConsole { */ public String readLine(String prompt) throws IOError; + /** + * Reads a single line of text from the console. + * + * @throws IOError + * If an I/O error occurs. + * + * @return A string containing the line read from the console, not + * including any line-termination characters, or {@code null} + * if an end of stream has been reached. + * @see java.io.Console#readLine() + * @since 24 + */ + @PreviewFeature(feature=PreviewFeature.Feature.IMPLICIT_CLASSES) + public String readLine() throws IOError; + /** * Provides a prompt, then reads a password or passphrase from * the console with echoing disabled. diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/ConsoleImpl.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/ConsoleImpl.java index b85b8c9ea0f..a697a37141e 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/ConsoleImpl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/impl/ConsoleImpl.java @@ -117,6 +117,9 @@ private int readChars(char[] data, int off, int len) throws IOException { private char[] readChars() throws IOException { int actualLen = readInt(); + if (actualLen == (-1)) { + return null; + } char[] result = new char[actualLen]; for (int i = 0; i < actualLen; i++) { result[i] = (char) ((remoteOutput.read() << 8) | @@ -233,6 +236,16 @@ public String readln(String prompt) { } } + /** + * {@inheritDoc} + * + * @throws IOError {@inheritDoc} + */ + @Override + public String readln() { + return readLine(); + } + /** * {@inheritDoc} */ @@ -257,6 +270,9 @@ public String readLine(Locale locale, String format, Object... args) { remoteInput.write(Task.READ_LINE.ordinal()); sendChars(chars, 0, chars.length); char[] line = readChars(); + if (line == null) { + return null; + } return new String(line); }); } catch (IOException ex) { @@ -269,7 +285,15 @@ public String readLine(Locale locale, String format, Object... args) { */ @Override public String readLine() { - return readLine(Locale.getDefault(Locale.Category.FORMAT), ""); + try { + return sendAndReceive(() -> { + remoteInput.write(Task.READ_LINE_NO_PROMPT.ordinal()); + char[] line = readChars(); + return new String(line); + }); + } catch (IOException ex) { + throw new IOError(ex); + } } /** @@ -399,16 +423,30 @@ public synchronized void write(int b) throws IOException { char[] data = readCharsOrNull(1); if (data != null) { String line = console.readLine(new String(data)); - char[] chars = line.toCharArray(); - sendChars(sinkOutput, chars, 0, chars.length); + if (line == null) { + sendInt(sinkOutput, -1); + } else { + char[] chars = line.toCharArray(); + sendChars(sinkOutput, chars, 0, chars.length); + } bp = 0; } } + case READ_LINE_NO_PROMPT -> { + String line = console.readLine(); + char[] chars = line.toCharArray(); + sendChars(sinkOutput, chars, 0, chars.length); + bp = 0; + } case READ_PASSWORD -> { char[] data = readCharsOrNull(1); if (data != null) { char[] chars = console.readPassword(new String(data)); - sendChars(sinkOutput, chars, 0, chars.length); + if (chars == null) { + sendInt(sinkOutput, -1); + } else { + sendChars(sinkOutput, chars, 0, chars.length); + } bp = 0; } } @@ -478,6 +516,7 @@ private enum Task { FLUSH_OUTPUT, READ_CHARS, READ_LINE, + READ_LINE_NO_PROMPT, READ_PASSWORD, FLUSH_CONSOLE, CHARSET, diff --git a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PREVIEW_DEFAULT.jsh b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PREVIEW_DEFAULT.jsh index 4644ac86386..975d1215535 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PREVIEW_DEFAULT.jsh +++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PREVIEW_DEFAULT.jsh @@ -1 +1,2 @@ import module java.base; +import static java.io.IO.*; diff --git a/src/jdk.jshell/share/man/jshell.1 b/src/jdk.jshell/share/man/jshell.1 deleted file mode 100644 index 6f478e57442..00000000000 --- a/src/jdk.jshell/share/man/jshell.1 +++ /dev/null @@ -1,1292 +0,0 @@ -.\" Copyright (c) 2017, 2023, 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. -.\" -'\" t -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JSHELL" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jshell - interactively evaluate declarations, statements, and -expressions of the Java programming language in a read-eval-print loop -(REPL) -.SH SYNOPSIS -.PP -\f[V]jshell\f[R] [\f[I]options\f[R]] [\f[I]load-files\f[R]] -.TP -\f[I]options\f[R] -Command-line options, separated by spaces. -See \f[B]Options for jshell\f[R]. -.TP -\f[I]load-files\f[R] -One or more scripts to run when the tool is started. -Scripts can contain any valid code snippets or JShell commands. -.RS -.PP -The script can be a local file or one of following predefined scripts: -.TP -\f[V]DEFAULT\f[R] -Loads the default entries, which are commonly used as imports. -.TP -\f[V]JAVASE\f[R] -Imports all Java SE packages. -.TP -\f[V]PRINTING\f[R] -Defines \f[V]print\f[R], \f[V]println\f[R], and \f[V]printf\f[R] as -\f[V]jshell\f[R] methods for use within the tool. -.TP -\f[V]TOOLING\f[R] -Defines \f[V]javac\f[R], \f[V]jar\f[R], and other methods for running -JDK tools via their command-line interface within the \f[V]jshell\f[R] -tool. -.PP -For more than one script, use a space to separate the names. -Scripts are run in the order in which they\[aq]re entered on the command -line. -Command-line scripts are run after startup scripts. -To run a script after JShell is started, use the \f[V]/open\f[R] -command. -.PP -To accept input from standard input and suppress the interactive I/O, -enter a hyphen (-) for \f[I]load-files\f[R]. -This option enables the use of the \f[V]jshell\f[R] tool in pipe chains. -.RE -.SH DESCRIPTION -.PP -JShell provides a way to interactively evaluate declarations, -statements, and expressions of the Java programming language, making it -easier to learn the language, explore unfamiliar code and APIs, and -prototype complex code. -Java statements, variable definitions, method definitions, class -definitions, import statements, and expressions are accepted. -The bits of code entered are called snippets. -.PP -As snippets are entered, they\[aq]re evaluated, and feedback is -provided. -Feedback varies from the results and explanations of actions to nothing, -depending on the snippet entered and the feedback mode chosen. -Errors are described regardless of the feedback mode. -Start with the verbose mode to get the most feedback while learning the -tool. -.PP -Command-line options are available for configuring the initial -environment when JShell is started. -Within JShell, commands are available for modifying the environment as -needed. -.PP -Existing snippets can be loaded from a file to initialize a JShell -session, or at any time within a session. -Snippets can be modified within the session to try out different -variations and make corrections. -To keep snippets for later use, save them to a file. -.SH OPTIONS FOR JSHELL -.TP -\f[V]--add-exports\f[R] \f[I]module\f[R]/\f[I]package\f[R] -Specifies a package to be considered as exported from its defining -module. -.TP -\f[V]--add-modules\f[R] \f[I]module\f[R][\f[V],\f[R]\f[I]module\f[R]...] -Specifies the root modules to resolve in addition to the initial module. -.TP -\f[V]-C\f[R]\f[I]flag\f[R] -passes \f[I]flag\f[R] to the Java compiler inside JShell. -For example, \f[V]-C-Xlint\f[R] enables all the recommended lint -warnings, and \f[V]-C--release=<N>\f[R] compiles for Java SE N, as if ---release N was specified. -.TP -\f[V]--class-path\f[R] \f[I]path\f[R] -Specifies the directories and archives that are searched to locate class -files. -This option overrides the path in the \f[V]CLASSPATH\f[R] environment -variable. -If the environment variable isn\[aq]t set and this option isn\[aq]t -used, then the current directory is searched. -For Linux and macOS, use a colon (:) to separate items in the path. -For Windows, use a semicolon (;) to separate items. -.TP -\f[V]--enable-preview\f[R] -Allows code to depend on the preview features of this release. -.TP -\f[V]--execution\f[R] \f[I]specification\f[R] -Specifies an alternate execution engine, where \f[I]specification\f[R] -is an ExecutionControl spec. -See the documentation of the package jdk.jshell.spi for the syntax of -the spec. -.TP -\f[V]--feedback\f[R] \f[I]mode\f[R] -Sets the initial level of feedback provided in response to what\[aq]s -entered. -The initial level can be overridden within a session by using the -\f[V]/set feedback\f[R] \f[I]mode\f[R] command. -The default is \f[V]normal\f[R]. -.RS -.PP -The following values are valid for \f[I]mode\f[R]: -.TP -\f[V]verbose\f[R] -Provides detailed feedback for entries. -Additional information about the action performed is displayed after the -result of the action. -The next prompt is separated from the feedback by a blank line. -.TP -\f[V]normal\f[R] -Provides an average amount of feedback. -The next prompt is separated from the feedback by a blank line. -.TP -\f[V]concise\f[R] -Provides minimal feedback. -The next prompt immediately follows the code snippet or feedback. -.TP -\f[V]silent\f[R] -Provides no feedback. -The next prompt immediately follows the code snippet. -.TP -\f[I]custom\f[R] -Provides custom feedback based on how the mode is defined. -Custom feedback modes are created within JShell by using the -\f[V]/set mode\f[R] command. -.RE -.TP -\f[V]--help\f[R] or \f[V]-h\f[R] or \f[V]-?\f[R] -Prints a summary of standard options and exits the tool. -.TP -\f[V]--help-extra\f[R] or \f[V]-X\f[R] -Prints a summary of nonstandard options and exits the tool. -Nonstandard options are subject to change without notice. -.TP -\f[V]-J\f[R]\f[I]flag\f[R] -passes \f[I]flag\f[R] to the runtime system, but has no effect on the -execution of code snippets. -To specify flags that affect the execution of code snippets, use -\f[V]-R\f[R]\f[I]flag\f[R]. -Alternatively, use \f[V]-J\f[R]\f[I]flag\f[R] with -\f[V]--execution local\f[R]. -.TP -\f[V]--module-path\f[R] \f[I]modulepath\f[R] -Specifies where to find application modules. -For Linux and macOS, use a colon (:) to separate items in the path. -For Windows, use a semicolon (;) to separate items. -.TP -\f[V]--no-startup\f[R] -Prevents startup scripts from running when JShell starts. -Use this option to run only the scripts entered on the command line when -JShell is started, or to start JShell without any preloaded information -if no scripts are entered. -This option can\[aq]t be used if the \f[V]--startup\f[R] option is used. -.TP -\f[V]-q\f[R] -Sets the feedback mode to \f[V]concise\f[R], which is the same as -entering \f[V]--feedback concise\f[R]. -.TP -\f[V]-R\f[R]\f[I]flag\f[R] -passes \f[I]flag\f[R] to the runtime system only when code snippets are -executed. -For example, \f[V]-R-Dfoo=bar\f[R] means that execution of the snippet -\f[V]System.getProperty(\[dq]foo\[dq])\f[R] will return -\f[V]\[dq]bar\[dq]\f[R]. -.TP -\f[V]-s\f[R] -Sets the feedback mode to \f[V]silent\f[R], which is the same as -entering \f[V]--feedback silent\f[R]. -.TP -\f[V]--show-version\f[R] -Prints version information and enters the tool. -.TP -\f[V]--startup\f[R] \f[I]file\f[R] -Overrides the default startup script for this session. -The script can contain any valid code snippets or commands. -.RS -.PP -The script can be a local file or one of the following predefined -scripts: -.TP -\f[V]DEFAULT\f[R] -Loads the default entries, which are commonly used as imports. -.TP -\f[V]JAVASE\f[R] -Imports all Java SE packages. -.TP -\f[V]PRINTING\f[R] -Defines \f[V]print\f[R], \f[V]println\f[R], and \f[V]printf\f[R] as -\f[V]jshell\f[R] methods for use within the tool. -.TP -\f[V]TOOLING\f[R] -Defines \f[V]javac\f[R], \f[V]jar\f[R], and other methods for running -JDK tools via their command-line interface within the \f[V]jshell\f[R] -tool. -.PP -For more than one script, provide a separate instance of this option for -each script. -Startup scripts are run when JShell is first started and when the -session is restarted with the \f[V]/reset\f[R], \f[V]/reload\f[R], or -\f[V]/env\f[R] command. -Startup scripts are run in the order in which they\[aq]re entered on the -command line. -.PP -This option can\[aq]t be used if the \f[V]--no-startup\f[R] option is -used. -.RE -.TP -\f[V]-v\f[R] -Sets the feedback mode to \f[V]verbose\f[R], which is the same as -entering \f[V]--feedback verbose\f[R]. -.TP -\f[V]--version\f[R] -Prints version information and exits the tool. -.SH JSHELL COMMANDS -.PP -Within the \f[V]jshell\f[R] tool, commands are used to modify the -environment and manage code snippets. -.TP -\f[V]/drop\f[R] {\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]} [{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]}...] -Drops snippets identified by name, ID, or ID range, making them -inactive. -For a range of IDs, provide the starting ID and ending ID separated with -a hyphen. -To provide a list, separate the items in the list with a space. -Use the \f[V]/list\f[R] command to see the IDs of code snippets. -.TP -\f[V]/edit\f[R] [\f[I]option\f[R]] -Opens an editor. -If no option is entered, then the editor opens with the active snippets. -.RS -.PP -The following options are valid: -.TP -{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]} [{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]}...] -Opens the editor with the snippets identified by name, ID, or ID range. -For a range of IDs, provide the starting ID and ending ID separated with -a hyphen. -To provide a list, separate the items in the list with a space. -Use the \f[V]/list\f[R] command to see the IDs of code snippets. -.TP -\f[V]-all\f[R] -Opens the editor with all snippets, including startup snippets and -snippets that failed, were overwritten, or were dropped. -.TP -\f[V]-start\f[R] -Opens the editor with startup snippets that were evaluated when JShell -was started. -.PP -To exit edit mode, close the editor window, or respond to the prompt -provided if the \f[V]-wait\f[R] option was used when the editor was set. -.PP -Use the \f[V]/set editor\f[R] command to specify the editor to use. -If no editor is set, then the following environment variables are -checked in order: \f[V]JSHELLEDITOR\f[R], \f[V]VISUAL\f[R], and -\f[V]EDITOR\f[R]. -If no editor is set in JShell and none of the editor environment -variables is set, then a simple default editor is used. -.RE -.TP -\f[V]/env\f[R] [\f[I]options\f[R]] -Displays the environment settings, or updates the environment settings -and restarts the session. -If no option is entered, then the current environment settings are -displayed. -If one or more options are entered, then the session is restarted as -follows: -.RS -.IP \[bu] 2 -Updates the environment settings with the provided options. -.IP \[bu] 2 -Resets the execution state. -.IP \[bu] 2 -Runs the startup scripts. -.IP \[bu] 2 -Silently replays the history in the order entered. -The history includes all valid snippets or \f[V]/drop\f[R] commands -entered at the \f[V]jshell\f[R] prompt, in scripts entered on the -command line, or scripts entered with the \f[V]/open\f[R] command. -.PP -Environment settings entered on the command line or provided with a -previous \f[V]/reset\f[R], \f[V]/env\f[R], or \f[V]/reload\f[R] command -are maintained unless an \f[I]option\f[R] is entered that overwrites the -setting. -.PP -The following options are valid: -.TP -\f[V]--add-modules\f[R] \f[I]module\f[R][\f[V],\f[R]\f[I]module\f[R]...] -Specifies the root modules to resolve in addition to the initial module. -.TP -\f[V]--add-exports\f[R] \f[I]source-module\f[R]\f[V]/\f[R]\f[I]package\f[R]\f[V]=\f[R]\f[I]target-module\f[R][\f[V],\f[R]\f[I]target-module\f[R]]* -Adds an export of \f[I]package\f[R] from \f[I]source-module\f[R] to -\f[I]target-module\f[R]. -.TP -\f[V]--class-path\f[R] \f[I]path\f[R] -Specifies the directories and archives that are searched to locate class -files. -This option overrides the path in the \f[V]CLASSPATH\f[R] environment -variable. -If the environment variable isn\[aq]t set and this option isn\[aq]t -used, then the current directory is searched. -For Linux and macOS, use a colon (\f[V]:\f[R]) to separate items in the -path. -For Windows, use a semicolon (\f[V];\f[R]) to separate items. -.TP -\f[V]--module-path\f[R] \f[I]modulepath\f[R] -Specifies where to find application modules. -For Linux and macOS, use a colon (\f[V]:\f[R]) to separate items in the -path. -For Windows, use a semicolon (\f[V];\f[R]) to separate items. -.RE -.TP -\f[V]/exit\f[R] [\f[I]integer-expression-snippet\f[R]] -Exits the tool. -If no snippet is entered, the exit status is zero. -If a snippet is entered and the result of the snippet is an integer, the -result is used as the exit status. -If an error occurs, or the result of the snippet is not an integer, an -error is displayed and the tool remains active. -.TP -\f[V]/history\f[R] -Displays what was entered in this session. -.TP -\f[V]/help\f[R] [\f[I]command\f[R]|\f[I]subject\f[R]] -Displays information about commands and subjects. -If no options are entered, then a summary of information for all -commands and a list of available subjects are displayed. -If a valid command is provided, then expanded information for that -command is displayed. -If a valid subject is entered, then information about that subject is -displayed. -.RS -.PP -The following values for \f[I]subject\f[R] are valid: -.TP -\f[V]context\f[R] -Describes the options that are available for configuring the -environment. -.TP -\f[V]intro\f[R] -Provides an introduction to the tool. -.TP -\f[V]shortcuts\f[R] -Describes keystrokes for completing commands and snippets. -See \f[B]Input Shortcuts\f[R]. -.RE -.TP -\f[V]/imports\f[R] -Displays the current active imports, including those from the startup -scripts and scripts that were entered on the command line when JShell -was started. -.TP -\f[V]/list\f[R] [\f[I]option\f[R]] -Displays a list of snippets and their IDs. -If no option is entered, then all active snippets are displayed, but -startup snippets aren\[aq]t. -.RS -.PP -The following options are valid: -.TP -{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]} [{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]}...] -Displays the snippets identified by name, ID, or ID range. -For a range of IDs, provide the starting ID and ending ID separated with -a hyphen. -To provide a list, separate the items in the list with a space. -.TP -\f[V]-all\f[R] -Displays all snippets, including startup snippets and snippets that -failed, were overwritten, or were dropped. -IDs that begin with \f[V]s\f[R] are startup snippets. -IDs that begin with \f[V]e\f[R] are snippets that failed. -.TP -\f[V]-start\f[R] -Displays startup snippets that were evaluated when JShell was started. -.RE -.TP -\f[V]/methods\f[R] [\f[I]option\f[R]] -Displays information about the methods that were entered. -If no option is entered, then the name, parameter types, and return type -of all active methods are displayed. -.RS -.PP -The following options are valid: -.TP -{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]} [{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]}...] -Displays information for methods identified by name, ID, or ID range. -For a range of IDs, provide the starting ID and ending ID separated with -a hyphen. -To provide a list, separate the items in the list with a space. -Use the \f[V]/list\f[R] command to see the IDs of code snippets. -.TP -\f[V]-all\f[R] -Displays information for all methods, including those added when JShell -was started, and methods that failed, were overwritten, or were dropped. -.TP -\f[V]-start\f[R] -Displays information for startup methods that were added when JShell was -started. -.RE -.TP -\f[V]/open\f[R] \f[I]file\f[R] -Opens the script specified and reads the snippets into the tool. -The script can be a local file or one of the following predefined -scripts: -.RS -.TP -\f[V]DEFAULT\f[R] -Loads the default entries, which are commonly used as imports. -.TP -\f[V]JAVASE\f[R] -Imports all Java SE packages. -.TP -\f[V]PRINTING\f[R] -Defines \f[V]print\f[R], \f[V]println\f[R], and \f[V]printf\f[R] as -\f[V]jshell\f[R] methods for use within the tool. -.TP -\f[V]TOOLING\f[R] -Defines \f[V]javac\f[R], \f[V]jar\f[R], and other methods for running -JDK tools via their command-line interface within the \f[V]jshell\f[R] -tool. -.RE -.TP -\f[V]/reload\f[R] [\f[I]options\f[R]] -Restarts the session as follows: -.RS -.IP \[bu] 2 -Updates the environment settings with the provided options, if any. -.IP \[bu] 2 -Resets the execution state. -.IP \[bu] 2 -Runs the startup scripts. -.IP \[bu] 2 -Replays the history in the order entered. -The history includes all valid snippets or \f[V]/drop\f[R] commands -entered at the \f[V]jshell\f[R] prompt, in scripts entered on the -command line, or scripts entered with the \f[V]/open\f[R] command. -.PP -Environment settings entered on the command line or provided with a -previous \f[V]/reset\f[R], \f[V]/env\f[R], or \f[V]/reload\f[R] command -are maintained unless an \f[I]option\f[R] is entered that overwrites the -setting. -.PP -The following options are valid: -.TP -\f[V]--add-modules\f[R] \f[I]module\f[R][\f[V],\f[R]\f[I]module\f[R]...] -Specifies the root modules to resolve in addition to the initial module. -.TP -\f[V]--add-exports\f[R] \f[I]source-module\f[R]\f[V]/\f[R]\f[I]package\f[R]\f[V]=\f[R]\f[I]target-module\f[R][\f[V],\f[R]\f[I]target-module\f[R]]* -Adds an export of \f[I]package\f[R] from \f[I]source-module\f[R] to -\f[I]target-module\f[R]. -.TP -\f[V]--class-path\f[R] \f[I]path\f[R] -Specifies the directories and archives that are searched to locate class -files. -This option overrides the path in the \f[V]CLASSPATH\f[R] environment -variable. -If the environment variable isn\[aq]t set and this option isn\[aq]t -used, then the current directory is searched. -For Linux and macOS, use a colon (\f[V]:\f[R]) to separate items in the -path. -For Windows, use a semicolon (\f[V];\f[R]) to separate items. -.TP -\f[V]--module-path\f[R] \f[I]modulepath\f[R] -Specifies where to find application modules. -For Linux and macOS, use a colon (\f[V]:\f[R]) to separate items in the -path. -For Windows, use a semicolon (\f[V];\f[R]) to separate items. -.TP -\f[V]-quiet\f[R] -Replays the valid history without displaying it. -Errors are displayed. -.TP -\f[V]-restore\f[R] -Resets the environment to the state at the start of the previous run of -the tool or to the last time a \f[V]/reset\f[R], \f[V]/reload\f[R], or -\f[V]/env\f[R] command was executed in the previous run. -The valid history since that point is replayed. -Use this option to restore a previous JShell session. -.RE -.TP -\f[V]/reset\f[R] [\f[I]options\f[R]] -Discards all entered snippets and restarts the session as follows: -.RS -.IP \[bu] 2 -Updates the environment settings with the provided options, if any. -.IP \[bu] 2 -Resets the execution state. -.IP \[bu] 2 -Runs the startup scripts. -.PP -History is not replayed. -All code that was entered is lost. -.PP -Environment settings entered on the command line or provided with a -previous \f[V]/reset\f[R], \f[V]/env\f[R], or \f[V]/reload\f[R] command -are maintained unless an \f[I]option\f[R] is entered that overwrites the -setting. -.PP -The following options are valid: -.TP -\f[V]--add-modules\f[R] \f[I]module\f[R][\f[V],\f[R]\f[I]module\f[R]...] -Specifies the root modules to resolve in addition to the initial module. -.TP -\f[V]--add-exports\f[R] \f[I]source-module\f[R]\f[V]/\f[R]\f[I]package\f[R]\f[V]=\f[R]\f[I]target-module\f[R][\f[V],\f[R]\f[I]target-module\f[R]]* -Adds an export of \f[I]package\f[R] from \f[I]source-module\f[R] to -\f[I]target-module\f[R]. -.TP -\f[V]--class-path\f[R] \f[I]path\f[R] -Specifies the directories and archives that are searched to locate class -files. -This option overrides the path in the \f[V]CLASSPATH\f[R] environment -variable. -If the environment variable isn\[aq]t set and this option isn\[aq]t -used, then the current directory is searched. -For Linux and macOS, use a colon (\f[V]:\f[R]) to separate items in the -path. -For Windows, use a semicolon (\f[V];\f[R]) to separate items. -.TP -\f[V]--module-path\f[R] \f[I]modulepath\f[R] -Specifies where to find application modules. -For Linux and macOS, use a colon (\f[V]:\f[R]) to separate items in the -path. -For Windows, use a semicolon (\f[V];\f[R]) to separate items. -.RE -.TP -\f[V]/save\f[R] [\f[I]options\f[R]] \f[I]file\f[R] -Saves snippets and commands to the file specified. -If no options are entered, then active snippets are saved. -.RS -.PP -The following options are valid: -.TP -{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]} [{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]}...] -Saves the snippets and commands identified by name, ID, or ID range. -For a range of IDs, provide the starting ID and ending ID separated with -a hyphen. -To provide a list, separate the items in the list with a space. -Use the \f[V]/list\f[R] command to see the IDs of the code snippets. -.TP -\f[V]-all\f[R] -Saves all snippets, including startup snippets and snippets that were -overwritten or failed. -.TP -\f[V]-history\f[R] -Saves the sequential history of all commands and snippets entered in the -current session. -.TP -\f[V]-start\f[R] -Saves the current startup settings. -If no startup scripts were provided, then an empty file is saved. -.RE -.TP -\f[V]/set\f[R] [\f[I]setting\f[R]] -Sets configuration information, including the external editor, startup -settings, and feedback mode. -This command is also used to create a custom feedback mode with -customized prompt, format, and truncation values. -If no setting is entered, then the current setting for the editor, -startup settings, and feedback mode are displayed. -.RS -.PP -The following values are valid for \f[V]setting\f[R]: -.TP -\f[V]editor\f[R] [\f[I]options\f[R]] [\f[I]command\f[R]] -Sets the command used to start an external editor when the -\f[V]/edit\f[R] command is entered. -The command can include command arguments separated by spaces. -If no command or options are entered, then the current setting is -displayed. -.RS -.PP -The following options are valid: -.TP -\f[V]-default\f[R] -Sets the editor to the default editor provided with JShell. -This option can\[aq]t be used if a command for starting an editor is -entered. -.TP -\f[V]-delete\f[R] -Sets the editor to the one in effect when the session started. -If used with the \f[V]-retain\f[R] option, then the retained editor -setting is deleted and the editor is set to the first of the following -environment variables found: \f[V]JSHELLEDITOR\f[R], \f[V]VISUAL\f[R], -or \f[V]EDITOR\f[R]. -If none of the editor environment variables are set, then this option -sets the editor to the default editor. -.RS -.PP -This option can\[aq]t be used if a command for starting an editor is -entered. -.RE -.TP -\f[V]-retain\f[R] -Saves the editor setting across sessions. -If no other option or a command is entered, then the current setting is -saved. -.TP -\f[V]-wait\f[R] -Prompts the user to indicate when editing is complete. -Otherwise control returns to JShell when the editor exits. -Use this option if the editor being used exits immediately, for example, -when an edit window already exists. -This option is valid only when a command for starting an editor is -entered. -.RE -.TP -\f[V]feedback\f[R] [\f[I]mode\f[R]] -Sets the feedback mode used to respond to input. -If no mode is entered, then the current mode is displayed. -.RS -.PP -The following modes are valid: \f[V]concise\f[R], \f[V]normal\f[R], -\f[V]silent\f[R], \f[V]verbose\f[R], and any custom mode created with -the \f[V]/set mode\f[R] command. -.RE -.TP -\f[V]format\f[R] \f[I]mode\f[R] \f[I]field\f[R] \f[V]\[dq]\f[R]\f[I]format-string\f[R]\f[V]\[dq]\f[R] \f[I]selector\f[R] -Sets the format of the feedback provided in response to input. -If no mode is entered, then the current formats for all fields for all -feedback modes are displayed. -If only a mode is entered, then the current formats for that mode are -displayed. -If only a mode and field are entered, then the current formats for that -field are displayed. -.RS -.PP -To define a format, the following arguments are required: -.TP -\f[I]mode\f[R] -Specifies a feedback mode to which the response format is applied. -Only custom modes created with the \f[V]/set mode\f[R] command can be -modified. -.TP -\f[I]field\f[R] -Specifies a context-specific field to which the response format is -applied. -The fields are described in the online help, which is accessed from -JShell using the \f[V]/help /set format\f[R] command. -.TP -\f[V]\[dq]\f[R]\f[I]format-string\f[R]\f[V]\[dq]\f[R] -Specifies the string to use as the response format for the specified -field and selector. -The structure of the format string is described in the online help, -which is accessed from JShell using the \f[V]/help /set format\f[R] -command. -.TP -\f[I]selector\f[R] -Specifies the context in which the response format is applied. -The selectors are described in the online help, which is accessed from -JShell using the \f[V]/help /set format\f[R] command. -.RE -.TP -\f[V]mode\f[R] [\f[I]mode-name\f[R]] [\f[I]existing-mode\f[R]] [\f[I]options\f[R]] -Creates a custom feedback mode with the mode name provided. -If no mode name is entered, then the settings for all modes are -displayed, which includes the mode, prompt, format, and truncation -settings. -If the name of an existing mode is provided, then the settings from the -existing mode are copied to the mode being created. -.RS -.PP -The following options are valid: -.TP -\f[V]-command\f[R]|\f[V]-quiet\f[R] -Specifies the level of feedback displayed for commands when using the -mode. -This option is required when creating a feedback mode. -Use \f[V]-command\f[R] to show information and verification feedback for -commands. -Use \f[V]-quiet\f[R] to show only essential feedback for commands, such -as error messages. -.TP -\f[V]-delete\f[R] -Deletes the named feedback mode for this session. -The name of the mode to delete is required. -To permanently delete a retained mode, use the \f[V]-retain\f[R] option -with this option. -Predefined modes can\[aq]t be deleted. -.TP -\f[V]-retain\f[R] -Saves the named feedback mode across sessions. -The name of the mode to retain is required. -.PP -Configure the new feedback mode using the \f[V]/set prompt\f[R], -\f[V]/set format\f[R], and \f[V]/set truncation\f[R] commands. -.PP -To start using the new mode, use the \f[V]/set feedback\f[R] command. -.RE -.TP -\f[V]prompt\f[R] \f[I]mode\f[R] \f[V]\[dq]\f[R]\f[I]prompt-string\f[R]\f[V]\[dq]\f[R] \f[V]\[dq]\f[R]\f[I]continuation-prompt-string\f[R]\f[V]\[dq]\f[R] -Sets the prompts for input within JShell. -If no mode is entered, then the current prompts for all feedback modes -are displayed. -If only a mode is entered, then the current prompts for that mode are -displayed. -.RS -.PP -To define a prompt, the following arguments are required: -.TP -\f[I]mode\f[R] -Specifies the feedback mode to which the prompts are applied. -Only custom modes created with the \f[V]/set mode\f[R] command can be -modified. -.TP -\f[V]\[dq]\f[R]\f[I]prompt-string\f[R]\f[V]\[dq]\f[R] -Specifies the string to use as the prompt for the first line of input. -.TP -\f[V]\[dq]\f[R]\f[I]continuation-prompt-string\f[R]\f[V]\[dq]\f[R] -Specifies the string to use as the prompt for the additional input lines -needed to complete a snippet. -.RE -.TP -\f[V]start\f[R] [\f[V]-retain\f[R]] [\f[I]file\f[R] [\f[I]file\f[R]...]|\f[I]option\f[R]] -Sets the names of the startup scripts used when the next -\f[V]/reset\f[R], \f[V]/reload\f[R], or \f[V]/env\f[R] command is -entered. -If more than one script is entered, then the scripts are run in the -order entered. -If no scripts or options are entered, then the current startup settings -are displayed. -.RS -.PP -The scripts can be local files or one of the following predefined -scripts: -.TP -\f[V]DEFAULT\f[R] -Loads the default entries, which are commonly used as imports. -.TP -\f[V]JAVASE\f[R] -Imports all Java SE packages. -.TP -\f[V]PRINTING\f[R] -Defines \f[V]print\f[R], \f[V]println\f[R], and \f[V]printf\f[R] as -\f[V]jshell\f[R] methods for use within the tool. -.TP -\f[V]TOOLING\f[R] -Defines \f[V]javac\f[R], \f[V]jar\f[R], and other methods for running -JDK tools via their command-line interface within the \f[V]jshell\f[R] -tool. -.PP -The following options are valid: -.TP -\f[V]-default\f[R] -Sets the startup settings to the default settings. -.TP -\f[V]-none\f[R] -Specifies that no startup settings are used. -.PP -Use the \f[V]-retain\f[R] option to save the start setting across -sessions. -.RE -.TP -\f[V]truncation\f[R] \f[I]mode\f[R] \f[I]length\f[R] \f[I]selector\f[R] -Sets the maximum length of a displayed value. -If no mode is entered, then the current truncation values for all -feedback modes are displayed. -If only a mode is entered, then the current truncation values for that -mode are displayed. -.RS -.PP -To define truncation values, the following arguments are required: -.TP -\f[I]mode\f[R] -Specifies the feedback mode to which the truncation value is applied. -Only custom modes created with the \f[V]/set mode\f[R] command can be -modified. -.TP -\f[I]length\f[R] -Specifies the unsigned integer to use as the maximum length for the -specified selector. -.TP -\f[I]selector\f[R] -Specifies the context in which the truncation value is applied. -The selectors are described in the online help, which is accessed from -JShell using the \f[V]/help /set truncation\f[R] command. -.RE -.RE -.TP -\f[V]/types\f[R] [\f[I]option\f[R]] -Displays classes, interfaces, and enums that were entered. -If no option is entered, then all current active classes, interfaces, -and enums are displayed. -.RS -.PP -The following options are valid: -.TP -{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]} [{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]}...] -Displays information for classes, interfaces, and enums identified by -name, ID, or ID range. -For a range of IDs, provide the starting ID and ending ID separated with -a hyphen. -To provide a list, separate the items in the list with a space. -Use the \f[V]/list\f[R] command to see the IDs of the code snippets. -.TP -\f[V]-all\f[R] -Displays information for all classes, interfaces, and enums, including -those added when JShell was started, and classes, interfaces, and enums -that failed, were overwritten, or were dropped. -.TP -\f[V]-start\f[R] -Displays information for startup classes, interfaces, and enums that -were added when JShell was started. -.RE -.TP -\f[V]/vars\f[R] [\f[I]option\f[R]] -Displays the name, type, and value of variables that were entered. -If no option is entered, then all current active variables are -displayed. -.RS -.PP -The following options are valid: -.TP -{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]} [{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]}...] -Displays information for variables identified by name, ID, or ID range. -For a range of IDs, provide the starting ID and ending ID separated with -a hyphen. -To provide a list, separate the items in the list with a space. -Use the \f[V]/list\f[R] command to see the IDs of the code snippets. -.TP -\f[V]-all\f[R] -Displays information for all variables, including those added when -JShell was started, and variables that failed, were overwritten, or were -dropped. -.TP -\f[V]-start\f[R] -Displays information for startup variables that were added when JShell -was started. -.RE -.TP -\f[V]/?\f[R] -Same as the \f[V]/help\f[R] command. -.TP -\f[V]/!\f[R] -Reruns the last snippet. -.TP -\f[V]/\f[R]{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]} [{\f[I]name\f[R]|\f[I]id\f[R]|\f[I]startID\f[R]\f[V]-\f[R]\f[I]endID\f[R]}...] -Reruns the snippets identified by ID, range of IDs, or name. -For a range of IDs, provide the starting ID and ending ID separated with -a hyphen. -To provide a list, separate the items in the list with a space. -The first item in the list must be an ID or ID range. -Use the \f[V]/list\f[R] command to see the IDs of the code snippets. -.TP -\f[V]/-\f[R]\f[I]n\f[R] -Reruns the -\f[I]n\f[R]th previous snippet. -For example, if 15 code snippets were entered, then \f[V]/-4\f[R] runs -the 11th snippet. -Commands aren\[aq]t included in the count. -.SH INPUT SHORTCUTS -.PP -The following shortcuts are available for entering commands and snippets -in JShell. -.SS Tab completion -.TP -\f[B]<tab>\f[R] -When entering snippets, commands, subcommands, command arguments, or -command options, use the Tab key to automatically complete the item. -If the item can\[aq]t be determined from what was entered, then possible -options are provided. -.RS -.PP -When entering a method call, use the Tab key after the method call\[aq]s -opening parenthesis to see the parameters for the method. -If the method has more than one signature, then all signatures are -displayed. -Pressing the Tab key a second time displays the description of the -method and the parameters for the first signature. -Continue pressing the Tab key for a description of any additional -signatures. -.RE -.TP -\f[B]Shift+<Tab> V\f[R] -After entering a complete expression, use this key sequence to convert -the expression to a variable declaration of a type determined by the -type of the expression. -.TP -\f[B]Shift+<Tab> M\f[R] -After entering a complete expression or statement, use this key sequence -to convert the expression or statement to a method declaration. -If an expression is entered, the return type is based on the type of the -expression. -.TP -\f[B]Shift+<Tab> I\f[R] -When an identifier is entered that can\[aq]t be resolved, use this key -sequence to show possible imports that resolve the identifier based on -the content of the specified class path. -.SS Command abbreviations -.PP -An abbreviation of a command is accepted if the abbreviation uniquely -identifies a command. -For example, \f[V]/l\f[R] is recognized as the \f[V]/list\f[R] command. -However, \f[V]/s\f[R] isn\[aq]t a valid abbreviation because it -can\[aq]t be determined if the \f[V]/set\f[R] or \f[V]/save\f[R] command -is meant. -Use \f[V]/se\f[R] for the \f[V]/set\f[R] command or \f[V]/sa\f[R] for -the \f[V]/save\f[R] command. -.PP -Abbreviations are also accepted for subcommands, command arguments, and -command options. -For example, use \f[V]/m -a\f[R] to display all methods. -.SS History navigation -.PP -A history of what was entered is maintained across sessions. -Use the up and down arrows to scroll through commands and snippets from -the current and past sessions. -Use the Ctrl key with the up and down arrows to skip all but the first -line of multiline snippets. -.SS History search -.PP -Use the Ctrl+R key combination to search the history for the string -entered. -The prompt changes to show the string and the match. -Ctrl+R searches backwards from the current location in the history -through earlier entries. -Ctrl+S searches forward from the current location in the history though -later entries. -.SH INPUT EDITING -.PP -The editing capabilities of JShell are similar to that of other common -shells. -Keyboard keys and key combinations provide line editing shortcuts. -The Ctrl key and Meta key are used in key combinations. -If your keyboard doesn\[aq]t have a Meta key, then the Alt key is often -mapped to provide Meta key functionality. -.PP -Line Editing Shortcuts -.TS -tab(@); -l l. -T{ -Key or Key Combination -T}@T{ -Action -T} -_ -T{ -Return -T}@T{ -Enter the current line. -T} -T{ -Left arrow -T}@T{ -Move the cursor to the left one character. -T} -T{ -Right arrow Move -T}@T{ -the cursor to the right one character. -T} -T{ -Ctrl+A -T}@T{ -Move the cursor to the beginning of the line. -T} -T{ -Ctrl+E -T}@T{ -Move the cursor to the end of the line. -T} -T{ -Meta+B -T}@T{ -Move the cursor to the left one word. -T} -T{ -Meta+F -T}@T{ -Move the cursor to the right one word. -T} -T{ -Delete -T}@T{ -Delete the character under the cursor. -T} -T{ -Backspace -T}@T{ -Delete the character before the cursor. -T} -T{ -Ctrl+K -T}@T{ -Delete the text from the cursor to the end of the line. -T} -T{ -Meta+D -T}@T{ -Delete the text from the cursor to the end of the word. -T} -T{ -Ctrl+W -T}@T{ -Delete the text from the cursor to the previous white space. -T} -T{ -Ctrl+Y -T}@T{ -Paste the most recently deleted text into the line. -T} -T{ -Meta+Y -T}@T{ -After Ctrl+Y, press to cycle through the previously deleted text. -T} -.TE -.SH EXAMPLE OF STARTING AND STOPPING A JSHELL SESSION -.PP -JShell is provided with the JDK. -To start a session, enter \f[V]jshell\f[R] on the command line. -A welcome message is printed, and a prompt for entering commands and -snippets is provided. -.IP -.nf -\f[CB] -% jshell -| Welcome to JShell -- Version 9 -| For an introduction type: /help intro - -jshell> -\f[R] -.fi -.PP -To see which snippets were automatically loaded when JShell started, use -the \f[V]/list -start\f[R] command. -The default startup snippets are import statements for common packages. -The ID for each snippet begins with the letter \f[I]s\f[R], which -indicates it\[aq]s a startup snippet. -.IP -.nf -\f[CB] -jshell> /list -start - - s1 : import java.io.*; - s2 : import java.math.*; - s3 : import java.net.*; - s4 : import java.nio.file.*; - s5 : import java.util.*; - s6 : import java.util.concurrent.*; - s7 : import java.util.function.*; - s8 : import java.util.prefs.*; - s9 : import java.util.regex.*; - s10 : import java.util.stream.*; - -jshell> -\f[R] -.fi -.PP -To end the session, use the \f[V]/exit\f[R] command. -.IP -.nf -\f[CB] -jshell> /exit -| Goodbye - -% -\f[R] -.fi -.SH EXAMPLE OF ENTERING SNIPPETS -.PP -Snippets are Java statements, variable definitions, method definitions, -class definitions, import statements, and expressions. -Terminating semicolons are automatically added to the end of a completed -snippet if they\[aq]re missing. -.PP -The following example shows two variables and a method being defined, -and the method being run. -Note that a scratch variable is automatically created to hold the result -because no variable was provided. -.IP -.nf -\f[CB] -jshell> int a=4 -a ==> 4 - -jshell> int b=8 -b ==> 8 - -jshell> int square(int i1) { - ...> return i1 * i1; - ...> } -| created method square(int) - -jshell> square(b) -$5 ==> 64 -\f[R] -.fi -.SH EXAMPLE OF CHANGING SNIPPETS -.PP -Change the definition of a variable, method, or class by entering it -again. -.PP -The following examples shows a method being defined and the method run: -.IP -.nf -\f[CB] -jshell> String grade(int testScore) { - ...> if (testScore >= 90) { - ...> return \[dq]Pass\[dq]; - ...> } - ...> return \[dq]Fail\[dq]; - ...> } -| created method grade(int) - -jshell> grade(88) -$3 ==> \[dq]Fail\[dq] -\f[R] -.fi -.PP -To change the method \f[V]grade\f[R] to allow more students to pass, -enter the method definition again and change the pass score to -\f[V]80\f[R]. -Use the up arrow key to retrieve the previous entries to avoid having to -reenter them and make the change in the \f[V]if\f[R] statement. -The following example shows the new definition and reruns the method to -show the new result: -.IP -.nf -\f[CB] -jshell> String grade(int testScore) { - ...> if (testScore >= 80) { - ...> return \[dq]Pass\[dq]; - ...> } - ...> return \[dq]Fail\[dq]; - ...> } -| modified method grade(int) - -jshell> grade(88) -$5 ==> \[dq]Pass\[dq] -\f[R] -.fi -.PP -For snippets that are more than a few lines long, or to make more than a -few changes, use the \f[V]/edit\f[R] command to open the snippet in an -editor. -After the changes are complete, close the edit window to return control -to the JShell session. -The following example shows the command and the feedback provided when -the edit window is closed. -The \f[V]/list\f[R] command is used to show that the pass score was -changed to \f[V]85\f[R]. -.IP -.nf -\f[CB] -jshell> /edit grade -| modified method grade(int) -jshell> /list grade - - 6 : String grade(int testScore) { - if (testScore >= 85) { - return \[dq]Pass\[dq]; - } - return \[dq]Fail\[dq]; - } -\f[R] -.fi -.SH EXAMPLE OF CREATING A CUSTOM FEEDBACK MODE -.PP -The feedback mode determines the prompt that\[aq]s displayed, the -feedback messages that are provided as snippets are entered, and the -maximum length of a displayed value. -Predefined feedback modes are provided. -Commands for creating custom feedback modes are also provided. -.PP -Use the \f[V]/set mode\f[R] command to create a new feedback mode. -In the following example, the new mode \f[V]mymode\f[R], is based on the -predefined feedback mode, \f[V]normal\f[R], and verifying command -feedback is displayed: -.IP -.nf -\f[CB] -jshell> /set mode mymode normal -command -| Created new feedback mode: mymode -\f[R] -.fi -.PP -Because the new mode is based on the \f[V]normal\f[R] mode, the prompts -are the same. -The following example shows how to see what prompts are used and then -changes the prompts to custom strings. -The first string represents the standard JShell prompt. -The second string represents the prompt for additional lines in -multiline snippets. -.IP -.nf -\f[CB] -jshell> /set prompt mymode -| /set prompt mymode \[dq]\[rs]njshell> \[dq] \[dq] ...> \[dq] - -jshell> /set prompt mymode \[dq]\[rs]nprompt$ \[dq] \[dq] continue$ \[dq] -\f[R] -.fi -.PP -The maximum length of a displayed value is controlled by the truncation -setting. -Different types of values can have different lengths. -The following example sets an overall truncation value of 72, and a -truncation value of 500 for variable value expressions: -.IP -.nf -\f[CB] -jshell> /set truncation mymode 72 - -jshell> /set truncation mymode 500 varvalue -\f[R] -.fi -.PP -The feedback displayed after snippets are entered is controlled by the -format setting and is based on the type of snippet entered and the -action taken for that snippet. -In the predefined mode \f[V]normal\f[R], the string \f[V]created\f[R] is -displayed when a method is created. -The following example shows how to change that string to -\f[V]defined\f[R]: -.IP -.nf -\f[CB] -jshell> /set format mymode action \[dq]defined\[dq] added-primary -\f[R] -.fi -.PP -Use the \f[V]/set feedback\f[R] command to start using the feedback mode -that was just created. -The following example shows the custom mode in use: -.IP -.nf -\f[CB] -jshell> /set feedback mymode -| Feedback mode: mymode - -prompt$ int square (int num1){ - continue$ return num1*num1; - continue$ } -| defined method square(int) - -prompt$ -\f[R] -.fi diff --git a/src/jdk.jshell/share/man/jshell.md b/src/jdk.jshell/share/man/jshell.md new file mode 100644 index 00000000000..b9f9fe577cf --- /dev/null +++ b/src/jdk.jshell/share/man/jshell.md @@ -0,0 +1,1042 @@ +--- +# Copyright (c) 2017, 2023, 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. +# + +title: 'JSHELL(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jshell - interactively evaluate declarations, statements, and expressions of +the Java programming language in a read-eval-print loop (REPL) + +## Synopsis + +`jshell` \[*options*\] \[*load-files*\] + +*options* +: Command-line options, separated by spaces. See [Options for jshell]. + +*load-files* +: One or more scripts to run when the tool is started. Scripts can contain + any valid code snippets or JShell commands. + + The script can be a local file or one of following predefined scripts: + + `DEFAULT` + : Loads the default entries, which are commonly used as imports. + + `JAVASE` + : Imports all Java SE packages. + + `PRINTING` + : Defines `print`, `println`, and `printf` as `jshell` methods for use + within the tool. + + `TOOLING` + : Defines `javac`, `jar`, and other methods for running JDK tools via + their command-line interface within the `jshell` tool. + + For more than one script, use a space to separate the names. Scripts are + run in the order in which they're entered on the command line. Command-line + scripts are run after startup scripts. To run a script after JShell is + started, use the `/open` command. + + To accept input from standard input and suppress the interactive I/O, enter + a hyphen (-) for *load-files*. This option enables the use of the `jshell` + tool in pipe chains. + +## Description + +JShell provides a way to interactively evaluate declarations, statements, and +expressions of the Java programming language, making it easier to learn the +language, explore unfamiliar code and APIs, and prototype complex code. Java +statements, variable definitions, method definitions, class definitions, import +statements, and expressions are accepted. The bits of code entered are called +snippets. + +As snippets are entered, they're evaluated, and feedback is provided. Feedback +varies from the results and explanations of actions to nothing, depending on +the snippet entered and the feedback mode chosen. Errors are described +regardless of the feedback mode. Start with the verbose mode to get the most +feedback while learning the tool. + +Command-line options are available for configuring the initial environment when +JShell is started. Within JShell, commands are available for modifying the +environment as needed. + +Existing snippets can be loaded from a file to initialize a JShell session, or +at any time within a session. Snippets can be modified within the session to +try out different variations and make corrections. To keep snippets for later +use, save them to a file. + +## Options for jshell + +`--add-exports` *module*/*package* +: Specifies a package to be considered as exported from its defining module. + +`--add-modules` *module*\[`,`*module*...\] +: Specifies the root modules to resolve in addition to the initial module. + +`-C`*flag* +: passes *flag* to the Java compiler inside JShell. For example, `-C-Xlint` + enables all the recommended lint warnings, and `-C--release=<N>` compiles + for Java SE N, as if --release N was specified. + +`--class-path` *path* +: Specifies the directories and archives that are searched to locate class + files. This option overrides the path in the `CLASSPATH` environment + variable. If the environment variable isn't set and this option isn't used, + then the current directory is searched. For Linux and macOS, use a colon + (:) to separate items in the path. For Windows, use a semicolon (;) to + separate items. + +`--enable-preview` +: Allows code to depend on the preview features of this release. + +`--execution` *specification* +: Specifies an alternate execution engine, where *specification* is an + ExecutionControl spec. See the documentation of the package jdk.jshell.spi + for the syntax of the spec. + +`--feedback` *mode* +: Sets the initial level of feedback provided in response to what's entered. + The initial level can be overridden within a session by using the + `/set feedback` *mode* command. The default is `normal`. + + The following values are valid for *mode*: + + `verbose` + : Provides detailed feedback for entries. Additional information about + the action performed is displayed after the result of the action. The + next prompt is separated from the feedback by a blank line. + + `normal` + : Provides an average amount of feedback. The next prompt is separated + from the feedback by a blank line. + + `concise` + : Provides minimal feedback. The next prompt immediately follows the code + snippet or feedback. + + `silent` + : Provides no feedback. The next prompt immediately follows the code + snippet. + + *custom* + : Provides custom feedback based on how the mode is defined. Custom + feedback modes are created within JShell by using the `/set mode` + command. + +`--help` or `-h` or `-?` +: Prints a summary of standard options and exits the tool. + +`--help-extra` or `-X` +: Prints a summary of nonstandard options and exits the tool. Nonstandard + options are subject to change without notice. + +`-J`*flag* +: passes *flag* to the runtime system, but has no effect on the execution of + code snippets. To specify flags that affect the execution of code snippets, + use `-R`*flag*. Alternatively, use `-J`*flag* with `--execution local`. + +`--module-path` *modulepath* +: Specifies where to find application modules. For Linux and macOS, use a + colon (:) to separate items in the path. For Windows, use a semicolon (;) + to separate items. + +`--no-startup` +: Prevents startup scripts from running when JShell starts. Use this option + to run only the scripts entered on the command line when JShell is started, + or to start JShell without any preloaded information if no scripts are + entered. This option can't be used if the `--startup` option is used. + +`-q` +: Sets the feedback mode to `concise`, which is the same as entering + `--feedback concise`. + +`-R`*flag* +: passes *flag* to the runtime system only when code snippets are executed. + For example, `-R-Dfoo=bar` means that execution of the snippet + `System.getProperty("foo")` will return `"bar"`. + +`-s` +: Sets the feedback mode to `silent`, which is the same as entering + `--feedback silent`. + +`--show-version` +: Prints version information and enters the tool. + +`--startup` *file* +: Overrides the default startup script for this session. The script can + contain any valid code snippets or commands. + + The script can be a local file or one of the following predefined scripts: + + `DEFAULT` + : Loads the default entries, which are commonly used as imports. + + `JAVASE` + : Imports all Java SE packages. + + `PRINTING` + : Defines `print`, `println`, and `printf` as `jshell` methods for use + within the tool. + + `TOOLING` + : Defines `javac`, `jar`, and other methods for running JDK tools via + their command-line interface within the `jshell` tool. + + For more than one script, provide a separate instance of this option for + each script. Startup scripts are run when JShell is first started and when + the session is restarted with the `/reset`, `/reload`, or `/env` command. + Startup scripts are run in the order in which they're entered on the + command line. + + This option can't be used if the `--no-startup` option is used. + +`-v` +: Sets the feedback mode to `verbose`, which is the same as entering + `--feedback verbose`. + +`--version` +: Prints version information and exits the tool. + +## jshell Commands + +Within the `jshell` tool, commands are used to modify the environment and +manage code snippets. + +`/drop` {*name*\|*id*\|*startID*`-`*endID*} \[{*name*\|*id*\|*startID*`-`*endID*}...\] +: Drops snippets identified by name, ID, or ID range, making them inactive. + For a range of IDs, provide the starting ID and ending ID separated with a + hyphen. To provide a list, separate the items in the list with a space. Use + the `/list` command to see the IDs of code snippets. + +`/edit` \[*option*\] +: Opens an editor. If no option is entered, then the editor opens with the + active snippets. + + The following options are valid: + + {*name*\|*id*\|*startID*`-`*endID*} \[{*name*\|*id*\|*startID*`-`*endID*}...\] + : Opens the editor with the snippets identified by name, ID, or ID range. + For a range of IDs, provide the starting ID and ending ID separated + with a hyphen. To provide a list, separate the items in the list with a + space. Use the `/list` command to see the IDs of code snippets. + + `-all` + : Opens the editor with all snippets, including startup snippets and + snippets that failed, were overwritten, or were dropped. + + `-start` + : Opens the editor with startup snippets that were evaluated when JShell + was started. + + To exit edit mode, close the editor window, or respond to the prompt + provided if the `-wait` option was used when the editor was set. + + Use the `/set editor` command to specify the editor to use. If no editor is + set, then the following environment variables are checked in order: + `JSHELLEDITOR`, `VISUAL`, and `EDITOR`. If no editor is set in JShell and + none of the editor environment variables is set, then a simple default + editor is used. + +`/env` \[*options*\] +: Displays the environment settings, or updates the environment settings and + restarts the session. If no option is entered, then the current environment + settings are displayed. If one or more options are entered, then the + session is restarted as follows: + + - Updates the environment settings with the provided options. + + - Resets the execution state. + + - Runs the startup scripts. + + - Silently replays the history in the order entered. The history includes + all valid snippets or `/drop` commands entered at the `jshell` prompt, + in scripts entered on the command line, or scripts entered with the + `/open` command. + + Environment settings entered on the command line or provided with a + previous `/reset`, `/env`, or `/reload` command are maintained unless an + *option* is entered that overwrites the setting. + + The following options are valid: + + `--add-modules` *module*\[`,`*module*...\] + : Specifies the root modules to resolve in addition to the initial + module. + + `--add-exports` *source-module*`/`*package*`=`*target-module*\[`,`*target-module*\]\* + : Adds an export of *package* from *source-module* to *target-module*. + + `--class-path` *path* + : Specifies the directories and archives that are searched to locate + class files. This option overrides the path in the `CLASSPATH` + environment variable. If the environment variable isn't set and this + option isn't used, then the current directory is searched. For Linux + and macOS, use a colon (`:`) to separate items in the path. For Windows, + use a semicolon (`;`) to separate items. + + `--module-path` *modulepath* + : Specifies where to find application modules. For Linux and macOS, use + a colon (`:`) to separate items in the path. For Windows, use a + semicolon (`;`) to separate items. + +`/exit` \[*integer-expression-snippet*\] +: Exits the tool. If no snippet is entered, the exit status is zero. If a + snippet is entered and the result of the snippet is an integer, the result + is used as the exit status. If an error occurs, or the result of the + snippet is not an integer, an error is displayed and the tool remains + active. + +`/history` +: Displays what was entered in this session. + +`/help` \[*command*\|*subject*\] +: Displays information about commands and subjects. If no options are + entered, then a summary of information for all commands and a list of + available subjects are displayed. If a valid command is provided, then + expanded information for that command is displayed. If a valid subject is + entered, then information about that subject is displayed. + + The following values for *subject* are valid: + + `context` + : Describes the options that are available for configuring the + environment. + + `intro` + : Provides an introduction to the tool. + + `shortcuts` + : Describes keystrokes for completing commands and snippets. See [Input + Shortcuts]. + +`/imports` +: Displays the current active imports, including those from the startup + scripts and scripts that were entered on the command line when JShell was + started. + +`/list` \[*option*\] +: Displays a list of snippets and their IDs. If no option is entered, then + all active snippets are displayed, but startup snippets aren't. + + The following options are valid: + + {*name*\|*id*\|*startID*`-`*endID*} \[{*name*\|*id*\|*startID*`-`*endID*}...\] + : Displays the snippets identified by name, ID, or ID range. For a range + of IDs, provide the starting ID and ending ID separated with a hyphen. + To provide a list, separate the items in the list with a space. + + `-all` + : Displays all snippets, including startup snippets and snippets that + failed, were overwritten, or were dropped. IDs that begin with `s` are + startup snippets. IDs that begin with `e` are snippets that failed. + + `-start` + : Displays startup snippets that were evaluated when JShell was started. + +`/methods` \[*option*\] +: Displays information about the methods that were entered. If no option is + entered, then the name, parameter types, and return type of all active + methods are displayed. + + The following options are valid: + + {*name*\|*id*\|*startID*`-`*endID*} \[{*name*\|*id*\|*startID*`-`*endID*}...\] + : Displays information for methods identified by name, ID, or ID range. + For a range of IDs, provide the starting ID and ending ID separated + with a hyphen. To provide a list, separate the items in the list with a + space. Use the `/list` command to see the IDs of code snippets. + + `-all` + : Displays information for all methods, including those added when JShell + was started, and methods that failed, were overwritten, or were + dropped. + + `-start` + : Displays information for startup methods that were added when JShell + was started. + +`/open` *file* +: Opens the script specified and reads the snippets into the tool. The script + can be a local file or one of the following predefined scripts: + + `DEFAULT` + : Loads the default entries, which are commonly used as imports. + + `JAVASE` + : Imports all Java SE packages. + + `PRINTING` + : Defines `print`, `println`, and `printf` as `jshell` methods for use + within the tool. + + `TOOLING` + : Defines `javac`, `jar`, and other methods for running JDK tools via + their command-line interface within the `jshell` tool. + +`/reload` \[*options*\] +: Restarts the session as follows: + + - Updates the environment settings with the provided options, if any. + + - Resets the execution state. + + - Runs the startup scripts. + + - Replays the history in the order entered. The history includes all + valid snippets or `/drop` commands entered at the `jshell` prompt, in + scripts entered on the command line, or scripts entered with the + `/open` command. + + Environment settings entered on the command line or provided with a + previous `/reset`, `/env`, or `/reload` command are maintained unless an + *option* is entered that overwrites the setting. + + The following options are valid: + + `--add-modules` *module*\[`,`*module*...\] + : Specifies the root modules to resolve in addition to the initial + module. + + `--add-exports` *source-module*`/`*package*`=`*target-module*\[`,`*target-module*\]\* + : Adds an export of *package* from *source-module* to *target-module*. + + `--class-path` *path* + : Specifies the directories and archives that are searched to locate + class files. This option overrides the path in the `CLASSPATH` + environment variable. If the environment variable isn't set and this + option isn't used, then the current directory is searched. For Linux + and macOS, use a colon (`:`) to separate items in the path. For + Windows, use a semicolon (`;`) to separate items. + + `--module-path` *modulepath* + : Specifies where to find application modules. For Linux and macOS, use + a colon (`:`) to separate items in the path. For Windows, use a + semicolon (`;`) to separate items. + + `-quiet` + : Replays the valid history without displaying it. Errors are displayed. + + `-restore` + : Resets the environment to the state at the start of the previous run of + the tool or to the last time a `/reset`, `/reload`, or `/env` command + was executed in the previous run. The valid history since that point is + replayed. Use this option to restore a previous JShell session. + +`/reset` \[*options*\] +: Discards all entered snippets and restarts the session as follows: + + - Updates the environment settings with the provided options, if any. + + - Resets the execution state. + + - Runs the startup scripts. + + History is not replayed. All code that was entered is lost. + + Environment settings entered on the command line or provided with a + previous `/reset`, `/env`, or `/reload` command are maintained unless an + *option* is entered that overwrites the setting. + + The following options are valid: + + `--add-modules` *module*\[`,`*module*...\] + : Specifies the root modules to resolve in addition to the initial + module. + + `--add-exports` *source-module*`/`*package*`=`*target-module*\[`,`*target-module*\]\* + : Adds an export of *package* from *source-module* to *target-module*. + + `--class-path` *path* + : Specifies the directories and archives that are searched to locate + class files. This option overrides the path in the `CLASSPATH` + environment variable. If the environment variable isn't set and this + option isn't used, then the current directory is searched. For Linux + and macOS, use a colon (`:`) to separate items in the path. For + Windows, use a semicolon (`;`) to separate items. + + `--module-path` *modulepath* + : Specifies where to find application modules. For Linux and macOS, use + a colon (`:`) to separate items in the path. For Windows, use a + semicolon (`;`) to separate items. + +`/save` \[*options*\] *file* +: Saves snippets and commands to the file specified. If no options are + entered, then active snippets are saved. + + The following options are valid: + + {*name*\|*id*\|*startID*`-`*endID*} \[{*name*\|*id*\|*startID*`-`*endID*}...\] + : Saves the snippets and commands identified by name, ID, or ID range. + For a range of IDs, provide the starting ID and ending ID separated + with a hyphen. To provide a list, separate the items in the list with a + space. Use the `/list` command to see the IDs of the code snippets. + + `-all` + : Saves all snippets, including startup snippets and snippets that were + overwritten or failed. + + `-history` + : Saves the sequential history of all commands and snippets entered in + the current session. + + `-start` + : Saves the current startup settings. If no startup scripts were + provided, then an empty file is saved. + +`/set` \[*setting*\] +: Sets configuration information, including the external editor, startup + settings, and feedback mode. This command is also used to create a custom + feedback mode with customized prompt, format, and truncation values. If no + setting is entered, then the current setting for the editor, startup + settings, and feedback mode are displayed. + + The following values are valid for `setting`: + + `editor` \[*options*\] \[*command*\] + : Sets the command used to start an external editor when the `/edit` + command is entered. The command can include command arguments separated + by spaces. If no command or options are entered, then the current + setting is displayed. + + The following options are valid: + + `-default` + : Sets the editor to the default editor provided with JShell. This + option can't be used if a command for starting an editor is + entered. + + `-delete` + : Sets the editor to the one in effect when the session started. If + used with the `-retain` option, then the retained editor setting is + deleted and the editor is set to the first of the following + environment variables found: `JSHELLEDITOR`, `VISUAL`, or `EDITOR`. + If none of the editor environment variables are set, then this + option sets the editor to the default editor. + + This option can't be used if a command for starting an editor is + entered. + + `-retain` + : Saves the editor setting across sessions. If no other option or a + command is entered, then the current setting is saved. + + `-wait` + : Prompts the user to indicate when editing is complete. Otherwise + control returns to JShell when the editor exits. Use this option if + the editor being used exits immediately, for example, when an edit + window already exists. This option is valid only when a command for + starting an editor is entered. + + `feedback` \[*mode*\] + : Sets the feedback mode used to respond to input. If no mode is entered, + then the current mode is displayed. + + The following modes are valid: `concise`, `normal`, `silent`, + `verbose`, and any custom mode created with the `/set mode` command. + + `format` *mode* *field* `"`*format-string*`"` *selector* + : Sets the format of the feedback provided in response to input. If no + mode is entered, then the current formats for all fields for all + feedback modes are displayed. If only a mode is entered, then the + current formats for that mode are displayed. If only a mode and field + are entered, then the current formats for that field are displayed. + + To define a format, the following arguments are required: + + *mode* + : Specifies a feedback mode to which the response format is applied. + Only custom modes created with the `/set mode` command can be + modified. + + *field* + : Specifies a context-specific field to which the response format is + applied. The fields are described in the online help, which is + accessed from JShell using the `/help /set format` command. + + `"`*format-string*`"` + : Specifies the string to use as the response format for the + specified field and selector. The structure of the format string is + described in the online help, which is accessed from JShell using + the `/help /set format` command. + + *selector* + : Specifies the context in which the response format is applied. The + selectors are described in the online help, which is accessed from + JShell using the `/help /set format` command. + + `mode` \[*mode-name*\] \[*existing-mode*\] \[*options*\] + : Creates a custom feedback mode with the mode name provided. If no mode + name is entered, then the settings for all modes are displayed, which + includes the mode, prompt, format, and truncation settings. If the name + of an existing mode is provided, then the settings from the existing + mode are copied to the mode being created. + + The following options are valid: + + `-command`\|`-quiet` + : Specifies the level of feedback displayed for commands when using + the mode. This option is required when creating a feedback mode. + Use `-command` to show information and verification feedback for + commands. Use `-quiet` to show only essential feedback for + commands, such as error messages. + + `-delete` + : Deletes the named feedback mode for this session. The name of the + mode to delete is required. To permanently delete a retained mode, + use the `-retain` option with this option. Predefined modes can't + be deleted. + + `-retain` + : Saves the named feedback mode across sessions. The name of the mode + to retain is required. + + Configure the new feedback mode using the `/set prompt`, `/set format`, + and `/set truncation` commands. + + To start using the new mode, use the `/set feedback` command. + + `prompt` *mode* `"`*prompt-string*`"` `"`*continuation-prompt-string*`"` + : Sets the prompts for input within JShell. If no mode is entered, then + the current prompts for all feedback modes are displayed. If only a + mode is entered, then the current prompts for that mode are displayed. + + To define a prompt, the following arguments are required: + + *mode* + : Specifies the feedback mode to which the prompts are applied. Only + custom modes created with the `/set mode` command can be modified. + + `"`*prompt-string*`"` + : Specifies the string to use as the prompt for the first line of + input. + + `"`*continuation-prompt-string*`"` + : Specifies the string to use as the prompt for the additional input + lines needed to complete a snippet. + + `start` \[`-retain`\] \[*file* \[*file*...\]\|*option*\] + : Sets the names of the startup scripts used when the next `/reset`, + `/reload`, or `/env` command is entered. If more than one script is + entered, then the scripts are run in the order entered. If no scripts + or options are entered, then the current startup settings are + displayed. + + The scripts can be local files or one of the following predefined + scripts: + + `DEFAULT` + : Loads the default entries, which are commonly used as imports. + + `JAVASE` + : Imports all Java SE packages. + + `PRINTING` + : Defines `print`, `println`, and `printf` as `jshell` methods for + use within the tool. + + `TOOLING` + : Defines `javac`, `jar`, and other methods for running JDK tools via + their command-line interface within the `jshell` tool. + + The following options are valid: + + `-default` + : Sets the startup settings to the default settings. + + `-none` + : Specifies that no startup settings are used. + + Use the `-retain` option to save the start setting across sessions. + + `truncation` *mode* *length* *selector* + : Sets the maximum length of a displayed value. If no mode is entered, + then the current truncation values for all feedback modes are + displayed. If only a mode is entered, then the current truncation + values for that mode are displayed. + + To define truncation values, the following arguments are required: + + *mode* + : Specifies the feedback mode to which the truncation value is + applied. Only custom modes created with the `/set mode` command can + be modified. + + *length* + : Specifies the unsigned integer to use as the maximum length for the + specified selector. + + *selector* + : Specifies the context in which the truncation value is applied. The + selectors are described in the online help, which is accessed from + JShell using the `/help /set truncation` command. + +`/types` \[*option*\] +: Displays classes, interfaces, and enums that were entered. If no option is + entered, then all current active classes, interfaces, and enums are + displayed. + + The following options are valid: + + {*name*\|*id*\|*startID*`-`*endID*} \[{*name*\|*id*\|*startID*`-`*endID*}...\] + : Displays information for classes, interfaces, and enums identified by + name, ID, or ID range. For a range of IDs, provide the starting ID and + ending ID separated with a hyphen. To provide a list, separate the + items in the list with a space. Use the `/list` command to see the IDs + of the code snippets. + + `-all` + : Displays information for all classes, interfaces, and enums, including + those added when JShell was started, and classes, interfaces, and enums + that failed, were overwritten, or were dropped. + + `-start` + : Displays information for startup classes, interfaces, and enums that + were added when JShell was started. + +`/vars` \[*option*\] +: Displays the name, type, and value of variables that were entered. If no + option is entered, then all current active variables are displayed. + + The following options are valid: + + {*name*\|*id*\|*startID*`-`*endID*} \[{*name*\|*id*\|*startID*`-`*endID*}...\] + : Displays information for variables identified by name, ID, or ID range. + For a range of IDs, provide the starting ID and ending ID separated + with a hyphen. To provide a list, separate the items in the list with a + space. Use the `/list` command to see the IDs of the code snippets. + + `-all` + : Displays information for all variables, including those added when + JShell was started, and variables that failed, were overwritten, or + were dropped. + + `-start` + : Displays information for startup variables that were added when JShell + was started. + +`/?` +: Same as the `/help` command. + +`/!` +: Reruns the last snippet. + +`/`{*name*\|*id*\|*startID*`-`*endID*} \[{*name*\|*id*\|*startID*`-`*endID*}...\] +: Reruns the snippets identified by ID, range of IDs, or name. For a range of + IDs, provide the starting ID and ending ID separated with a hyphen. To + provide a list, separate the items in the list with a space. The first item + in the list must be an ID or ID range. Use the `/list` command to see the + IDs of the code snippets. + +`/-`*n* +: Reruns the -*n*th previous snippet. For example, if 15 code snippets were + entered, then `/-4` runs the 11th snippet. Commands aren't included in the + count. + +## Input Shortcuts + +The following shortcuts are available for entering commands and snippets in +JShell. + +### Tab completion + +**\<tab\>** +: When entering snippets, commands, subcommands, command arguments, or + command options, use the Tab key to automatically complete the item. If the + item can't be determined from what was entered, then possible options are + provided. + + When entering a method call, use the Tab key after the method call's + opening parenthesis to see the parameters for the method. If the method has + more than one signature, then all signatures are displayed. Pressing the + Tab key a second time displays the description of the method and the + parameters for the first signature. Continue pressing the Tab key for a + description of any additional signatures. + +**Shift+\<Tab\> V** +: After entering a complete expression, use this key sequence to convert the + expression to a variable declaration of a type determined by the type of + the expression. + +**Shift+\<Tab\> M** +: After entering a complete expression or statement, use this key sequence to + convert the expression or statement to a method declaration. If an + expression is entered, the return type is based on the type of the + expression. + +**Shift+\<Tab\> I** +: When an identifier is entered that can't be resolved, use this key sequence + to show possible imports that resolve the identifier based on the content + of the specified class path. + +### Command abbreviations + +An abbreviation of a command is accepted if the abbreviation uniquely +identifies a command. For example, `/l` is recognized as the `/list` command. +However, `/s` isn't a valid abbreviation because it can't be determined if the +`/set` or `/save` command is meant. Use `/se` for the `/set` command or `/sa` +for the `/save` command. + +Abbreviations are also accepted for subcommands, command arguments, and command +options. For example, use `/m -a` to display all methods. + +### History navigation + +A history of what was entered is maintained across sessions. Use the up and +down arrows to scroll through commands and snippets from the current and past +sessions. Use the Ctrl key with the up and down arrows to skip all but the +first line of multiline snippets. + +### History search + +Use the Ctrl+R key combination to search the history for the string entered. +The prompt changes to show the string and the match. Ctrl+R searches backwards +from the current location in the history through earlier entries. Ctrl+S +searches forward from the current location in the history though later entries. + +## Input Editing + +The editing capabilities of JShell are similar to that of other common shells. +Keyboard keys and key combinations provide line editing shortcuts. The Ctrl key +and Meta key are used in key combinations. If your keyboard doesn't have a Meta +key, then the Alt key is often mapped to provide Meta key functionality. + +Table: Line Editing Shortcuts + +Key or Key Combination Action +----------------------- ------- +Return Enter the current line. +Left arrow Move the cursor to the left one character. +Right arrow Move the cursor to the right one character. +Ctrl+A Move the cursor to the beginning of the line. +Ctrl+E Move the cursor to the end of the line. +Meta+B Move the cursor to the left one word. +Meta+F Move the cursor to the right one word. +Delete Delete the character under the cursor. +Backspace Delete the character before the cursor. +Ctrl+K Delete the text from the cursor to the end of the line. +Meta+D Delete the text from the cursor to the end of the word. +Ctrl+W Delete the text from the cursor to the previous white space. +Ctrl+Y Paste the most recently deleted text into the line. +Meta+Y After Ctrl+Y, press to cycle through the previously deleted text. +----------------------- ------- + +## Example of Starting and Stopping a JShell Session + +JShell is provided with the JDK. To start a session, enter `jshell` on the +command line. A welcome message is printed, and a prompt for entering commands +and snippets is provided. + +``` +% jshell +| Welcome to JShell -- Version 9 +| For an introduction type: /help intro + +jshell> +``` + +To see which snippets were automatically loaded when JShell started, use the +`/list -start` command. The default startup snippets are import statements for +common packages. The ID for each snippet begins with the letter *s*, which +indicates it's a startup snippet. + +``` +jshell> /list -start + + s1 : import java.io.*; + s2 : import java.math.*; + s3 : import java.net.*; + s4 : import java.nio.file.*; + s5 : import java.util.*; + s6 : import java.util.concurrent.*; + s7 : import java.util.function.*; + s8 : import java.util.prefs.*; + s9 : import java.util.regex.*; + s10 : import java.util.stream.*; + +jshell> +``` + +To end the session, use the `/exit` command. + +``` +jshell> /exit +| Goodbye + +% +``` + +## Example of Entering Snippets + +Snippets are Java statements, variable definitions, method definitions, class +definitions, import statements, and expressions. Terminating semicolons are +automatically added to the end of a completed snippet if they're missing. + +The following example shows two variables and a method being defined, and the +method being run. Note that a scratch variable is automatically created to hold +the result because no variable was provided. + +``` +jshell> int a=4 +a ==> 4 + +jshell> int b=8 +b ==> 8 + +jshell> int square(int i1) { + ...> return i1 * i1; + ...> } +| created method square(int) + +jshell> square(b) +$5 ==> 64 +``` + +## Example of Changing Snippets + +Change the definition of a variable, method, or class by entering it again. + +The following examples shows a method being defined and the method run: + +``` +jshell> String grade(int testScore) { + ...> if (testScore >= 90) { + ...> return "Pass"; + ...> } + ...> return "Fail"; + ...> } +| created method grade(int) + +jshell> grade(88) +$3 ==> "Fail" +``` + +To change the method `grade` to allow more students to pass, enter the method +definition again and change the pass score to `80`. Use the up arrow key to +retrieve the previous entries to avoid having to reenter them and make the +change in the `if` statement. The following example shows the new definition +and reruns the method to show the new result: + +``` +jshell> String grade(int testScore) { + ...> if (testScore >= 80) { + ...> return "Pass"; + ...> } + ...> return "Fail"; + ...> } +| modified method grade(int) + +jshell> grade(88) +$5 ==> "Pass" +``` + +For snippets that are more than a few lines long, or to make more than a few +changes, use the `/edit` command to open the snippet in an editor. After the +changes are complete, close the edit window to return control to the JShell +session. The following example shows the command and the feedback provided when +the edit window is closed. The `/list` command is used to show that the pass +score was changed to `85`. + +``` +jshell> /edit grade +| modified method grade(int) +jshell> /list grade + + 6 : String grade(int testScore) { + if (testScore >= 85) { + return "Pass"; + } + return "Fail"; + } +``` + +## Example of Creating a Custom Feedback Mode + +The feedback mode determines the prompt that's displayed, the feedback messages +that are provided as snippets are entered, and the maximum length of a +displayed value. Predefined feedback modes are provided. Commands for creating +custom feedback modes are also provided. + +Use the `/set mode` command to create a new feedback mode. In the following +example, the new mode `mymode`, is based on the predefined feedback mode, +`normal`, and verifying command feedback is displayed: + +``` +jshell> /set mode mymode normal -command +| Created new feedback mode: mymode +``` + +Because the new mode is based on the `normal` mode, the prompts are the same. +The following example shows how to see what prompts are used and then changes +the prompts to custom strings. The first string represents the standard JShell +prompt. The second string represents the prompt for additional lines in +multiline snippets. + +``` +jshell> /set prompt mymode +| /set prompt mymode "\njshell> " " ...> " + +jshell> /set prompt mymode "\nprompt$ " " continue$ " +``` + +The maximum length of a displayed value is controlled by the truncation +setting. Different types of values can have different lengths. The following +example sets an overall truncation value of 72, and a truncation value of 500 +for variable value expressions: + +``` +jshell> /set truncation mymode 72 + +jshell> /set truncation mymode 500 varvalue +``` + +The feedback displayed after snippets are entered is controlled by the format +setting and is based on the type of snippet entered and the action taken for +that snippet. In the predefined mode `normal`, the string `created` is +displayed when a method is created. The following example shows how to change +that string to `defined`: + +``` +jshell> /set format mymode action "defined" added-primary +``` + +Use the `/set feedback` command to start using the feedback mode that was just +created. The following example shows the custom mode in use: + +``` +jshell> /set feedback mymode +| Feedback mode: mymode + +prompt$ int square (int num1){ + continue$ return num1*num1; + continue$ } +| defined method square(int) + +prompt$ +``` diff --git a/src/jdk.jstatd/share/man/jstatd.1 b/src/jdk.jstatd/share/man/jstatd.1 deleted file mode 100644 index f5d2f347b45..00000000000 --- a/src/jdk.jstatd/share/man/jstatd.1 +++ /dev/null @@ -1,219 +0,0 @@ -.\" Copyright (c) 2004, 2024, 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. -.\" -.\" Automatically generated by Pandoc 2.19.2 -.\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[R]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "JSTATD" "1" "2025" "JDK 24-ea" "JDK Commands" -.hy -.SH NAME -.PP -jstatd - monitor the creation and termination of instrumented Java -HotSpot VMs -.SH SYNOPSIS -.PP -\f[B]WARNING:\f[R] This command is experimental, unsupported, and -deprecated. -It will be removed in a future release. -.PP -\f[V]jstatd\f[R] [\f[I]options\f[R]] -.TP -\f[I]options\f[R] -This represents the \f[V]jstatd\f[R] command-line options. -See \f[B]Options for the jstatd Command\f[R]. -.SH DESCRIPTION -.PP -The \f[V]jstatd\f[R] command is an RMI server application that monitors -for the creation and termination of instrumented Java HotSpot VMs and -provides an interface to enable remote monitoring tools, \f[V]jstat\f[R] -and \f[V]jps\f[R], to attach to JVMs that are running on the local host -and collect information about the JVM process. -.PP -The \f[V]jstatd\f[R] server requires an RMI registry on the local host. -The \f[V]jstatd\f[R] server attempts to attach to the RMI registry on -the default port, or on the port you specify with the \f[V]-p\f[R] -\f[V]port\f[R] option. -If an RMI registry is not found, then one is created within the -\f[V]jstatd\f[R] application that\[aq]s bound to the port that\[aq]s -indicated by the \f[V]-p\f[R] \f[V]port\f[R] option or to the default -RMI registry port when the \f[V]-p\f[R] \f[V]port\f[R] option is -omitted. -You can stop the creation of an internal RMI registry by specifying the -\f[V]-nr\f[R] option. -.SH OPTIONS FOR THE JSTATD COMMAND -.TP -\f[V]-nr\f[R] -This option does not attempt to create an internal RMI registry within -the \f[V]jstatd\f[R] process when an existing RMI registry isn\[aq]t -found. -.TP -\f[V]-p\f[R] \f[I]port\f[R] -This option sets the port number where the RMI registry is expected to -be found, or when not found, created if the \f[V]-nr\f[R] option -isn\[aq]t specified. -.TP -\f[V]-r\f[R] \f[I]rmiport\f[R] -This option sets the port number to which the RMI connector is bound. -If not specified a random available port is used. -.TP -\f[V]-n\f[R] \f[I]rminame\f[R] -This option sets the name to which the remote RMI object is bound in the -RMI registry. -The default name is \f[V]JStatRemoteHost\f[R]. -If multiple \f[V]jstatd\f[R] servers are started on the same host, then -the name of the exported RMI object for each server can be made unique -by specifying this option. -However, doing so requires that the unique server name be included in -the monitoring client\[aq]s \f[V]hostid\f[R] and \f[V]vmid\f[R] strings. -.TP -\f[V]-J\f[R]\f[I]option\f[R] -This option passes a Java \f[V]option\f[R] to the JVM, where the option -is one of those described on the reference page for the Java application -launcher. -For example, \f[V]-J-Xms48m\f[R] sets the startup memory to 48 MB. -See \f[B]java\f[R]. -.SH SECURITY -.PP -The \f[V]jstatd\f[R] server can monitor only JVMs for which it has the -appropriate native access permissions. -Therefore, the \f[V]jstatd\f[R] process must be running with the same -user credentials as the target JVMs. -Some user credentials, such as the root user in Linux and macOS -operating systems, have permission to access the instrumentation -exported by any JVM on the system. -A \f[V]jstatd\f[R] process running with such credentials can monitor any -JVM on the system, but introduces additional security concerns. -.PP -The \f[V]jstatd\f[R] server doesn\[aq]t provide any authentication of -remote clients. -Therefore, running a \f[V]jstatd\f[R] server process exposes the -instrumentation export by all JVMs for which the \f[V]jstatd\f[R] -process has access permissions to any user on the network. -This exposure might be undesirable in your environment, and therefore, -local security policies should be considered before you start the -\f[V]jstatd\f[R] process, particularly in production environments or on -networks that aren\[aq]t secure. -.PP -For security purposes, the \f[V]jstatd\f[R] server uses an RMI -ObjectInputFilter to allow only essential classes to be deserialized. -.PP -If your security concerns can\[aq]t be addressed, then the safest action -is to not run the \f[V]jstatd\f[R] server and use the \f[V]jstat\f[R] -and \f[V]jps\f[R] tools locally. -However, when using \f[V]jps\f[R] to get a list of instrumented JVMs, -the list will not include any JVMs running in docker containers. -.SH REMOTE INTERFACE -.PP -The interface exported by the \f[V]jstatd\f[R] process is proprietary -and guaranteed to change. -Users and developers are discouraged from writing to this interface. -.SH EXAMPLES -.PP -The following are examples of the \f[V]jstatd\f[R] command. -The \f[V]jstatd\f[R] scripts automatically start the server in the -background. -.SH INTERNAL RMI REGISTRY -.PP -This example shows how to start a \f[V]jstatd\f[R] session with an -internal RMI registry. -This example assumes that no other server is bound to the default RMI -registry port (port \f[V]1099\f[R]). -.RS -.PP -\f[V]jstatd\f[R] -.RE -.SH EXTERNAL RMI REGISTRY -.PP -This example starts a \f[V]jstatd\f[R] session with an external RMI -registry. -.IP -.nf -\f[CB] -rmiregistry& -jstatd -\f[R] -.fi -.PP -This example starts a \f[V]jstatd\f[R] session with an external RMI -registry server on port \f[V]2020\f[R]. -.IP -.nf -\f[CB] -jrmiregistry 2020& -jstatd -p 2020 -\f[R] -.fi -.PP -This example starts a \f[V]jstatd\f[R] session with an external RMI -registry server on port \f[V]2020\f[R] and JMX connector bound to port -\f[V]2021\f[R]. -.IP -.nf -\f[CB] -jrmiregistry 2020& -jstatd -p 2020 -r 2021 -\f[R] -.fi -.PP -This example starts a \f[V]jstatd\f[R] session with an external RMI -registry on port 2020 that\[aq]s bound to -\f[V]AlternateJstatdServerName\f[R]. -.IP -.nf -\f[CB] -rmiregistry 2020& -jstatd -p 2020 -n AlternateJstatdServerName -\f[R] -.fi -.SH STOP THE CREATION OF AN IN-PROCESS RMI REGISTRY -.PP -This example starts a \f[V]jstatd\f[R] session that doesn\[aq]t create -an RMI registry when one isn\[aq]t found. -This example assumes an RMI registry is already running. -If an RMI registry isn\[aq]t running, then an error message is -displayed. -.RS -.PP -\f[V]jstatd -nr\f[R] -.RE -.SH ENABLE RMI LOGGING -.PP -This example starts a \f[V]jstatd\f[R] session with RMI logging -capabilities enabled. -This technique is useful as a troubleshooting aid or for monitoring -server activities. -.RS -.PP -\f[V]jstatd -J-Djava.rmi.server.logCalls=true\f[R] -.RE diff --git a/src/jdk.jstatd/share/man/jstatd.md b/src/jdk.jstatd/share/man/jstatd.md new file mode 100644 index 00000000000..d068fddeb01 --- /dev/null +++ b/src/jdk.jstatd/share/man/jstatd.md @@ -0,0 +1,180 @@ +--- +# Copyright (c) 2004, 2024, 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. +# + +title: 'JSTATD(1) JDK @@VERSION_SHORT@@ | JDK Commands' +date: @@COPYRIGHT_YEAR@@ +lang: en +--- + +## Name + +jstatd - monitor the creation and termination of instrumented Java HotSpot VMs + +## Synopsis + +**WARNING:** This command is experimental, unsupported, and deprecated. It will be removed in a future release. + +`jstatd` \[*options*\] + +*options* +: This represents the `jstatd` command-line options. See [Options for the + jstatd Command]. + +## Description + +The `jstatd` command is an RMI server application that monitors for the +creation and termination of instrumented Java HotSpot VMs and provides an +interface to enable remote monitoring tools, `jstat` and `jps`, to attach to +JVMs that are running on the local host and collect information about the JVM +process. + +The `jstatd` server requires an RMI registry on the local host. The `jstatd` +server attempts to attach to the RMI registry on the default port, or on the +port you specify with the `-p` `port` option. If an RMI registry is not found, +then one is created within the `jstatd` application that's bound to the port +that's indicated by the `-p` `port` option or to the default RMI registry port +when the `-p` `port` option is omitted. You can stop the creation of an +internal RMI registry by specifying the `-nr` option. + +## Options for the jstatd Command + +`-nr` +: This option does not attempt to create an internal RMI registry within the + `jstatd` process when an existing RMI registry isn't found. + +`-p` *port* +: This option sets the port number where the RMI registry is expected to be + found, or when not found, created if the `-nr` option isn't specified. + +`-r` *rmiport* +: This option sets the port number to which the RMI connector is bound. If + not specified a random available port is used. + +`-n` *rminame* +: This option sets the name to which the remote RMI object is bound in the + RMI registry. The default name is `JStatRemoteHost`. If multiple `jstatd` + servers are started on the same host, then the name of the exported RMI + object for each server can be made unique by specifying this option. + However, doing so requires that the unique server name be included in the + monitoring client's `hostid` and `vmid` strings. + +`-J`*option* +: This option passes a Java `option` to the JVM, where the option is one of + those described on the reference page for the Java application launcher. + For example, `-J-Xms48m` sets the startup memory to 48 MB. See + [java](java.html). + +## Security + +The `jstatd` server can monitor only JVMs for which it has the appropriate +native access permissions. Therefore, the `jstatd` process must be running with +the same user credentials as the target JVMs. Some user credentials, such as +the root user in Linux and macOS operating systems, have +permission to access the instrumentation exported by any JVM on the system. A +`jstatd` process running with such credentials can monitor any JVM on the +system, but introduces additional security concerns. + +The `jstatd` server doesn't provide any authentication of remote clients. +Therefore, running a `jstatd` server process exposes the instrumentation export +by all JVMs for which the `jstatd` process has access permissions to any user +on the network. This exposure might be undesirable in your environment, and +therefore, local security policies should be considered before you start the +`jstatd` process, particularly in production environments or on networks that +aren't secure. + +For security purposes, the `jstatd` server uses an RMI ObjectInputFilter to allow +only essential classes to be deserialized. + +If your security concerns can't be addressed, +then the safest action is to not run the `jstatd` server and use the `jstat` +and `jps` tools locally. However, when using `jps` to get a list of +instrumented JVMs, the list will not include any JVMs running in docker +containers. + +## Remote Interface + +The interface exported by the `jstatd` process is proprietary and guaranteed to +change. Users and developers are discouraged from writing to this interface. + +## Examples + +The following are examples of the `jstatd` command. The `jstatd` scripts +automatically start the server in the background. + +## Internal RMI Registry + +This example shows how to start a `jstatd` session with an internal RMI +registry. This example assumes that no other server is bound to the default RMI +registry port (port `1099`). + +> `jstatd` + +## External RMI Registry + +This example starts a `jstatd` session with an external RMI registry. + +``` +rmiregistry& +jstatd +``` + +This example starts a `jstatd` session with an external RMI registry server on +port `2020`. + +``` +jrmiregistry 2020& +jstatd -p 2020 +``` + +This example starts a `jstatd` session with an external RMI registry server on +port `2020` and JMX connector bound to port `2021`. + +``` +jrmiregistry 2020& +jstatd -p 2020 -r 2021 +``` + +This example starts a `jstatd` session with an external RMI registry on port +2020 that's bound to `AlternateJstatdServerName`. + +``` +rmiregistry 2020& +jstatd -p 2020 -n AlternateJstatdServerName +``` + +## Stop the Creation of an In-Process RMI Registry + +This example starts a `jstatd` session that doesn't create an RMI registry when +one isn't found. This example assumes an RMI registry is already running. If an +RMI registry isn't running, then an error message is displayed. + +> `jstatd -nr` + +## Enable RMI Logging + +This example starts a `jstatd` session with RMI logging capabilities enabled. +This technique is useful as a troubleshooting aid or for monitoring server +activities. + +> `jstatd + -J-Djava.rmi.server.logCalls=true` diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java index 2e12e67c6c7..2a676e55a90 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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,8 +30,6 @@ import java.net.InetSocketAddress; import java.io.FileDescriptor; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collections; import java.util.Set; import java.util.HashSet; @@ -194,11 +192,6 @@ public SctpChannel bind(SocketAddress local) throws IOException { SctpNet.throwAlreadyBoundException(); InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : Net.checkAddress(local); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkListen(isa.getPort()); - } Net.bind(fd, isa.getAddress(), isa.getPort()); InetSocketAddress boundIsa = Net.localAddress(fd); port = boundIsa.getPort(); @@ -364,11 +357,6 @@ public boolean connect(SocketAddress endpoint) throws IOException { synchronized (sendLock) { ensureOpenAndUnconnected(); InetSocketAddress isa = Net.checkAddress(endpoint); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkConnect(isa.getAddress().getHostAddress(), - isa.getPort()); synchronized (blockingLock()) { int n = 0; try { @@ -1094,16 +1082,10 @@ static native int send0(int fd, long address, int length, loadSctpLibrary(); } - @SuppressWarnings({"removal", "restricted"}) + @SuppressWarnings("restricted") private static void loadSctpLibrary() { IOUtil.load(); /* loads nio & net native libraries */ - AccessController.doPrivileged( - new PrivilegedAction<>() { - public Void run() { - System.loadLibrary("sctp"); - return null; - } - }); + System.loadLibrary("sctp"); initIDs(); } } diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index b1b721c9976..4a3f18e6b08 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -149,10 +149,6 @@ public SctpMultiChannel bind(SocketAddress local, int backlog) InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : Net.checkAddress(local); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkListen(isa.getPort()); Net.bind(fd, isa.getAddress(), isa.getPort()); InetSocketAddress boundIsa = Net.localAddress(fd); @@ -508,21 +504,6 @@ public <T> MessageInfo receive(ByteBuffer buffer, resultContainer.getMessageInfo(); info.setAssociation(lookupAssociation(info. associationID())); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - InetSocketAddress isa = (InetSocketAddress)info.address(); - if (!addressMap.containsKey(isa)) { - /* must be a new association */ - try { - sm.checkAccept(isa.getAddress().getHostAddress(), - isa.getPort()); - } catch (SecurityException se) { - buffer.clear(); - throw se; - } - } - } assert info.association() != null; return info; @@ -805,12 +786,6 @@ public int send(ByteBuffer buffer, MessageInfo messageInfo) checkStreamNumber(association, messageInfo.streamNumber()); assocId = association.associationID(); - } else { /* must be new association */ - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkConnect(addr.getAddress().getHostAddress(), - addr.getPort()); } } else { throw new AssertionError( diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java index decf964c6cb..a12049cbcf0 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ import java.nio.channels.AlreadyBoundException; import java.util.Set; import java.util.HashSet; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.net.util.IPAddressUtil; import sun.nio.ch.IOUtil; import sun.nio.ch.Net; @@ -91,41 +89,14 @@ static Set<SocketAddress> getLocalAddresses(int fd) SocketAddress[] saa = getLocalAddresses0(fd); if (saa != null) { - set = getRevealedLocalAddressSet(saa); + set = new HashSet<>(saa.length); + for (SocketAddress sa : saa) + set.add(sa); } return set; } - private static Set<SocketAddress> getRevealedLocalAddressSet( - SocketAddress[] saa) - { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - Set<SocketAddress> set = new HashSet<>(saa.length); - for (SocketAddress sa : saa) { - set.add(getRevealedLocalAddress(sa, sm)); - } - return set; - } - - private static SocketAddress getRevealedLocalAddress(SocketAddress sa, - @SuppressWarnings("removal") SecurityManager sm) - { - if (sm == null || sa == null) - return sa; - InetSocketAddress ia = (InetSocketAddress)sa; - try{ - sm.checkConnect(ia.getAddress().getHostAddress(), -1); - // Security check passed - } catch (SecurityException e) { - // Return loopback address - return new InetSocketAddress(InetAddress.getLoopbackAddress(), - ia.getPort()); - } - return sa; - } - static Set<SocketAddress> getRemoteAddresses(int fd, int assocId) throws IOException { Set<SocketAddress> set = null; @@ -336,13 +307,7 @@ static native void setInitMsgOption0(int fd, int arg1, int arg2) @SuppressWarnings({"removal", "restricted"}) private static void loadSctpLibrary() { IOUtil.load(); // loads nio & net native libraries - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Void>() { - public Void run() { - System.loadLibrary("sctp"); - return null; - } - }); + System.loadLibrary("sctp"); init(); } } diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java index 0f710a4c670..4b2be742c6d 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -109,10 +109,6 @@ public SctpServerChannel bind(SocketAddress local, int backlog) InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : Net.checkAddress(local); - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkListen(isa.getPort()); Net.bind(fd, isa.getAddress(), isa.getPort()); InetSocketAddress boundIsa = Net.localAddress(fd); @@ -217,7 +213,6 @@ public SctpChannel accept() throws IOException { throw new ClosedChannelException(); if (!isBound()) throw new NotYetBoundException(); - SctpChannel sc = null; int n = 0; FileDescriptor newfd = new FileDescriptor(); @@ -244,16 +239,7 @@ public SctpChannel accept() throws IOException { return null; IOUtil.configureBlocking(newfd, true); - InetSocketAddress isa = isaa[0]; - sc = new SctpChannelImpl(provider(), newfd); - - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkAccept(isa.getAddress().getHostAddress(), - isa.getPort()); - - return sc; + return new SctpChannelImpl(provider(), newfd); } } diff --git a/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java b/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java index f6f9b3976fc..e671e1db526 100644 --- a/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java +++ b/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,64 +25,39 @@ package sun.reflect; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; import java.io.OptionalDataException; import java.lang.invoke.MethodHandle; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedAction; /** * ReflectionFactory supports custom serialization. * Its methods support the creation of uninitialized objects, invoking serialization * private methods for readObject, writeObject, readResolve, and writeReplace. - * <p> - * ReflectionFactory access is restricted, if a security manager is active, - * unless the permission {@code RuntimePermission("reflectionFactoryAccess")} - * is granted. */ public class ReflectionFactory { private static final ReflectionFactory soleInstance = new ReflectionFactory(); - @SuppressWarnings("removal") - private static final jdk.internal.reflect.ReflectionFactory delegate = AccessController.doPrivileged( - new PrivilegedAction<jdk.internal.reflect.ReflectionFactory>() { - public jdk.internal.reflect.ReflectionFactory run() { - return jdk.internal.reflect.ReflectionFactory.getReflectionFactory(); - } - }); + private static final jdk.internal.reflect.ReflectionFactory delegate = + jdk.internal.reflect.ReflectionFactory.getReflectionFactory(); private ReflectionFactory() {} - private static final Permission REFLECTION_FACTORY_ACCESS_PERM - = new RuntimePermission("reflectionFactoryAccess"); - /** * Provides the caller with the capability to instantiate reflective * objects. * - * <p> First, if there is a security manager, its {@code checkPermission} - * method is called with a {@link java.lang.RuntimePermission} with target - * {@code "reflectionFactoryAccess"}. This may result in a security - * exception. - * * <p> The returned {@code ReflectionFactory} object should be carefully * guarded by the caller, since it can be used to read and write private * data and invoke private methods, as well as to load unverified bytecodes. * It must never be passed to untrusted code. * * @return the ReflectionFactory - * @throws SecurityException if a security manager exists and its - * {@code checkPermission} method doesn't allow access to - * the RuntimePermission "reflectionFactoryAccess". */ public static ReflectionFactory getReflectionFactory() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(REFLECTION_FACTORY_ACCESS_PERM); - } return soleInstance; } @@ -157,6 +132,50 @@ public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) { return delegate.readObjectNoDataForSerialization(cl); } + /** + * Generate and return a direct MethodHandle which implements + * the general default behavior for serializable class's {@code readObject}. + * The generated method behaves in accordance with the + * Java Serialization specification's rules for that method. + * <p> + * The generated method will invoke {@link ObjectInputStream#readFields()} + * to acquire the stream field values. The serialization fields of the class will + * then be populated from the stream values. + * <p> + * Only fields which are eligible for default serialization will be populated. + * This includes only fields which are not {@code transient} and not {@code static} + * (even if the field is {@code final} or {@code private}). + * <p> + * Requesting a default serialization method for a class in a disallowed + * category is not supported; {@code null} will be returned for such classes. + * The disallowed categories include (but are not limited to): + * <ul> + * <li>Classes which do not implement {@code Serializable}</li> + * <li>Classes which implement {@code Externalizable}</li> + * <li>Classes which are specially handled by the Java Serialization specification, + * including record classes, enum constant classes, {@code Class}, {@code String}, + * array classes, reflection proxy classes, and hidden classes</li> + * <li>Classes which declare a valid {@code serialPersistentFields} value</li> + * <li>Any special types which may possibly be added to the JDK or the Java language + * in the future which in turn might require special handling by the + * provisions of the corresponding future version of the Java Serialization + * specification</li> + * </ul> + * <p> + * The generated method will accept the instance as its first argument + * and the {@code ObjectInputStream} as its second argument. + * The return type of the method is {@code void}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the synthetic {@code readObject} method + * or {@code null} if the class falls in a disallowed category + * + * @since 24 + */ + public final MethodHandle defaultReadObjectForSerialization(Class<?> cl) { + return delegate.defaultReadObjectForSerialization(cl); + } + /** * Returns a direct MethodHandle for the {@code writeObject} method on * a Serializable class. @@ -172,6 +191,53 @@ public final MethodHandle writeObjectForSerialization(Class<?> cl) { return delegate.writeObjectForSerialization(cl); } + /** + * Generate and return a direct MethodHandle which implements + * the general default behavior for serializable class's {@code writeObject}. + * The generated method behaves in accordance with the + * Java Serialization specification's rules for that method. + * <p> + * The generated method will invoke {@link ObjectOutputStream#putFields} + * to acquire the buffer for the stream field values. The buffer will + * be populated from the serialization fields of the class. The buffer + * will then be flushed to the stream using the + * {@link ObjectOutputStream#writeFields()} method. + * <p> + * Only fields which are eligible for default serialization will be written + * to the buffer. + * This includes only fields which are not {@code transient} and not {@code static} + * (even if the field is {@code final} or {@code private}). + * <p> + * Requesting a default serialization method for a class in a disallowed + * category is not supported; {@code null} will be returned for such classes. + * The disallowed categories include (but are not limited to): + * <ul> + * <li>Classes which do not implement {@code Serializable}</li> + * <li>Classes which implement {@code Externalizable}</li> + * <li>Classes which are specially handled by the Java Serialization specification, + * including record classes, enum constant classes, {@code Class}, {@code String}, + * array classes, reflection proxy classes, and hidden classes</li> + * <li>Classes which declare a valid {@code serialPersistentFields} value</li> + * <li>Any special types which may possibly be added to the JDK or the Java language + * in the future which in turn might require special handling by the + * provisions of the corresponding future version of the Java Serialization + * specification</li> + * </ul> + * <p> + * The generated method will accept the instance as its first argument + * and the {@code ObjectOutputStream} as its second argument. + * The return type of the method is {@code void}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the synthetic {@code writeObject} method + * or {@code null} if the class falls in a disallowed category + * + * @since 24 + */ + public final MethodHandle defaultWriteObjectForSerialization(Class<?> cl) { + return delegate.defaultWriteObjectForSerialization(cl); + } + /** * Returns a direct MethodHandle for the {@code readResolve} method on * a serializable class. @@ -225,4 +291,21 @@ public final OptionalDataException newOptionalDataExceptionForSerialization(bool throw new InternalError("unable to create OptionalDataException", ex); } } + + /** + * {@return the declared {@code serialPersistentFields} from a + * serializable class, or {@code null} if none is declared, the field + * is declared but not valid, or the class is not a valid serializable class} + * A class is a valid serializable class if it implements {@code Serializable} + * but not {@code Externalizable}. The {@code serialPersistentFields} field + * is valid if it meets the type and accessibility restrictions defined + * by the Java Serialization specification. + * + * @param cl a Serializable class + * + * @since 24 + */ + public final ObjectStreamField[] serialPersistentFields(Class<?> cl) { + return delegate.serialPersistentFields(cl); + } } diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index 20ed86eae4f..9ea935551b8 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -44,10 +44,6 @@ import java.nio.file.*; import java.nio.file.attribute.*; import java.nio.file.spi.FileSystemProvider; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.*; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -82,10 +78,8 @@ */ class ZipFileSystem extends FileSystem { // statics - @SuppressWarnings("removal") - private static final boolean isWindows = AccessController.doPrivileged( - (PrivilegedAction<Boolean>)()->System.getProperty("os.name") - .startsWith("Windows")); + private static final boolean isWindows = System.getProperty("os.name") + .startsWith("Windows"); private static final byte[] ROOTPATH = new byte[] { '/' }; private static final String PROPERTY_POSIX = "enablePosixFileAttributes"; private static final String PROPERTY_DEFAULT_OWNER = "defaultOwner"; @@ -168,9 +162,7 @@ class ZipFileSystem extends FileSystem { } // sm and existence check zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ); - @SuppressWarnings("removal") - boolean writeable = AccessController.doPrivileged( - (PrivilegedAction<Boolean>)()->Files.isWritable(zfpath)); + boolean writeable = Files.isWritable(zfpath); this.readOnly = !writeable; this.zc = ZipCoder.get(nameEncoding); this.rootdir = new ZipPath(this, new byte[]{'/'}); @@ -244,23 +236,14 @@ private static boolean isTrue(Map<String, ?> env, String name) { // If not specified in env, it is the owner of the archive. If no owner can // be determined, we try to go with system property "user.name". If that's not // accessible, we return "<zipfs_default>". - @SuppressWarnings("removal") private UserPrincipal initOwner(Path zfpath, Map<String, ?> env) throws IOException { Object o = env.get(PROPERTY_DEFAULT_OWNER); if (o == null) { try { - PrivilegedExceptionAction<UserPrincipal> pa = ()->Files.getOwner(zfpath); - return AccessController.doPrivileged(pa); - } catch (UnsupportedOperationException | PrivilegedActionException e) { - if (e instanceof UnsupportedOperationException || - e.getCause() instanceof NoSuchFileException) - { - PrivilegedAction<String> pa = ()->System.getProperty("user.name"); - String userName = AccessController.doPrivileged(pa); - return ()->userName; - } else { - throw new IOException(e); - } + return Files.getOwner(zfpath); + } catch (UnsupportedOperationException | NoSuchFileException e) { + String userName = System.getProperty("user.name"); + return ()->userName; } } if (o instanceof String) { @@ -282,7 +265,6 @@ private UserPrincipal initOwner(Path zfpath, Map<String, ?> env) throws IOExcept // If not specified in env, we try to determine the group of the zip archive itself. // If this is not possible/unsupported, we will return a group principal going by // the same name as the default owner. - @SuppressWarnings("removal") private GroupPrincipal initGroup(Path zfpath, Map<String, ?> env) throws IOException { Object o = env.get(PROPERTY_DEFAULT_GROUP); if (o == null) { @@ -291,16 +273,9 @@ private GroupPrincipal initGroup(Path zfpath, Map<String, ?> env) throws IOExcep if (zfpv == null) { return defaultOwner::getName; } - PrivilegedExceptionAction<GroupPrincipal> pa = ()->zfpv.readAttributes().group(); - return AccessController.doPrivileged(pa); - } catch (UnsupportedOperationException | PrivilegedActionException e) { - if (e instanceof UnsupportedOperationException || - e.getCause() instanceof NoSuchFileException) - { - return defaultOwner::getName; - } else { - throw new IOException(e); - } + return zfpv.readAttributes().group(); + } catch (UnsupportedOperationException | NoSuchFileException e) { + return defaultOwner::getName; } } if (o instanceof String) { @@ -462,7 +437,6 @@ public PathMatcher getPathMatcher(String syntaxAndInput) { return (path)->pattern.matcher(path.toString()).matches(); } - @SuppressWarnings("removal") @Override public void close() throws IOException { beginWrite(); @@ -480,13 +454,9 @@ public void close() throws IOException { } beginWrite(); // lock and sync try { - AccessController.doPrivileged((PrivilegedExceptionAction<Void>)() -> { - sync(); return null; - }); + sync(); ch.close(); // close the ch just in case no update // and sync didn't close the ch - } catch (PrivilegedActionException e) { - throw (IOException)e.getException(); } finally { endWrite(); } @@ -512,10 +482,8 @@ public void close() throws IOException { synchronized (tmppaths) { for (Path p : tmppaths) { try { - AccessController.doPrivileged( - (PrivilegedExceptionAction<Boolean>)() -> Files.deleteIfExists(p)); - } catch (PrivilegedActionException e) { - IOException x = (IOException)e.getException(); + Files.deleteIfExists(p); + } catch (IOException x) { if (ioe == null) ioe = x; else diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java index 615d2a42e20..a8336b0f8f6 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -39,9 +39,6 @@ import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileAttributeView; import java.nio.file.spi.FileSystemProvider; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -317,17 +314,9 @@ public void setAttribute(Path path, String attribute, } ////////////////////////////////////////////////////////////// - @SuppressWarnings("removal") void removeFileSystem(Path zfpath, ZipFileSystem zfs) throws IOException { synchronized (filesystems) { - Path tempPath = zfpath; - PrivilegedExceptionAction<Path> action = tempPath::toRealPath; - try { - zfpath = AccessController.doPrivileged(action); - } catch (PrivilegedActionException e) { - throw (IOException) e.getException(); - } - filesystems.remove(zfpath, zfs); + filesystems.remove(zfpath.toRealPath(), zfs); } } } diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalCFGLayoutManager.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalCFGLayoutManager.java index c712c2f935e..3d4e8f87b27 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalCFGLayoutManager.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalCFGLayoutManager.java @@ -45,6 +45,12 @@ public HierarchicalCFGLayoutManager() { fontMetrics = canvas.getFontMetrics(font); } + @Override + public void setCutEdges(boolean enable) { + subManager.setCutEdges(enable); + manager.setCutEdges(enable); + } + public void setSubManager(LayoutManager manager) { this.subManager = manager; } diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java index badfb0e036a..1d103585e58 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java @@ -43,6 +43,12 @@ public HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine combin this.combine = combine; } + @Override + public void setCutEdges(boolean enable) { + subManager.setCutEdges(enable); + manager.setCutEdges(enable); + } + public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks) { doLayout(graph); } diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java index 0c9e5ccd480..996fd895577 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java @@ -136,8 +136,9 @@ public void setLayerOffset(int layerOffset) { this.layerOffset = layerOffset; } - public void setMaxLayerLength(int v) { - maxLayerLength = v; + @Override + public void setCutEdges(boolean enable) { + maxLayerLength = enable ? 10 : -1; } public void setMinLayerDifference(int v) { diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalStableLayoutManager.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalStableLayoutManager.java index 875ccb19022..2d76d15394c 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalStableLayoutManager.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalStableLayoutManager.java @@ -38,8 +38,8 @@ public class HierarchicalStableLayoutManager { public static final int X_OFFSET = 8; public static final int LAYER_OFFSET = 8; // Algorithm global data structures - private HashSet<? extends Vertex> currentVertices; - private HashSet<? extends Link> currentLinks; + private Set<? extends Vertex> currentVertices; + private Set<? extends Link> currentLinks; private Set<Link> reversedLinks; private List<LayoutNode> nodes; private final HashMap<Vertex, LayoutNode> vertexToLayoutNode; @@ -51,10 +51,19 @@ public class HierarchicalStableLayoutManager { private HashMap<Vertex, VertexAction> vertexToAction; private List<VertexAction> vertexActions; private List<LinkAction> linkActions; - private HashSet<? extends Vertex> oldVertices; - private HashSet<? extends Link> oldLinks; + private Set<? extends Vertex> oldVertices; + private Set<? extends Link> oldLinks; private boolean shouldRedrawLayout = true; private boolean shouldRemoveEmptyLayers = true; + private boolean cutEdges = false; + + public void doLayout(LayoutGraph layoutGraph) { + boolean oldShouldRedrawLayout = shouldRedrawLayout; + setShouldRedrawLayout(true); + updateLayout(layoutGraph.getVertices(), layoutGraph.getLinks()); + setShouldRedrawLayout(oldShouldRedrawLayout); + } + enum Action { ADD, @@ -90,6 +99,15 @@ public HierarchicalStableLayoutManager() { nodes = new ArrayList<>(); } + public void setCutEdges(boolean enable) { + cutEdges = enable; + manager.setCutEdges(enable); + } + + public boolean getCutEdges() { + return cutEdges; + } + private int calculateOptimalBoth(LayoutNode n) { if (n.preds.isEmpty() && n.succs.isEmpty()) { return n.x; @@ -396,7 +414,7 @@ public void setShouldRedrawLayout(boolean shouldRedrawLayout) { this.shouldRedrawLayout = shouldRedrawLayout; } - public void updateLayout(HashSet<? extends Vertex> vertices, HashSet<? extends Link> links) { + public void updateLayout(Set<? extends Vertex> vertices, Set<? extends Link> links) { currentVertices = vertices; currentLinks = links; reversedLinks = new HashSet<>(); diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LinearLayoutManager.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LinearLayoutManager.java index 32f56e69bf9..69d53ebc9fa 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LinearLayoutManager.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LinearLayoutManager.java @@ -39,6 +39,9 @@ public LinearLayoutManager(Map<? extends Vertex, Integer> vertexRank) { this.vertexRank = vertexRank; } + @Override + public void setCutEdges(boolean enable) {} + @Override public void doLayout(LayoutGraph graph) { doLayout(graph, new HashSet<>()); diff --git a/src/utils/IdealGraphVisualizer/Layout/src/main/java/com/sun/hotspot/igv/layout/LayoutManager.java b/src/utils/IdealGraphVisualizer/Layout/src/main/java/com/sun/hotspot/igv/layout/LayoutManager.java index 86a0d02e16b..a74ef280ebe 100644 --- a/src/utils/IdealGraphVisualizer/Layout/src/main/java/com/sun/hotspot/igv/layout/LayoutManager.java +++ b/src/utils/IdealGraphVisualizer/Layout/src/main/java/com/sun/hotspot/igv/layout/LayoutManager.java @@ -31,6 +31,8 @@ */ public interface LayoutManager { + void setCutEdges(boolean enable); + void doLayout(LayoutGraph graph); void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks); diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java index f9c2e991d46..3f7fec74505 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java @@ -700,12 +700,19 @@ private boolean isVisible(Connection c) { } private void doStableSeaLayout(HashSet<Figure> visibleFigures, HashSet<Connection> visibleConnections) { - hierarchicalStableLayoutManager.updateLayout(visibleFigures, visibleConnections); + boolean enable = model.getCutEdges(); + boolean previous = hierarchicalStableLayoutManager.getCutEdges(); + hierarchicalStableLayoutManager.setCutEdges(enable); + if (enable != previous) { + hierarchicalStableLayoutManager.doLayout(new LayoutGraph(visibleConnections, visibleFigures)); + } else { + hierarchicalStableLayoutManager.updateLayout(visibleFigures, visibleConnections); + } } private void doSeaLayout(HashSet<Figure> figures, HashSet<Connection> edges) { HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS); - manager.setMaxLayerLength(10); + manager.setCutEdges(model.getCutEdges()); manager.doLayout(new LayoutGraph(edges, figures)); hierarchicalStableLayoutManager.setShouldRedrawLayout(true); } @@ -713,7 +720,7 @@ private void doSeaLayout(HashSet<Figure> figures, HashSet<Connection> edges) { private void doClusteredLayout(HashSet<Connection> edges) { HierarchicalClusterLayoutManager m = new HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS); HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS); - manager.setMaxLayerLength(9); + manager.setCutEdges(model.getCutEdges()); manager.setMinLayerDifference(3); m.setManager(manager); m.setSubManager(new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS)); @@ -724,7 +731,7 @@ private void doCFGLayout(HashSet<Figure> figures, HashSet<Connection> edges) { Diagram diagram = getModel().getDiagram(); HierarchicalCFGLayoutManager m = new HierarchicalCFGLayoutManager(); HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS); - manager.setMaxLayerLength(9); + manager.setCutEdges(model.getCutEdges()); manager.setMinLayerDifference(1); manager.setLayoutSelfEdges(true); manager.setXOffset(25); diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java index 6d7599e6d34..3081825025f 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java @@ -36,6 +36,7 @@ import com.sun.hotspot.igv.graph.MatcherSelector; import com.sun.hotspot.igv.settings.Settings; import com.sun.hotspot.igv.util.RangeSliderModel; +import com.sun.hotspot.igv.view.actions.CutEdgesAction; import com.sun.hotspot.igv.view.actions.GlobalSelectionAction; import java.awt.Color; import java.util.*; @@ -68,8 +69,8 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene private boolean showCFG; private boolean showNodeHull; private boolean showEmptyBlocks; - private boolean hideDuplicates; private static boolean globalSelection = false; + private static boolean cutEdges = false; private final ChangedListener<FilterChain> filterChainChangedListener = changedFilterChain -> { assert filterChain == changedFilterChain; @@ -80,6 +81,18 @@ public Group getGroup() { return group; } + public boolean getCutEdges() { + return cutEdges; + } + + public void setCutEdges(boolean enable, boolean fire) { + boolean prevEnable = cutEdges; + cutEdges = enable; + if (fire && prevEnable != enable) { + diagramChangedEvent.fire(); + } + } + public boolean getGlobalSelection() { return globalSelection; } @@ -154,25 +167,6 @@ public void setShowEmptyBlocks(boolean b) { diagramChangedEvent.fire(); } - public void setHideDuplicates(boolean hideDuplicates) { - this.hideDuplicates = hideDuplicates; - InputGraph currentGraph = getFirstGraph(); - if (hideDuplicates) { - // Back up to the unhidden equivalent graph - int index = graphs.indexOf(currentGraph); - while (graphs.get(index).getProperties().get("_isDuplicate") != null) { - index--; - } - currentGraph = graphs.get(index); - } - filterGraphs(); - selectGraph(currentGraph); - } - - public boolean getHideDuplicates() { - return hideDuplicates; - } - private void initGroup() { group.getChangedEvent().addListener(g -> { assert g == group; @@ -191,6 +185,7 @@ private void initGroup() { public DiagramViewModel(DiagramViewModel model) { super(model); globalSelection = false; + cutEdges = false; group = model.getGroup(); initGroup(); graphs = new ArrayList<>(model.graphs); @@ -205,12 +200,12 @@ public DiagramViewModel(DiagramViewModel model) { filtersOrder = provider.getAllFiltersOrdered(); globalSelection = GlobalSelectionAction.get(GlobalSelectionAction.class).isSelected(); + cutEdges = CutEdgesAction.get(CutEdgesAction.class).isSelected(); showCFG = model.getShowCFG(); showSea = model.getShowSea(); showBlocks = model.getShowBlocks(); showNodeHull = model.getShowNodeHull(); showEmptyBlocks = model.getShowEmptyBlocks(); - hideDuplicates = model.getHideDuplicates(); hiddenNodes = new HashSet<>(model.getHiddenNodes()); selectedNodes = new HashSet<>(); @@ -228,13 +223,13 @@ public DiagramViewModel(InputGraph graph) { filtersOrder = provider.getAllFiltersOrdered(); globalSelection = GlobalSelectionAction.get(GlobalSelectionAction.class).isSelected(); + cutEdges = CutEdgesAction.get(CutEdgesAction.class).isSelected(); showStableSea = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.STABLE_SEA_OF_NODES; showSea = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.SEA_OF_NODES; showBlocks = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CLUSTERED_SEA_OF_NODES; showCFG = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CONTROL_FLOW_GRAPH; showNodeHull = true; showEmptyBlocks = true; - hideDuplicates = false; hiddenNodes = new HashSet<>(); selectedNodes = new HashSet<>(); @@ -422,11 +417,8 @@ private void filterGraphs() { ArrayList<InputGraph> result = new ArrayList<>(); List<String> positions = new ArrayList<>(); for (InputGraph graph : group.getGraphs()) { - String duplicate = graph.getProperties().get("_isDuplicate"); - if (duplicate == null || !hideDuplicates) { - result.add(graph); - positions.add(graph.getName()); - } + result.add(graph); + positions.add(graph.getName()); } this.graphs = result; setPositions(positions); @@ -460,22 +452,12 @@ public InputGraph getSecondGraph() { public void selectGraph(InputGraph graph) { int index = graphs.indexOf(graph); - if (index == -1 && hideDuplicates) { - // A graph was selected that's currently hidden, so unhide and select it. - setHideDuplicates(false); - index = graphs.indexOf(graph); - } assert index != -1; setPositions(index, index); } public void selectDiffGraph(InputGraph graph) { int index = graphs.indexOf(graph); - if (index == -1 && hideDuplicates) { - // A graph was selected that's currently hidden, so unhide and select it. - setHideDuplicates(false); - index = graphs.indexOf(graph); - } assert index != -1; int firstIndex = getFirstPosition(); int secondIndex = getSecondPosition(); diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java index e24ffa476a2..d69047c8c3e 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java @@ -210,7 +210,6 @@ public void mouseMoved(MouseEvent e) {} toolBar.addSeparator(); toolBar.add(new JToggleButton(new PredSuccAction(diagramViewModel.getShowNodeHull()))); toolBar.add(new JToggleButton(new ShowEmptyBlocksAction(cfgLayoutAction, diagramViewModel.getShowEmptyBlocks()))); - toolBar.add(new JToggleButton(new HideDuplicatesAction(diagramViewModel.getHideDuplicates()))); toolBar.addSeparator(); UndoAction undoAction = UndoAction.get(UndoAction.class); @@ -221,6 +220,11 @@ public void mouseMoved(MouseEvent e) {} toolBar.add(redoAction); toolBar.addSeparator(); + + JToggleButton cutEdgesButton = new JToggleButton(CutEdgesAction.get(CutEdgesAction.class)); + cutEdgesButton.setHideActionText(true); + toolBar.add(cutEdgesButton); + JToggleButton globalSelectionButton = new JToggleButton(GlobalSelectionAction.get(GlobalSelectionAction.class)); globalSelectionButton.setHideActionText(true); toolBar.add(globalSelectionButton); @@ -453,6 +457,7 @@ public TopComponent cloneComponent() { } etc.addSelectedNodes(selectedNodes, false); model.setGlobalSelection(GlobalSelectionAction.get(GlobalSelectionAction.class).isSelected(), false); + model.setCutEdges(CutEdgesAction.get(CutEdgesAction.class).isSelected(), false); etc.resetUndoRedo(); int currentZoomLevel = scene.getZoomPercentage(); diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/CutEdgesAction.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/CutEdgesAction.java new file mode 100644 index 00000000000..4467031bab9 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/CutEdgesAction.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024, 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 com.sun.hotspot.igv.view.actions; + +import com.sun.hotspot.igv.view.EditorTopComponent; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.SwingUtilities; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; +import org.openide.util.HelpCtx; +import org.openide.util.ImageUtilities; +import org.openide.util.NbBundle; +import org.openide.util.actions.CallableSystemAction; + +@ActionID(category = "View", id = "com.sun.hotspot.igv.view.actions.CutEdgesAction") +@ActionRegistration(displayName = "#CTL_CutEdgesAction") +@ActionReferences({ + @ActionReference(path = "Menu/Options", position = 350), +}) +@NbBundle.Messages({ + "CTL_CutEdgesAction=Cut long edges", + "HINT_CutEdgesAction=Cut long edges" +}) +public final class CutEdgesAction extends CallableSystemAction { + + private boolean isSelected; + + public CutEdgesAction() { + putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource()))); + putValue(Action.SHORT_DESCRIPTION, getDescription()); + putValue(SELECTED_KEY, false); + isSelected = false; + } + + @Override + public String getName() { + return NbBundle.getMessage(CutEdgesAction.class, "CTL_CutEdgesAction"); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public void performAction() { + isSelected = !isSelected; + putValue(SELECTED_KEY, isSelected); + EditorTopComponent editor = EditorTopComponent.getActive(); + if (editor != null) { + SwingUtilities.invokeLater(() -> editor.getModel().setCutEdges(isSelected, true)); + } + } + + public boolean isSelected() { + return isSelected; + } + + private String getDescription() { + return NbBundle.getMessage(CutEdgesAction.class, "HINT_CutEdgesAction"); + } + + @Override + protected boolean asynchronous() { + return false; + } + + @Override + public String iconResource() { + return "com/sun/hotspot/igv/view/images/cut.png"; + } +} diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/HideDuplicatesAction.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/HideDuplicatesAction.java deleted file mode 100644 index 34dd615b459..00000000000 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/HideDuplicatesAction.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, 2023, 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 com.sun.hotspot.igv.view.actions; - -import com.sun.hotspot.igv.view.EditorTopComponent; -import java.awt.event.ActionEvent; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import org.openide.util.ImageUtilities; - -/** - * - * @author Tom Rodriguez - */ -public class HideDuplicatesAction extends AbstractAction { - - public HideDuplicatesAction(boolean selected) { - putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource()))); - putValue(Action.SELECTED_KEY, selected); - putValue(Action.SHORT_DESCRIPTION, "Hide graphs which are the same as the previous graph"); - } - - @Override - public void actionPerformed(ActionEvent ev) { - EditorTopComponent editor = EditorTopComponent.getActive(); - if (editor != null) { - boolean selected = (boolean)getValue(SELECTED_KEY); - editor.getModel().setHideDuplicates(selected); - } - } - - protected String iconResource() { - return "com/sun/hotspot/igv/view/images/hideDuplicates.png"; - } -} diff --git a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/cut.png b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/cut.png new file mode 100644 index 00000000000..67030403bb0 Binary files /dev/null and b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/cut.png differ diff --git a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/hideDuplicates.png b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/hideDuplicates.png deleted file mode 100644 index 907b900c2f3..00000000000 Binary files a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/hideDuplicates.png and /dev/null differ diff --git a/test/hotspot/gtest/classfile/test_stringConversion.cpp b/test/hotspot/gtest/classfile/test_stringConversion.cpp new file mode 100644 index 00000000000..13553464229 --- /dev/null +++ b/test/hotspot/gtest/classfile/test_stringConversion.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2024, 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 "runtime/interfaceSupport.inline.hpp" +#include "unittest.hpp" + +// Tests that string functions (hash code/equals) stay consistant when comparing equal strings and converting between strings types + +// Simple ASCII string "Java(R)!!" +// Same length in both UTF8 and Unicode +static const char static_ascii_utf8_str[] = {0x4A, 0x61, 0x76, 0x61, 0x28, 0x52, 0x29, 0x21, 0x21}; +static const jchar static_ascii_unicode_str[] = {0x004A, 0x0061, 0x0076, 0x0061, 0x0028, 0x0052, 0x0029, 0x0021, 0x0021}; + +// Complex string "Jāvá®!☺☻", UTF8 has character lengths 13122133 = 16 +static const unsigned char static_utf8_str[] = {0x4A, 0x61, 0xCC, 0x84, 0x76, 0xC3, 0xA1, 0xC2, 0xAE, 0x21, 0xE2, 0x98, 0xBA, 0xE2, 0x98, 0xBB}; +static const jchar static_unicode_str[] = { 0x004A, 0x0061, 0x0304, 0x0076, 0x00E1, 0x00AE, 0x0021, 0x263A, 0x263B}; + +static const int ASCII_LENGTH = 9; +static const size_t UTF8_LENGTH = 16; +static const int UNICODE_LENGTH = 9; + +void compare_utf8_utf8(const char* utf8_str1, const char* utf8_str2, size_t utf8_len) { + EXPECT_EQ(java_lang_String::hash_code(utf8_str1, utf8_len), java_lang_String::hash_code(utf8_str2, utf8_len)); + EXPECT_STREQ(utf8_str1, utf8_str2); +} + +void compare_utf8_unicode(const char* utf8_str, const jchar* unicode_str, size_t utf8_len, int unicode_len) { + EXPECT_EQ(java_lang_String::hash_code(utf8_str, utf8_len), java_lang_String::hash_code(unicode_str, unicode_len)); +} + +void compare_utf8_oop(const char* utf8_str, Handle oop_str, size_t utf8_len, int unicode_len) { + EXPECT_EQ(java_lang_String::hash_code(utf8_str, utf8_len), java_lang_String::hash_code(oop_str())); + EXPECT_TRUE(java_lang_String::equals(oop_str(), utf8_str, utf8_len)); +} + +void compare_unicode_unicode(const jchar* unicode_str1, const jchar* unicode_str2, int unicode_len) { + EXPECT_EQ(java_lang_String::hash_code(unicode_str1, unicode_len), java_lang_String::hash_code(unicode_str2, unicode_len)); + for (int i = 0; i < unicode_len; i++) { + EXPECT_EQ(unicode_str1[i], unicode_str2[i]); + } +} + +void compare_unicode_oop(const jchar* unicode_str, Handle oop_str, int unicode_len) { + EXPECT_EQ(java_lang_String::hash_code(unicode_str, unicode_len), java_lang_String::hash_code(oop_str())); + EXPECT_TRUE(java_lang_String::equals(oop_str(), unicode_str, unicode_len)); +} + +void compare_oop_oop(Handle oop_str1, Handle oop_str2) { + EXPECT_EQ(java_lang_String::hash_code(oop_str1()), java_lang_String::hash_code(oop_str2())); + EXPECT_TRUE(java_lang_String::equals(oop_str1(), oop_str2())); +} + +void test_utf8_convert(const char* utf8_str, size_t utf8_len, int unicode_len) { + EXPECT_TRUE(UTF8::is_legal_utf8((unsigned char*)utf8_str, strlen(utf8_str), false)); + + JavaThread* THREAD = JavaThread::current(); + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + ResourceMark rm(THREAD); + HandleMark hm(THREAD); + + jchar* unicode_str_from_utf8 = NEW_RESOURCE_ARRAY(jchar, unicode_len); + UTF8::convert_to_unicode(utf8_str, unicode_str_from_utf8, unicode_len); + Handle oop_str_from_utf8 = java_lang_String::create_from_str(utf8_str, THREAD); + + compare_utf8_unicode(utf8_str, unicode_str_from_utf8, utf8_len, unicode_len); + compare_utf8_oop(utf8_str, oop_str_from_utf8, utf8_len, unicode_len); + + size_t length = unicode_len; + const char* utf8_str_from_unicode = UNICODE::as_utf8(unicode_str_from_utf8, length); + const char* utf8_str_from_oop = java_lang_String::as_utf8_string(oop_str_from_utf8()); + + EXPECT_TRUE(UTF8::is_legal_utf8((unsigned char*)utf8_str_from_unicode, strlen(utf8_str_from_unicode), false)); + EXPECT_TRUE(UTF8::is_legal_utf8((unsigned char*)utf8_str_from_oop, strlen(utf8_str_from_oop), false)); + + compare_utf8_utf8(utf8_str, utf8_str_from_unicode, utf8_len); + compare_utf8_utf8(utf8_str, utf8_str_from_oop, utf8_len); +} + +void test_unicode_convert(const jchar* unicode_str, size_t utf8_len, int unicode_len) { + JavaThread* THREAD = JavaThread::current(); + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + ResourceMark rm(THREAD); + HandleMark hm(THREAD); + + size_t length = unicode_len; + const char* utf8_str_from_unicode = UNICODE::as_utf8(unicode_str, length); + Handle oop_str_from_unicode = java_lang_String::create_from_unicode(unicode_str, unicode_len, THREAD); + + EXPECT_TRUE(UTF8::is_legal_utf8((unsigned char*)utf8_str_from_unicode, strlen(utf8_str_from_unicode), false)); + + compare_utf8_unicode(utf8_str_from_unicode, unicode_str, utf8_len, unicode_len); + compare_unicode_oop(unicode_str, oop_str_from_unicode, unicode_len); + + int _; + jchar* unicode_str_from_utf8 = NEW_RESOURCE_ARRAY(jchar, unicode_len); + UTF8::convert_to_unicode(utf8_str_from_unicode, unicode_str_from_utf8, unicode_len); + const jchar* unicode_str_from_oop = java_lang_String::as_unicode_string(oop_str_from_unicode(), _, THREAD); + + compare_unicode_unicode(unicode_str, unicode_str_from_utf8, unicode_len); + compare_unicode_unicode(unicode_str, unicode_str_from_oop, unicode_len); +} + +void test_utf8_unicode_cross(const char* utf8_str, const jchar* unicode_str, size_t utf8_len, int unicode_len) { + compare_utf8_unicode(utf8_str, unicode_str, utf8_len, unicode_len); + + JavaThread* THREAD = JavaThread::current(); + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + ResourceMark rm(THREAD); + HandleMark hm(THREAD); + + size_t length = unicode_len; + const char* utf8_str_from_unicode = UNICODE::as_utf8(unicode_str, length); + + jchar* unicode_str_from_utf8 = NEW_RESOURCE_ARRAY(jchar, unicode_len); + UTF8::convert_to_unicode(utf8_str, unicode_str_from_utf8, unicode_len); + + Handle oop_str_from_unicode = java_lang_String::create_from_unicode(unicode_str, unicode_len, THREAD); + Handle oop_str_from_utf8 = java_lang_String::create_from_str(utf8_str, THREAD); + + compare_utf8_utf8(utf8_str, utf8_str_from_unicode, utf8_len); + compare_utf8_oop(utf8_str, oop_str_from_unicode, utf8_len, unicode_len); + + compare_unicode_unicode(unicode_str, unicode_str_from_utf8, unicode_len); + compare_unicode_oop(unicode_str, oop_str_from_utf8, unicode_len); + + compare_utf8_oop(utf8_str_from_unicode, oop_str_from_utf8, utf8_len, unicode_len); + compare_unicode_oop(unicode_str_from_utf8, oop_str_from_unicode, unicode_len); + + compare_utf8_unicode(utf8_str_from_unicode, unicode_str_from_utf8, utf8_len, unicode_len); + compare_oop_oop(oop_str_from_utf8, oop_str_from_unicode); +} + +TEST_VM(StringConversion, fromUTF8_ascii) { + const char utf8_str[ASCII_LENGTH + 1] = { }; + memcpy((unsigned char*)utf8_str, static_ascii_utf8_str, ASCII_LENGTH); + test_utf8_convert(utf8_str, ASCII_LENGTH, ASCII_LENGTH); +} + +TEST_VM(StringConversion, fromUTF8_varlen) { + const char utf8_str[UTF8_LENGTH + 1] = { }; + memcpy((unsigned char*)utf8_str, static_utf8_str, UTF8_LENGTH); + test_utf8_convert(utf8_str, UTF8_LENGTH, UNICODE_LENGTH); +} + +TEST_VM(StringConversion, fromUnicode_ascii) { + jchar unicode_str[ASCII_LENGTH] = { }; + memcpy(unicode_str, static_ascii_unicode_str, ASCII_LENGTH * sizeof(jchar)); + test_unicode_convert(unicode_str, ASCII_LENGTH, ASCII_LENGTH); +} + +TEST_VM(StringConversion, fromUnicode_varlen) { + jchar unicode_str[UNICODE_LENGTH] = { }; + memcpy(unicode_str, static_unicode_str, UNICODE_LENGTH * sizeof(jchar)); + test_unicode_convert(unicode_str, UTF8_LENGTH, UNICODE_LENGTH); +} + +TEST_VM(StringConversion, cross_ascii) { + const char utf8_str[ASCII_LENGTH + 1] = { }; + jchar unicode_str[ASCII_LENGTH] = { }; + memcpy((unsigned char*)utf8_str, static_ascii_utf8_str, ASCII_LENGTH); + memcpy(unicode_str, static_ascii_unicode_str, ASCII_LENGTH * sizeof(jchar)); + + test_utf8_unicode_cross(utf8_str, unicode_str, ASCII_LENGTH, ASCII_LENGTH); +} + +TEST_VM(StringConversion, cross_varlen) { + const char utf8_str[UTF8_LENGTH + 1] = { }; + jchar unicode_str[UNICODE_LENGTH] = { }; + memcpy((unsigned char*)utf8_str, static_utf8_str, UTF8_LENGTH); + memcpy(unicode_str, static_unicode_str, UNICODE_LENGTH * sizeof(jchar)); + + test_utf8_unicode_cross(utf8_str, unicode_str, UTF8_LENGTH, UNICODE_LENGTH); +} diff --git a/test/hotspot/gtest/classfile/test_stringIntern.cpp b/test/hotspot/gtest/classfile/test_stringIntern.cpp new file mode 100644 index 00000000000..69c0a5b2aa4 --- /dev/null +++ b/test/hotspot/gtest/classfile/test_stringIntern.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024, 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 "classfile/stringTable.hpp" +#include "classfile/symbolTable.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "unittest.hpp" + +// Tests that strings are interned and returns the same string when interning from different string types + +// Simple ASCII string "Java(R)!!" +static const char static_ascii_utf8_str[] = {0x4A, 0x61, 0x76, 0x61, 0x28, 0x52, 0x29, 0x21, 0x21}; +static const size_t ASCII_LENGTH = 9; + +// Complex string "Jāvá®!☺☻", has character lengths 13122133 = 16 +static const unsigned char static_utf8_str[] = {0x4A, 0x61, 0xCC, 0x84, 0x76, 0xC3, 0xA1, 0xC2, 0xAE, 0x21, 0xE2, 0x98, 0xBA, 0xE2, 0x98, 0xBB}; +static const size_t COMPLEX_LENGTH = 16; + +void test_intern(const char* utf8_str, size_t utf8_length) { + JavaThread* THREAD = JavaThread::current(); + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + HandleMark hm(THREAD); + + oop interned_string_from_utf8 = StringTable::intern(utf8_str, THREAD); + + EXPECT_TRUE(java_lang_String::equals(interned_string_from_utf8, utf8_str, utf8_length)); + EXPECT_EQ(java_lang_String::hash_code(utf8_str, utf8_length),java_lang_String::hash_code(interned_string_from_utf8)); + + Symbol* symbol_from_utf8 = SymbolTable::new_symbol(utf8_str, static_cast<int>(utf8_length)); + oop interned_string_from_symbol = StringTable::intern(symbol_from_utf8, THREAD); + + EXPECT_EQ(interned_string_from_utf8, interned_string_from_symbol); + + oop interned_string_from_oop1 = StringTable::intern(interned_string_from_utf8, THREAD); + + EXPECT_EQ(interned_string_from_utf8, interned_string_from_oop1); + +} + +TEST_VM(StringIntern, intern_ascii) { + const char utf8_str[ASCII_LENGTH + 1] = { }; + memcpy((unsigned char*)utf8_str, static_ascii_utf8_str, ASCII_LENGTH); + test_intern(utf8_str, ASCII_LENGTH); +} + +TEST_VM(StringIntern, intern_varlen) { + const char utf8_str[COMPLEX_LENGTH + 1] = { }; + memcpy((unsigned char*)utf8_str, static_utf8_str, COMPLEX_LENGTH); + test_intern(utf8_str, COMPLEX_LENGTH); +} diff --git a/test/hotspot/gtest/runtime/test_ThreadsListHandle.cpp b/test/hotspot/gtest/runtime/test_ThreadsListHandle.cpp index 5caa19fae95..81d36670c9a 100644 --- a/test/hotspot/gtest/runtime/test_ThreadsListHandle.cpp +++ b/test/hotspot/gtest/runtime/test_ThreadsListHandle.cpp @@ -171,8 +171,10 @@ TEST_VM(ThreadsListHandle, sanity) { // Verify the current thread refers to tlh2: EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh2.list()) << "thr->_threads_hazard_ptr must match tlh2.list()"; - EXPECT_EQ(tlh1.list(), tlh2.list()) - << "tlh1.list() must match tlh2.list()"; + // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values, + // until the root cause of test failure(JDK-8315141) has been fixed + // EXPECT_EQ(tlh1.list(), tlh2.list()) + // << "tlh1.list() must match tlh2.list()"; EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2) << "thr->_threads_list_ptr must match list_ptr2"; EXPECT_NE(list_ptr1, list_ptr2) @@ -291,8 +293,10 @@ TEST_VM(ThreadsListHandle, sanity) { // Verify the current thread refers to tlh2: EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh2.list()) << "thr->_threads_hazard_ptr must match tlh2.list()"; - EXPECT_EQ(tlh1.list(), tlh2.list()) - << "tlh1.list() must match tlh2.list()"; + // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values, + // until the root cause of test failure(JDK-8315141) has been fixed + // EXPECT_EQ(tlh1.list(), tlh2.list()) + // << "tlh1.list() must match tlh2.list()"; EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2) << "thr->_threads_list_ptr must match list_ptr2"; EXPECT_NE(list_ptr1, list_ptr2) @@ -339,8 +343,10 @@ TEST_VM(ThreadsListHandle, sanity) { // Verify the current thread refers to tlh3: EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh3.list()) << "thr->_threads_hazard_ptr must match tlh3.list()"; - EXPECT_EQ(tlh1.list(), tlh3.list()) - << "tlh1.list() must match tlh3.list()"; + // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values, + // until the root cause of test failure(JDK-8315141) has been fixed + // EXPECT_EQ(tlh1.list(), tlh3.list()) + // << "tlh1.list() must match tlh3.list()"; EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr3) << "thr->_threads_list_ptr must match list_ptr3"; EXPECT_NE(list_ptr1, list_ptr3) @@ -523,8 +529,10 @@ TEST_VM(ThreadsListHandle, sanity) { // Verify the current thread refers to tlh2a: EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh2a.list()) << "thr->_threads_hazard_ptr must match tlh2a.list()"; - EXPECT_EQ(tlh1.list(), tlh2a.list()) - << "tlh1.list() must match tlh2a.list()"; + // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values, + // until the root cause of test failure(JDK-8315141) has been fixed + // EXPECT_EQ(tlh1.list(), tlh2a.list()) + // << "tlh1.list() must match tlh2a.list()"; EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2a) << "thr->_threads_list_ptr must match list_ptr2a"; EXPECT_NE(list_ptr1, list_ptr2a) @@ -601,8 +609,10 @@ TEST_VM(ThreadsListHandle, sanity) { // Verify the current thread refers to tlh2b: EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh2b.list()) << "thr->_threads_hazard_ptr must match tlh2b.list()"; - EXPECT_EQ(tlh1.list(), tlh2b.list()) - << "tlh1.list() must match tlh2b.list()"; + // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values, + // until the root cause of test failure(JDK-8315141) has been fixed + // EXPECT_EQ(tlh1.list(), tlh2b.list()) + // << "tlh1.list() must match tlh2b.list()"; EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2b) << "thr->_threads_list_ptr must match list_ptr2b"; EXPECT_NE(list_ptr1, list_ptr2b) diff --git a/test/hotspot/gtest/utilities/test_powerOfTwo.cpp b/test/hotspot/gtest/utilities/test_powerOfTwo.cpp index 4d16e13ab31..fc4080bcefd 100644 --- a/test/hotspot/gtest/utilities/test_powerOfTwo.cpp +++ b/test/hotspot/gtest/utilities/test_powerOfTwo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -305,3 +305,44 @@ TEST(power_of_2, log2i) { check_log2i_variants_for((uint)0); check_log2i_variants_for((jlong)0); } + +template <typename T> void test_ceil_log2() { + EXPECT_EQ(ceil_log2(T(1)), 0) << "value = " << T(1); + EXPECT_EQ(ceil_log2(T(2)), 1) << "value = " << T(2); + EXPECT_EQ(ceil_log2(T(3)), 2) << "value = " << T(3); + EXPECT_EQ(ceil_log2(T(4)), 2) << "value = " << T(4); + EXPECT_EQ(ceil_log2(T(5)), 3) << "value = " << T(5); + EXPECT_EQ(ceil_log2(T(6)), 3) << "value = " << T(6); + EXPECT_EQ(ceil_log2(T(7)), 3) << "value = " << T(7); + EXPECT_EQ(ceil_log2(T(8)), 3) << "value = " << T(8); + EXPECT_EQ(ceil_log2(T(9)), 4) << "value = " << T(9); + EXPECT_EQ(ceil_log2(T(10)), 4) << "value = " << T(10); + + // Test max values + if (std::is_unsigned<T>::value) { + EXPECT_EQ(ceil_log2(std::numeric_limits<T>::max()), + (int)(sizeof(T) * 8)) << "value = " << std::numeric_limits<T>::max(); + } else { + EXPECT_EQ(ceil_log2(std::numeric_limits<T>::max()), + (int)(sizeof(T) * 8 - 1)) << "value = " << std::numeric_limits<T>::max(); + } +} + +TEST(power_of_2, ceil_log2) { + test_ceil_log2<int8_t>(); + test_ceil_log2<int16_t>(); + test_ceil_log2<int32_t>(); + test_ceil_log2<int64_t>(); + test_ceil_log2<uint8_t>(); + test_ceil_log2<uint16_t>(); + test_ceil_log2<uint32_t>(); + test_ceil_log2<uint64_t>(); +} + +#ifdef ASSERT +TEST_VM_ASSERT_MSG(power_of_2, ceil_log2_invalid, + ".*Invalid value") { + ceil_log2(0); +} + +#endif // ASSERT diff --git a/test/hotspot/jtreg/ProblemList-AotJdk.txt b/test/hotspot/jtreg/ProblemList-AotJdk.txt new file mode 100644 index 00000000000..2528f8d377e --- /dev/null +++ b/test/hotspot/jtreg/ProblemList-AotJdk.txt @@ -0,0 +1,18 @@ +runtime/modules/PatchModule/PatchModuleClassList.java 0000000 generic-all +runtime/NMT/NMTWithCDS.java 0000000 generic-all +runtime/symbols/TestSharedArchiveConfigFile.java 0000000 generic-all + +gc/arguments/TestSerialHeapSizeFlags.java 0000000 generic-all +gc/TestAllocateHeapAtMultiple.java 0000000 generic-all +gc/TestAllocateHeapAt.java 0000000 generic-all + +# use -Xshare +serviceability/sa/ClhsdbCDSJstackPrintAll.java 0000000 generic-all +serviceability/sa/ClhsdbCDSCore.java 0000000 generic-all +serviceability/sa/CDSJMapClstats.java 0000000 generic-all +compiler/intrinsics/klass/TestIsPrimitive.java 0000000 generic-all + +# This test is incompatible with AOTClassLinking. +# It has the assumption about unresolved Integer. +# However when AOTClassLinking is enabled, Integer is always resolved at JVM start-up. +compiler/ciReplay/TestInliningProtectionDomain.java 0000000 generic-all diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 43f72f0be73..f2f1c4f2f50 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -58,7 +58,7 @@ compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897 aix-ppc64,linux-ppc64le compiler/vectorapi/VectorLogicalOpIdentityTest.java 8302459 linux-x64,windows-x64 -compiler/vectorapi/VectorRebracket128Test.java#Z 8330538 generic-all +compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java 8331704 linux-riscv64 @@ -100,6 +100,17 @@ gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all # :hotspot_runtime +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id0 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id1 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id2 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id3 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id4 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id5 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id6 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id7 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id8 8344583 macosx-aarch64 +runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java#id9 8344583 macosx-aarch64 + runtime/jni/terminatedThread/TestTerminatedThread.java 8317789 aix-ppc64 runtime/handshake/HandshakeSuspendExitTest.java 8294313 generic-all runtime/Monitor/SyncOnValueBasedClassTest.java 8340995 linux-s390x @@ -113,9 +124,7 @@ runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 -runtime/Dictionary/CleanProtectionDomain.java 8341916 generic-all -runtime/Dictionary/ProtectionDomainCacheTest.java 8341916 generic-all -runtime/logging/ProtectionDomainVerificationTest.java 8341916 generic-all +runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x # Fails with +UseCompactObjectHeaders on aarch64 runtime/cds/appcds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64 diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index af97ff465de..1e5094bd116 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -74,6 +74,7 @@ requires.properties= \ vm.rtm.compiler \ vm.cds \ vm.cds.custom.loaders \ + vm.cds.supports.aot.class.linking \ vm.cds.write.archived.java.heap \ vm.continuations \ vm.jvmti \ diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 575c0caa674..718ecf610f1 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -56,6 +56,7 @@ hotspot_runtime_no_cds = \ hotspot_runtime_non_cds_mode = \ runtime \ -runtime/cds/CheckSharingWithDefaultArchive.java \ + -runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java \ -runtime/cds/appcds/dynamicArchive/DynamicSharedSymbols.java \ -runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java \ -runtime/cds/appcds/jcmd @@ -430,6 +431,7 @@ hotspot_cds_only = \ hotspot_appcds_dynamic = \ runtime/cds/appcds/ \ + -runtime/cds/appcds/applications \ -runtime/cds/appcds/cacheObject \ -runtime/cds/appcds/complexURI \ -runtime/cds/appcds/customLoader \ @@ -447,10 +449,12 @@ hotspot_appcds_dynamic = \ -runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java \ -runtime/cds/appcds/lambdaForm/DefaultClassListLFInvokers.java \ -runtime/cds/appcds/methodHandles \ + -runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java \ -runtime/cds/appcds/sharedStrings \ -runtime/cds/appcds/resolvedConstants \ -runtime/cds/appcds/ArchiveRelocationTest.java \ -runtime/cds/appcds/BadBSM.java \ + -runtime/cds/appcds/CommandLineFlagCombo.java \ -runtime/cds/appcds/DumpClassList.java \ -runtime/cds/appcds/DumpClassListWithLF.java \ -runtime/cds/appcds/DumpRuntimeClassesTest.java \ @@ -518,6 +522,61 @@ hotspot_cds_epsilongc = \ runtime/cds/appcds/jigsaw \ runtime/cds/appcds/loaderConstraints +# Run CDS tests with -XX:+AOTClassLinking. This should include most CDS tests, except for +# those that rely on redefining classes that are already archived. +hotspot_aot_classlinking = \ + runtime/cds \ + -runtime/cds/appcds/aotClassLinking \ + -runtime/cds/appcds/BadBSM.java \ + -runtime/cds/appcds/cacheObject/ArchivedIntegerCacheTest.java \ + -runtime/cds/appcds/cacheObject/ArchivedModuleCompareTest.java \ + -runtime/cds/appcds/CDSandJFR.java \ + -runtime/cds/appcds/customLoader/HelloCustom_JFR.java \ + -runtime/cds/appcds/customLoader/ParallelTestMultiFP.java \ + -runtime/cds/appcds/customLoader/ParallelTestSingleFP.java \ + -runtime/cds/appcds/customLoader/SameNameInTwoLoadersTest.java \ + -runtime/cds/appcds/DumpClassListWithLF.java \ + -runtime/cds/appcds/dynamicArchive/ModulePath.java \ + -runtime/cds/appcds/dynamicArchive/LambdaInBaseArchive.java \ + -runtime/cds/appcds/dynamicArchive/LambdasInTwoArchives.java \ + -runtime/cds/appcds/HelloExtTest.java \ + -runtime/cds/appcds/javaldr/AnonVmClassesDuringDump.java \ + -runtime/cds/appcds/javaldr/GCDuringDump.java \ + -runtime/cds/appcds/javaldr/LockDuringDump.java \ + -runtime/cds/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java \ + -runtime/cds/appcds/jigsaw/JigsawOptionsCombo.java \ + -runtime/cds/appcds/jigsaw/modulepath/AddOpens.java \ + -runtime/cds/appcds/jigsaw/modulepath/AddModules.java \ + -runtime/cds/appcds/jigsaw/modulepath/JvmtiAddPath.java \ + -runtime/cds/appcds/jigsaw/modulepath/MainModuleOnly.java \ + -runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP.java \ + -runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP_JFR.java \ + -runtime/cds/appcds/jigsaw/modulepath/ModulePathAndFMG.java \ + -runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java \ + -runtime/cds/appcds/jigsaw/overridetests/OverrideTests.java \ + -runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraph.java \ + -runtime/cds/appcds/JvmtiAddPath.java \ + -runtime/cds/appcds/jvmti \ + -runtime/cds/appcds/LambdaProxyClasslist.java \ + -runtime/cds/appcds/loaderConstraints/LoaderConstraintsTest.java \ + -runtime/cds/appcds/redefineClass \ + -runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java \ + -runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java \ + -runtime/cds/appcds/resolvedConstants/ResolvedConstants.java \ + -runtime/cds/appcds/RewriteBytecodesTest.java \ + -runtime/cds/appcds/SpecifySysLoaderProp.java \ + -runtime/cds/appcds/StaticArchiveWithLambda.java \ + -runtime/cds/appcds/TestEpsilonGCWithCDS.java \ + -runtime/cds/appcds/TestParallelGCWithCDS.java \ + -runtime/cds/appcds/TestSerialGCWithCDS.java \ + -runtime/cds/appcds/TestZGCWithCDS.java \ + -runtime/cds/appcds/TestWithProfiler.java \ + -runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java \ + -runtime/cds/serviceability/ReplaceCriticalClasses.java \ + -runtime/cds/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java \ + -runtime/cds/serviceability/transformRelatedClasses/TransformSuperAndSubClasses.java \ + -runtime/cds/serviceability/transformRelatedClasses/TransformSuperSubTwoPckgs.java + # needs -nativepath:<output>/images/test/hotspot/jtreg/native/ hotspot_metaspace = \ gtest/MetaspaceGtests.java \ @@ -537,6 +596,10 @@ tier1_runtime_appcds_exclude = \ runtime/cds/appcds/ \ -:tier1_runtime_appcds +tier1_runtime_no_cds = \ + :tier1_runtime \ + -runtime/cds + # This group should be executed with "jtreg -Dtest.cds.run.with.jfr=true ..." # to test interaction between AppCDS and JFR. It also has the side effect of # testing JVMTI ClassFileLoadHook. diff --git a/test/hotspot/jtreg/compiler/c2/TestFindNode.java b/test/hotspot/jtreg/compiler/c2/TestFindNode.java index ea7649c713a..fa545da7e58 100644 --- a/test/hotspot/jtreg/compiler/c2/TestFindNode.java +++ b/test/hotspot/jtreg/compiler/c2/TestFindNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -27,7 +27,7 @@ * @requires vm.debug == true & vm.flavor == "server" * @summary Test which uses some special flags in order to test Node::find() in debug builds which could result in an endless loop or a stack overflow crash. * - * @run main/othervm -Xbatch -XX:CompileCommand=option,*::*,bool,Vectorize,true -XX:CompileCommand=memlimit,compiler.c2.TestFindNode::*,0 + * @run main/othervm -Xbatch -XX:CompileCommand=option,*::*,bool,Vectorize,true * -XX:+PrintOpto -XX:+TraceLoopOpts compiler.c2.TestFindNode */ package compiler.c2; diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java index c8e8bd337ad..3598b8eae71 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java @@ -340,8 +340,8 @@ public void runTests(RunInfo info) { set_random(aL); set_random(bL); - offset1 = Math.abs(RANDOM.nextInt()) % 100; - offset2 = Math.abs(RANDOM.nextInt()) % 100; + offset1 = RANDOM.nextInt(100); + offset2 = RANDOM.nextInt(100); vB1 = (byte)RANDOM.nextInt(); vB2 = (byte)RANDOM.nextInt(); vS1 = (short)RANDOM.nextInt(); diff --git a/test/hotspot/jtreg/compiler/codegen/TestMatcherClone.java b/test/hotspot/jtreg/compiler/codegen/TestMatcherClone.java new file mode 100644 index 00000000000..e062cc20538 --- /dev/null +++ b/test/hotspot/jtreg/compiler/codegen/TestMatcherClone.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2024, 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 8331295 + * @requires os.simpleArch == "aarch64" + * @summary Check that the matcher does not needlessly clone an addressing + * expression that will in any case not be subsumed into complex + * loads and stores. + * @library /test/lib / + * @run driver compiler.codegen.TestMatcherClone + */ + +package compiler.codegen; + +import compiler.lib.ir_framework.*; + +public class TestMatcherClone { + static volatile int[] iArr; + static volatile int x; + static int[] iArr2 = new int[100]; + static int[] iArr3 = new int[100]; + + public static void main(String[] args) { + TestFramework.run(); + } + + @Test(compLevel = CompLevel.C2) + @IR(counts = {IRNode.ADD_P_OF, "reg_imm", "<200"}, + phase = CompilePhase.MATCHING) + public void test() { + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + iArr = new int[] {x % 2}; + + for (int i = 0; i < 50; i++) { + iArr2[i] = iArr3[i]; + } + } +} diff --git a/test/hotspot/jtreg/compiler/intrinsics/chacha/TestChaCha20.java b/test/hotspot/jtreg/compiler/intrinsics/chacha/TestChaCha20.java index 448d594b6aa..d2f287e8bcc 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/chacha/TestChaCha20.java +++ b/test/hotspot/jtreg/compiler/intrinsics/chacha/TestChaCha20.java @@ -104,7 +104,7 @@ public static void main(String... args) throws Exception { // Riscv64 intrinsics require the vector instructions if (containsFuzzy(cpuFeatures, "rvv")) { System.out.println("Setting up vector worker"); - configs.add(List.of("-XX:+UseRVV")); + configs.add(List.of()); } } else { // We only have ChaCha20 intrinsics on x64, aarch64 and riscv64 diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java index 3ee8fc8f45b..316eb5f3ce6 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java @@ -104,6 +104,15 @@ public enum CompilePhase { BEFORE_MATCHING("Before matching"), MATCHING("After matching", RegexType.MACH), GLOBAL_CODE_MOTION("Global code motion", RegexType.MACH), + INITIAL_LIVENESS("Initial liveness", RegexType.MACH), + AGGRESSIVE_COALESCING("Aggressive coalescing", RegexType.MACH), + INITIAL_SPILLING("Initial spilling", RegexType.MACH), + CONSERVATIVE_COALESCING("Conservative coalescing", RegexType.MACH, ActionOnRepeat.KEEP_FIRST), + ITERATIVE_SPILLING("Iterative spilling", RegexType.MACH, ActionOnRepeat.KEEP_FIRST), + AFTER_ITERATIVE_SPILLING("After iterative spilling", RegexType.MACH), + POST_ALLOCATION_COPY_REMOVAL("Post-allocation copy removal", RegexType.MACH), + MERGE_MULTI_DEFS("Merge multiple definitions", RegexType.MACH), + FIX_UP_SPILLS("Fix up spills", RegexType.MACH), REGISTER_ALLOCATION("Register Allocation", RegexType.MACH), BLOCK_ORDERING("Block Ordering", RegexType.MACH), PEEPHOLE("Peephole", RegexType.MACH), diff --git a/test/hotspot/jtreg/compiler/loopopts/TestDeepGraphVerifyIterativeGVN.java b/test/hotspot/jtreg/compiler/loopopts/TestDeepGraphVerifyIterativeGVN.java index bcb4a211368..d5ddc048702 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestDeepGraphVerifyIterativeGVN.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestDeepGraphVerifyIterativeGVN.java @@ -28,7 +28,6 @@ * @summary Test which causes a stack overflow segmentation fault with -XX:VerifyIterativeGVN=1 due to a too deep recursion in Node::verify_recur(). * * @run main/othervm/timeout=600 -Xcomp -XX:VerifyIterativeGVN=1 -XX:CompileCommand=compileonly,compiler.loopopts.TestDeepGraphVerifyIterativeGVN::* - * -XX:CompileCommand=memlimit,compiler.loopopts.TestDeepGraphVerifyIterativeGVN::*,0 * compiler.loopopts.TestDeepGraphVerifyIterativeGVN */ diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java index efd328dc5cc..60d753ee75f 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java @@ -168,6 +168,9 @@ public TestAlignVector() { tests.put("test14aB", () -> { return test14aB(aB.clone()); }); tests.put("test14bB", () -> { return test14bB(aB.clone()); }); tests.put("test14cB", () -> { return test14cB(aB.clone()); }); + tests.put("test14dB", () -> { return test14dB(aB.clone()); }); + tests.put("test14eB", () -> { return test14eB(aB.clone()); }); + tests.put("test14fB", () -> { return test14fB(aB.clone()); }); tests.put("test15aB", () -> { return test15aB(aB.clone()); }); tests.put("test15bB", () -> { return test15bB(aB.clone()); }); @@ -239,6 +242,9 @@ public TestAlignVector() { "test14aB", "test14bB", "test14cB", + "test14dB", + "test14eB", + "test14fB", "test15aB", "test15bB", "test15cB", @@ -1128,9 +1134,9 @@ static Object[] test13bBSIL(byte[] a, short[] b, int[] c, long[] d) { } @Test - @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", - IRNode.ADD_VB, "> 0", - IRNode.STORE_VECTOR, "> 0"}, + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}, applyIf = {"AlignVector", "false"}) @@ -1143,6 +1149,9 @@ static Object[] test13bBSIL(byte[] a, short[] b, int[] c, long[] d) { static Object[] test14aB(byte[] a) { // non-power-of-2 stride for (int i = 0; i < RANGE-20; i+=9) { + // Since the stride is shorter than the vector length, there will be always + // partial overlap of loads with previous stores, this leads to failure in + // store-to-load-forwarding -> vectorization not profitable. a[i+0]++; a[i+1]++; a[i+2]++; @@ -1164,9 +1173,9 @@ static Object[] test14aB(byte[] a) { } @Test - @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", - IRNode.ADD_VB, "> 0", - IRNode.STORE_VECTOR, "> 0"}, + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}, applyIf = {"AlignVector", "false"}) @@ -1179,6 +1188,9 @@ static Object[] test14aB(byte[] a) { static Object[] test14bB(byte[] a) { // non-power-of-2 stride for (int i = 0; i < RANGE-20; i+=3) { + // Since the stride is shorter than the vector length, there will be always + // partial overlap of loads with previous stores, this leads to failure in + // store-to-load-forwarding -> vectorization not profitable. a[i+0]++; a[i+1]++; a[i+2]++; @@ -1200,9 +1212,9 @@ static Object[] test14bB(byte[] a) { } @Test - @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", - IRNode.ADD_VB, "> 0", - IRNode.STORE_VECTOR, "> 0"}, + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}, applyIf = {"AlignVector", "false"}) @@ -1215,6 +1227,9 @@ static Object[] test14bB(byte[] a) { static Object[] test14cB(byte[] a) { // non-power-of-2 stride for (int i = 0; i < RANGE-20; i+=5) { + // Since the stride is shorter than the vector length, there will be always + // partial overlap of loads with previous stores, this leads to failure in + // store-to-load-forwarding -> vectorization not profitable. a[i+0]++; a[i+1]++; a[i+2]++; @@ -1235,6 +1250,90 @@ static Object[] test14cB(byte[] a) { return new Object[]{ a }; } + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE + "min(max_byte, 8)", "> 0", + IRNode.ADD_VB, IRNode.VECTOR_SIZE + "min(max_byte, 8)", "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test14dB(byte[] a) { + // non-power-of-2 stride + for (int i = 0; i < RANGE-20; i+=9) { + a[i+0]++; + a[i+1]++; + a[i+2]++; + a[i+3]++; + a[i+4]++; + a[i+5]++; + a[i+6]++; + a[i+7]++; + } + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE + "min(max_byte, 8)", "> 0", + IRNode.ADD_VB, IRNode.VECTOR_SIZE + "min(max_byte, 8)", "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test14eB(byte[] a) { + // non-power-of-2 stride + for (int i = 0; i < RANGE-32; i+=11) { + a[i+0]++; + a[i+1]++; + a[i+2]++; + a[i+3]++; + a[i+4]++; + a[i+5]++; + a[i+6]++; + a[i+7]++; + } + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE + "min(max_byte, 8)", "> 0", + IRNode.ADD_VB, IRNode.VECTOR_SIZE + "min(max_byte, 8)", "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test14fB(byte[] a) { + // non-power-of-2 stride + for (int i = 0; i < RANGE-40; i+=12) { + a[i+0]++; + a[i+1]++; + a[i+2]++; + a[i+3]++; + a[i+4]++; + a[i+5]++; + a[i+6]++; + a[i+7]++; + } + return new Object[]{ a }; + } + @Test // IR rules difficult because of modulo wrapping with offset after peeling. static Object[] test15aB(byte[] a) { diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestCyclicDependency.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestCyclicDependency.java index 3849f1b05cf..7c6b7c92c37 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestCyclicDependency.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestCyclicDependency.java @@ -24,7 +24,7 @@ /* * @test - * @bug 8298935 + * @bug 8298935 8334431 * @summary Writing forward on array creates cyclic dependency * which leads to wrong result, when ignored. * @library /test/lib / @@ -55,15 +55,30 @@ public class TestCyclicDependency { float[] goldF6a = new float[RANGE]; int[] goldI6b = new int[RANGE]; float[] goldF6b = new float[RANGE]; - int[] goldI7 = new int[RANGE]; - float[] goldF7 = new float[RANGE]; - int[] goldI8 = new int[RANGE]; - float[] goldF8 = new float[RANGE]; + int[] goldI7a = new int[RANGE]; + float[] goldF7a = new float[RANGE]; + int[] goldI7b = new int[RANGE]; + float[] goldF7b = new float[RANGE]; + float[] goldF7b_2 = new float[RANGE]; + int[] goldI7c = new int[RANGE]; + float[] goldF7c = new float[RANGE]; + int[] goldI8a = new int[RANGE]; + float[] goldF8a = new float[RANGE]; + int[] goldI8b = new int[RANGE]; + int[] goldI8b_2 = new int[RANGE]; + float[] goldF8b = new float[RANGE]; + int[] goldI8c = new int[RANGE]; + float[] goldF8c = new float[RANGE]; int[] goldI9 = new int[RANGE]; float[] goldF9 = new float[RANGE]; public static void main(String args[]) { - TestFramework.runWithFlags("-XX:CompileCommand=compileonly,TestCyclicDependency::test*"); + TestFramework.runWithFlags("-XX:CompileCommand=compileonly,TestCyclicDependency::test*", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-AlignVector", "-XX:-VerifyAlignVector"); + TestFramework.runWithFlags("-XX:CompileCommand=compileonly,TestCyclicDependency::test*", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+AlignVector", "-XX:-VerifyAlignVector"); + TestFramework.runWithFlags("-XX:CompileCommand=compileonly,TestCyclicDependency::test*", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+AlignVector", "-XX:+VerifyAlignVector"); } TestCyclicDependency() { @@ -95,12 +110,24 @@ public static void main(String args[]) { // test6b init(goldI6b, goldF6b); test6b(goldI6b, goldF6b); - // test7 - init(goldI7, goldF7); - test7(goldI7, goldF7); - // test8 - init(goldI8, goldF8); - test8(goldI8, goldF8); + // test7a + init(goldI7a, goldF7a); + test7a(goldI7a, goldF7a); + // test7b + init(goldI7b, goldF7b, goldF7b_2); + test7b(goldI7b, goldF7b, goldF7b_2); + // test7c + init(goldI7c, goldF7c); + test7c(goldI7c, goldF7c, goldF7c); + // test8a + init(goldI8a, goldF8a); + test8a(goldI8a, goldF8a); + // test8b + init(goldI8b, goldI8b_2, goldF8b); + test8b(goldI8b, goldI8b_2, goldF8b); + // test8c + init(goldI8c, goldF8c); + test8c(goldI8c, goldI8c, goldF8c); // test9 init(goldI9, goldF9); test9(goldI9, goldF9); @@ -205,26 +232,74 @@ public void runTest6b() { verifyF("test6b", dataF, goldF6b); } - @Run(test = "test7") + @Run(test = "test7a") @Warmup(100) - public void runTest7() { + public void runTest7a() { int[] dataI = new int[RANGE]; float[] dataF = new float[RANGE]; init(dataI, dataF); - test7(dataI, dataF); - verifyI("test7", dataI, goldI7); - verifyF("test7", dataF, goldF7); + test7a(dataI, dataF); + verifyI("test7a", dataI, goldI7a); + verifyF("test7a", dataF, goldF7a); } - @Run(test = "test8") + @Run(test = "test7b") @Warmup(100) - public void runTest8() { + public void runTest7b() { + int[] dataI = new int[RANGE]; + float[] dataF = new float[RANGE]; + float[] dataF_2 = new float[RANGE]; + init(dataI, dataF, dataF_2); + test7b(dataI, dataF, dataF_2); + verifyI("test7b", dataI, goldI7b); + verifyF("test7b", dataF, goldF7b); + verifyF("test7b", dataF_2, goldF7b_2); + } + + @Run(test = "test7c") + @Warmup(100) + public void runTest7c() { + int[] dataI = new int[RANGE]; + float[] dataF = new float[RANGE]; + init(dataI, dataF); + test7c(dataI, dataF, dataF); + verifyI("test7c", dataI, goldI7c); + verifyF("test7c", dataF, goldF7c); + } + + @Run(test = "test8a") + @Warmup(100) + public void runTest8a() { + int[] dataI = new int[RANGE]; + float[] dataF = new float[RANGE]; + init(dataI, dataF); + test8a(dataI, dataF); + verifyI("test8a", dataI, goldI8a); + verifyF("test8a", dataF, goldF8a); + } + + @Run(test = "test8b") + @Warmup(100) + public void runTest8b() { + int[] dataI = new int[RANGE]; + int[] dataI_2 = new int[RANGE]; + float[] dataF = new float[RANGE]; + init(dataI, dataI_2, dataF); + test8b(dataI, dataI_2, dataF); + verifyI("test8b", dataI, goldI8b); + verifyI("test8b", dataI_2, goldI8b_2); + verifyF("test8b", dataF, goldF8b); + } + + @Run(test = "test8c") + @Warmup(100) + public void runTest8c() { int[] dataI = new int[RANGE]; float[] dataF = new float[RANGE]; init(dataI, dataF); - test8(dataI, dataF); - verifyI("test8", dataI, goldI8); - verifyF("test8", dataF, goldF8); + test8c(dataI, dataI, dataF); + verifyI("test8c", dataI, goldI8c); + verifyF("test8c", dataF, goldF8c); } @Run(test = "test9") @@ -328,34 +403,156 @@ static void test6b(int[] dataI, float[] dataF) { } @Test - @IR(counts = {IRNode.ADD_VI, "> 0"}, + @IR(counts = {IRNode.ADD_VI, "= 0", + IRNode.ADD_VF, "= 0"}, applyIf = {"AlignVector", "false"}, applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.ADD_VI, "> 0", + IRNode.ADD_VF, "= 0"}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) // Some aarch64 machines have AlignVector == true, like ThunderX2 - static void test7(int[] dataI, float[] dataF) { + static void test7a(int[] dataI, float[] dataF) { for (int i = 0; i < RANGE - 32; i++) { // write forward 32 -> more than vector size -> can vectorize - // write forward 3 -> cannot vectorize - // separate types should make decision separately if they vectorize or not int v = dataI[i]; dataI[i + 32] = v + 5; + // write forward 3: + // AlignVector=true -> cannot vectorize because load and store cannot be both aligned + // AlignVector=false -> could vectorize, but would get 2-element vectors where + // store-to-load-forwarding fails, because we have store-load + // dependencies that have partial overlap. + // -> all vectorization cancled. float f = dataF[i]; dataF[i + 3] = f + 3.5f; } } @Test - @IR(counts = {IRNode.ADD_VF, IRNode.VECTOR_SIZE + "min(max_int, max_float)", "> 0"}, + @IR(counts = {IRNode.ADD_VI, "> 0", + IRNode.ADD_VF, IRNode.VECTOR_SIZE + "2", "> 0"}, + applyIf = {"AlignVector", "false"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.ADD_VI, "> 0", + IRNode.ADD_VF, "= 0"}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Some aarch64 machines have AlignVector == true, like ThunderX2 + static void test7b(int[] dataI, float[] dataF, float[] dataF_2) { + for (int i = 0; i < RANGE - 32; i++) { + // write forward 32 -> more than vector size -> can vectorize + int v = dataI[i]; + dataI[i + 32] = v + 5; + // write forward 3 to different array reference: + // AlignVector=true -> cannot vectorize because load and store cannot be both aligned + // AlignVector=false -> vectorizes because we cannot prove store-to-load forwarding + // failure. But we can only have 2-element vectors in case + // the two float-arrays reference the same array. + // Note: at runtime the float-arrays are always different. + float f = dataF[i]; + dataF_2[i + 3] = f + 3.5f; + } + } + + @Test + @IR(counts = {IRNode.ADD_VI, "> 0", + IRNode.ADD_VF, IRNode.VECTOR_SIZE + "2", "> 0"}, applyIf = {"AlignVector", "false"}, applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.ADD_VI, "> 0", + IRNode.ADD_VF, "= 0"}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) // Some aarch64 machines have AlignVector == true, like ThunderX2 - static void test8(int[] dataI, float[] dataF) { + static void test7c(int[] dataI, float[] dataF, float[] dataF_2) { for (int i = 0; i < RANGE - 32; i++) { // write forward 32 -> more than vector size -> can vectorize - // write forward 3 -> cannot vectorize - // separate types should make decision separately if they vectorize or not + int v = dataI[i]; + dataI[i + 32] = v + 5; + // write forward 3 to different array reference: + // AlignVector=true -> cannot vectorize because load and store cannot be both aligned + // AlignVector=false -> vectorizes because we cannot prove store-to-load forwarding + // failure. But we can only have 2-element vectors in case + // the two float-arrays reference the same array. + // Note: at runtime the float-arrays are always the same. + float f = dataF[i]; + dataF_2[i + 3] = f + 3.5f; + } + } + + @Test + @IR(counts = {IRNode.ADD_VI, "= 0", + IRNode.ADD_VF, "= 0"}, + applyIf = {"AlignVector", "false"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.ADD_VI, "= 0", + IRNode.ADD_VF, IRNode.VECTOR_SIZE + "min(max_int, max_float)", "> 0"}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Some aarch64 machines have AlignVector == true, like ThunderX2 + static void test8a(int[] dataI, float[] dataF) { + for (int i = 0; i < RANGE - 32; i++) { + // write forward 3: + // AlignVector=true -> cannot vectorize because load and store cannot be both aligned + // AlignVector=false -> could vectorize, but would get 2-element vectors where + // store-to-load-forwarding fails, because we have store-load + // dependencies that have partial overlap. + // -> all vectorization cancled. int v = dataI[i]; dataI[i + 3] = v + 5; + // write forward 32 -> more than vector size -> can vectorize + float f = dataF[i]; + dataF[i + 32] = f + 3.5f; + } + } + + @Test + @IR(counts = {IRNode.ADD_VI, IRNode.VECTOR_SIZE + "2", "> 0", + IRNode.ADD_VF, IRNode.VECTOR_SIZE + "min(max_int, max_float)", "> 0"}, + applyIf = {"AlignVector", "false"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.ADD_VI, "= 0", + IRNode.ADD_VF, IRNode.VECTOR_SIZE + "min(max_int, max_float)", "> 0"}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Some aarch64 machines have AlignVector == true, like ThunderX2 + static void test8b(int[] dataI, int[] dataI_2, float[] dataF) { + for (int i = 0; i < RANGE - 32; i++) { + // write forward 3 to different array reference: + // AlignVector=true -> cannot vectorize because load and store cannot be both aligned + // AlignVector=false -> vectorizes because we cannot prove store-to-load forwarding + // failure. But we can only have 2-element vectors in case + // the two float-arrays reference the same array. + // Note: at runtime the float-arrays are always different. + int v = dataI[i]; + dataI_2[i + 3] = v + 5; + // write forward 32 -> more than vector size -> can vectorize + float f = dataF[i]; + dataF[i + 32] = f + 3.5f; + } + } + + @Test + @IR(counts = {IRNode.ADD_VI, IRNode.VECTOR_SIZE + "2", "> 0", + IRNode.ADD_VF, IRNode.VECTOR_SIZE + "min(max_int, max_float)", "> 0"}, + applyIf = {"AlignVector", "false"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.ADD_VI, "= 0", + IRNode.ADD_VF, IRNode.VECTOR_SIZE + "min(max_int, max_float)", "> 0"}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Some aarch64 machines have AlignVector == true, like ThunderX2 + static void test8c(int[] dataI, int[] dataI_2, float[] dataF) { + for (int i = 0; i < RANGE - 32; i++) { + // write forward 3 to different array reference: + // AlignVector=true -> cannot vectorize because load and store cannot be both aligned + // AlignVector=false -> vectorizes because we cannot prove store-to-load forwarding + // failure. But we can only have 2-element vectors in case + // the two float-arrays reference the same array. + // Note: at runtime the float-arrays are always the same. + int v = dataI[i]; + dataI_2[i + 3] = v + 5; + // write forward 32 -> more than vector size -> can vectorize float f = dataF[i]; dataF[i + 32] = f + 3.5f; } @@ -380,6 +577,22 @@ public static void init(int[] dataI, float[] dataF) { } } + public static void init(int[] dataI, float[] dataF, float[] dataF_2) { + for (int j = 0; j < RANGE; j++) { + dataI[j] = j; + dataF[j] = j * 0.5f; + dataF_2[j] = j * 0.3f; + } + } + + public static void init(int[] dataI, int[] dataI_2, float[] dataF) { + for (int j = 0; j < RANGE; j++) { + dataI[j] = j; + dataI_2[j] = 3*j - 42; + dataF[j] = j * 0.5f; + } + } + static void verifyI(String name, int[] data, int[] gold) { for (int i = 0; i < RANGE; i++) { if (data[i] != gold[i]) { diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java index 8e5ac88a27d..cfa19ce385a 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java @@ -643,6 +643,12 @@ static List<Integer> getOffsets() { return new ArrayList<Integer>(set); } + enum ExpectVectorization { + ALWAYS, // -> positive "count" IR rule + UNKNOWN, // -> disable IR rule + NEVER // -> negative "failOn" IR rule + }; + static record TestDefinition (int id, Type type, int offset) { /* @@ -656,18 +662,22 @@ String generate() { String aliasingComment; String secondArgument; String loadFrom; + boolean isSingleArray; switch (RANDOM.nextInt(3)) { case 0: // a[i + offset] = a[i] + isSingleArray = true; aliasingComment = "single-array"; secondArgument = "a"; loadFrom = "a"; break; case 1: // a[i + offset] = b[i], but a and b alias, i.e. at runtime a == b. + isSingleArray = false; aliasingComment = "aliasing"; secondArgument = "a"; loadFrom = "b"; break; case 2: // a[i + offset] = b[i], and a and b do not alias, i.e. at runtime a != b. + isSingleArray = false; aliasingComment = "non-aliasing"; secondArgument = "b"; loadFrom = "b"; @@ -712,7 +722,7 @@ String generate() { type.name, id, type.name, id, id, id, id, secondArgument, id, // IR rules - generateIRRules(), + generateIRRules(isSingleArray), // test id, type.name, type.name, start, end, @@ -726,7 +736,7 @@ String generate() { * expect depends on AlignVector and MaxVectorSize, as well as the byteOffset between the load and * store. */ - String generateIRRules() { + String generateIRRules(boolean isSingleArray) { StringBuilder builder = new StringBuilder(); for (CPUMinVectorWidth cm : getCPUMinVectorWidth(type.name)) { @@ -744,29 +754,75 @@ String generateIRRules() { // power of two. int infinity = 256; // No vector size is ever larger than this. int maxVectorWidth = infinity; // no constraint by default + int log2 = 31 - Integer.numberOfLeadingZeros(offset); + int floorPow2Offset = 1 << log2; if (0 < byteOffset && byteOffset < maxVectorWidth) { - int log2 = 31 - Integer.numberOfLeadingZeros(offset); - int floorPow2 = 1 << log2; - maxVectorWidth = Math.min(maxVectorWidth, floorPow2 * type.size); - builder.append(" // Vectors must have at most " + floorPow2 + + maxVectorWidth = Math.min(maxVectorWidth, floorPow2Offset * type.size); + builder.append(" // Vectors must have at most " + floorPow2Offset + " elements: maxVectorWidth = " + maxVectorWidth + " to avoid cyclic dependency.\n"); } + ExpectVectorization expectVectorization = ExpectVectorization.ALWAYS; + if (isSingleArray && 0 < offset && offset < 64) { + // In a store-forward case at iteration distances below a certain threshold, and not there + // is some partial overlap between the expected vector store and some vector load in a later + // iteration, we avoid vectorization to avoid the latency penalties of store-to-load + // forwarding failure. We only detect these failures in single-array cases. + // + // Note: we currently never detect store-to-load-forwarding failures beyond 64 iterations, + // And so if the offset >= 64, we always expect vectorization. + // + // The condition for partial overlap: + // offset % #elements != 0 + // + // But we do not know #elements exactly, only a range from min/maxVectorWidth. + + int maxElements = maxVectorWidth / type.size; + int minElements = minVectorWidth / type.size; + boolean sometimesPartialOverlap = offset % maxElements != 0; + // If offset % minElements != 0, then it does also not hold for any larger vector. + boolean alwaysPartialOverlap = offset % minElements != 0; + + if (alwaysPartialOverlap) { + // It is a little tricky to know the exact threshold. On all platforms and in all + // unrolling cases, it is between 8 and 64. Hence, we have these 3 cases: + if (offset <= 8) { + builder.append(" // We always detect store-to-load-forwarding failures -> never vectorize.\n"); + expectVectorization = ExpectVectorization.NEVER; + } else if (offset <= 64) { + builder.append(" // Unknown if detect store-to-load-forwarding failures -> maybe disable IR rules.\n"); + expectVectorization = ExpectVectorization.UNKNOWN; + } else { + // offset > 64 -> offset too large, expect no store-to-load-failure detection + throw new RuntimeException("impossible"); + } + } else if (sometimesPartialOverlap && !alwaysPartialOverlap) { + builder.append(" // Partial overlap condition true: sometimes but not always -> maybe disable IR rules.\n"); + expectVectorization = ExpectVectorization.UNKNOWN; + } else { + builder.append(" // Partial overlap never happens -> expect vectorization.\n"); + expectVectorization = ExpectVectorization.ALWAYS; + } + } + // Rule 1: No strict alignment: -XX:-AlignVector + ExpectVectorization expectVectorization1 = expectVectorization; IRRule r1 = new IRRule(type, type.irNode, applyIfCPUFeature); r1.addApplyIf("\"AlignVector\", \"false\""); r1.addApplyIf("\"MaxVectorSize\", \">=" + minVectorWidth + "\""); if (maxVectorWidth < minVectorWidth) { builder.append(" // maxVectorWidth < minVectorWidth -> expect no vectorization.\n"); - r1.setNegative(); + expectVectorization1 = ExpectVectorization.NEVER; } else if (maxVectorWidth < infinity) { r1.setSize("min(" + (maxVectorWidth / type.size) + ",max_" + type.name + ")"); } + r1.setExpectVectVectorization(expectVectorization1); r1.generate(builder); // Rule 2: strict alignment: -XX:+AlignVector + ExpectVectorization expectVectorization2 = expectVectorization; IRRule r2 = new IRRule(type, type.irNode, applyIfCPUFeature); r2.addApplyIf("\"AlignVector\", \"true\""); r2.addApplyIf("\"MaxVectorSize\", \">=" + minVectorWidth + "\""); @@ -791,18 +847,23 @@ String generateIRRules() { builder.append(" // byteOffset % awMax == 0 -> always trivially aligned\n"); } else if (byteOffset % awMin != 0) { builder.append(" // byteOffset % awMin != 0 -> can never align -> expect no vectorization.\n"); - r2.setNegative(); + expectVectorization2 = ExpectVectorization.NEVER; } else { - builder.append(" // Alignment unknown -> disable IR rule.\n"); - r2.disable(); + if (expectVectorization2 != ExpectVectorization.NEVER) { + builder.append(" // Alignment unknown -> disable IR rule.\n"); + expectVectorization2 = ExpectVectorization.UNKNOWN; + } else { + builder.append(" // Alignment unknown -> but already proved no vectorization above.\n"); + } } if (maxVectorWidth < minVectorWidth) { builder.append(" // Not at least 2 elements or 4 bytes -> expect no vectorization.\n"); - r2.setNegative(); + expectVectorization2 = ExpectVectorization.NEVER; } else if (maxVectorWidth < infinity) { r2.setSize("min(" + (maxVectorWidth / type.size) + ",max_" + type.name + ")"); } + r2.setExpectVectVectorization(expectVectorization2); r2.generate(builder); } return builder.toString(); @@ -846,12 +907,12 @@ void setSize(String size) { this.size = size; } - void setNegative() { - this.isPositiveRule = false; - } - - void disable() { - this.isEnabled = false; + void setExpectVectVectorization(ExpectVectorization expectVectorization) { + switch(expectVectorization) { + case ExpectVectorization.NEVER -> { this.isPositiveRule = false; } + case ExpectVectorization.UNKNOWN -> { this.isEnabled = false; } + case ExpectVectorization.ALWAYS -> {} + } } void addApplyIf(String constraint) { diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java b/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java index 4f7f03590dd..7e6a457d25e 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java @@ -35,7 +35,7 @@ import jdk.internal.vm.annotation.ForceInline; /* - * @test id=Z + * @test * @bug 8260473 * @requires vm.gc.Z * @modules jdk.incubator.vector diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java index 16d04102082..8a0715eadfe 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java @@ -138,8 +138,11 @@ public int[] multipleOpsWithMultipleConstants() { } @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse4.1", "true"}, counts = {IRNode.STORE_VECTOR, ">0"}) + // With sse2, the MulI does not vectorize. This means we have vectorized stores + // to res1, but scalar loads from res1. The store-to-load-forwarding failure + // detection catches this and rejects vectorization. public int[] multipleStores() { int[] res1 = new int[SIZE]; int[] res2 = new int[SIZE]; diff --git a/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java b/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java index 00e32a4136e..1a3d07bf80d 100644 --- a/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java +++ b/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java @@ -27,7 +27,7 @@ * @summary Test OOME in due to classloader leak * @requires vm.gc.Shenandoah * @library /test/lib - * @run driver/timeout=600 TestClassLoaderLeak + * @run driver TestClassLoaderLeak */ import java.util.*; diff --git a/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java b/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java deleted file mode 100644 index 4e4a9329f5d..00000000000 --- a/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Verifies the creation and cleaup of entries in the Protection Domain Table - * @requires vm.flagless - * @library /test/lib - * @modules java.base/jdk.internal.misc - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run driver CleanProtectionDomain - */ - -import java.security.ProtectionDomain; -import jdk.test.lib.compiler.InMemoryJavaCompiler; -import jdk.internal.misc.Unsafe; -import static jdk.test.lib.Asserts.*; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; -import jdk.test.whitebox.WhiteBox; - -public class CleanProtectionDomain { - - public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-Xlog:protectiondomain+table=debug", - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - "-Xbootclasspath/a:.", - "-Djava.security.manager=allow", - Test.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("protection domain added"); - output.shouldContain("protection domain unlinked"); - output.shouldHaveExitValue(0); - } - - static class Test { - public static void test() throws Exception { - TestClassLoader classloader = new TestClassLoader(); - ProtectionDomain pd = new ProtectionDomain(null, null); - byte klassbuf[] = InMemoryJavaCompiler.compile("TestClass", "class TestClass { }"); - Class<?> klass = classloader.defineClass("TestClass", klassbuf, pd); - } - - public static void main(String[] args) throws Exception { - WhiteBox wb = WhiteBox.getWhiteBox(); - int removedCountOrig = wb.protectionDomainRemovedCount(); - int removedCount; - - test(); - - // Wait until ServiceThread cleans ProtectionDomain table. - // When the TestClassLoader is unloaded by GC, at least one - // ProtectionDomainCacheEntry will be eligible for removal. - int cnt = 0; - while (true) { - if (cnt++ % 30 == 0) { - System.gc(); - } - removedCount = wb.protectionDomainRemovedCount(); - if (removedCountOrig != removedCount) { - break; - } - Thread.sleep(100); - } - } - - private static class TestClassLoader extends ClassLoader { - public TestClassLoader() { - super(); - } - - public Class<?> defineClass(String name, byte[] bytes, ProtectionDomain pd) { - return defineClass(name, bytes, 0, bytes.length, pd); - } - } - } -} diff --git a/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java b/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java deleted file mode 100644 index 423fba7d221..00000000000 --- a/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2018, 2023, 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 8151486 8218266 - * @summary Call Class.forName() on the system classloader from a class loaded - * from a custom classloader, using the current class's protection domain. - * @requires vm.flagless - * @library /test/lib - * @modules java.base/jdk.internal.misc - * @build jdk.test.lib.Utils - * jdk.test.lib.util.JarUtils - * @build ClassForName ProtectionDomainCacheTest - * @run driver ProtectionDomainCacheTest - */ - -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import jdk.test.lib.Utils; -import jdk.test.lib.util.JarUtils; -import java.io.File; - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; - -/* - * Create .jar, load ClassForName from .jar using a URLClassLoader - */ -public class ProtectionDomainCacheTest { - static class Test { - private static final long TIMEOUT = (long)(5000.0 * Utils.TIMEOUT_FACTOR); - private static final String TESTCLASSES = System.getProperty("test.classes", "."); - private static final String CLASSFILENAME = "ClassForName.class"; - - // Use a new classloader to load the ClassForName class. - public static void loadAndRun(Path jarFilePath) - throws Exception { - ClassLoader classLoader = new URLClassLoader( - new URL[]{jarFilePath.toUri().toURL()}) { - @Override public String toString() { return "LeakedClassLoader"; } - }; - - Class<?> loadClass = Class.forName("ClassForName", true, classLoader); - loadClass.newInstance(); - - System.out.println("returning : " + classLoader); - } - - public static void main(final String[] args) throws Exception { - // Create a temporary .jar file containing ClassForName.class - Path testClassesDir = Paths.get(TESTCLASSES); - Path jarFilePath = Files.createTempFile("cfn", ".jar"); - JarUtils.createJarFile(jarFilePath, testClassesDir, CLASSFILENAME); - jarFilePath.toFile().deleteOnExit(); - - // Remove the ClassForName.class file that jtreg built, to make sure - // we're loading from the tmp .jar - Path classFile = FileSystems.getDefault().getPath(TESTCLASSES, - CLASSFILENAME); - Files.delete(classFile); - - for (int i = 0; i < 20; i++) { - loadAndRun(jarFilePath); - } - - // Give the GC a chance to unload protection domains - for (int i = 0; i < 100; i++) { - System.gc(); - } - System.out.println("All Classloaders and protection domain cache entries successfully unloaded"); - } - } - - public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-Djava.security.policy==" + System.getProperty("test.src") + File.separator + "test.policy", - "-Dtest.classes=" + System.getProperty("test.classes", "."), - "-XX:+UnlockDiagnosticVMOptions", - "-XX:VerifySubSet=dictionary", - "-XX:+VerifyAfterGC", - "-Xlog:gc+verify,protectiondomain=trace", - "-Djava.security.manager", - Test.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("PD in set is not alive"); - output.shouldContain("HandshakeForPD::do_thread"); - output.shouldHaveExitValue(0); - } -} diff --git a/test/hotspot/jtreg/runtime/cds/SharedBaseAddress.java b/test/hotspot/jtreg/runtime/cds/SharedBaseAddress.java index a7f31cf1a08..49265680ef2 100644 --- a/test/hotspot/jtreg/runtime/cds/SharedBaseAddress.java +++ b/test/hotspot/jtreg/runtime/cds/SharedBaseAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -67,8 +67,23 @@ import jdk.test.lib.cds.CDSOptions; import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; +import jtreg.SkippedException; public class SharedBaseAddress { + static final boolean skipUncompressedOopsTests; + static boolean checkSkipUncompressedOopsTests(String prop) { + String opts = System.getProperty(prop); + return opts.contains("+AOTClassLinking") && + opts.matches(".*[+]Use[A-Za-z]+GC.*") && !opts.contains("+UseG1GC"); + } + static { + // AOTClassLinking requires the ability to load archived heap objects. However, + // due to JDK-8341371, only G1GC supports loading archived heap objects + // with uncompressed oops. + skipUncompressedOopsTests = + checkSkipUncompressedOopsTests("test.vm.opts") || + checkSkipUncompressedOopsTests("test.java.opts"); + } // shared base address test table for {32, 64}bit VM private static final String[] testTableShared = { @@ -100,6 +115,10 @@ public static void test(String[] args, String[] testTable) throws Exception { int end = args[0].equals("0") ? mid : testTable.length; boolean provoke = (args.length > 1 && args[1].equals("provoke")); + if (provoke && skipUncompressedOopsTests) { + throw new SkippedException("Test skipped due to JDK-8341371"); + } + // provoke == true: we want to increase the chance that mapping the generated archive at the designated base // succeeds, to test Klass pointer encoding at that weird location. We do this by sizing heap + class space // small, and by switching off compressed oops. diff --git a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java index 590f22feed7..192f7ca42a8 100644 --- a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java +++ b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java @@ -66,12 +66,32 @@ * @run driver TestDefaultArchiveLoading coops_coh */ +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; + import jtreg.SkippedException; public class TestDefaultArchiveLoading { + + private static String archiveName(String archiveSuffix) { + return "classes" + archiveSuffix + ".jsa"; + } + + private static Path archivePath(String archiveSuffix) { + return Paths.get(System.getProperty("java.home"), "lib", + "server", archiveName(archiveSuffix)); + } + + private static boolean isCOHArchiveAvailable(char coops, char coh, + String archiveSuffix) throws Exception { + Path archive= archivePath(archiveSuffix); + return Files.exists(archive); + } + public static void main(String[] args) throws Exception { if (args.length != 1) { @@ -90,6 +110,10 @@ public static void main(String[] args) throws Exception { coops = '-'; coh = '+'; archiveSuffix = "_nocoops_coh"; + if (!isCOHArchiveAvailable(coops, coh, archiveSuffix)) { + throw new SkippedException("Skipping test due to " + + archivePath(archiveSuffix).toString() + " not available"); + } break; case "coops_nocoh": coops = '+'; @@ -99,6 +123,10 @@ public static void main(String[] args) throws Exception { case "coops_coh": coh = coops = '+'; archiveSuffix = "_coh"; + if (!isCOHArchiveAvailable(coops, coh, archiveSuffix)) { + throw new SkippedException("Skipping test due to " + + archivePath(archiveSuffix).toString() + " not available"); + } break; default: throw new RuntimeException("Invalid argument " + args[0]); } @@ -114,7 +142,6 @@ public static void main(String[] args) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); - output.shouldContain("classes" + archiveSuffix + ".jsa"); - + output.shouldContain(archiveName(archiveSuffix)); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java new file mode 100644 index 00000000000..3a678eefc5b --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @summary "AOT" aliases for traditional CDS command-line options + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @build Hello + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello + * @run driver AOTFlags + */ + +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class AOTFlags { + static String appJar = ClassFileInstaller.getJarPath("hello.jar"); + static String aotConfigFile = "hello.aotconfig"; + static String aotCacheFile = "hello.aot"; + static String helloClass = "Hello"; + + public static void main(String[] args) throws Exception { + positiveTests(); + negativeTests(); + } + + static void positiveTests() throws Exception { + // (1) Training Run + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=record", + "-XX:AOTConfiguration=" + aotConfigFile, + "-cp", appJar, helloClass); + + OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "train"); + out.shouldContain("Hello World"); + out.shouldHaveExitValue(0); + + // (2) Assembly Phase + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=create", + "-XX:AOTConfiguration=" + aotConfigFile, + "-XX:AOTCache=" + aotCacheFile, + "-Xlog:cds", + "-cp", appJar); + out = CDSTestUtils.executeAndLog(pb, "asm"); + out.shouldContain("Dumping shared data to file:"); + out.shouldMatch("cds.*hello[.]aot"); + out.shouldHaveExitValue(0); + + // (3) Production Run with AOTCache + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTCache=" + aotCacheFile, + "-Xlog:cds", + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "prod"); + out.shouldContain("Opened archive hello.aot."); + out.shouldContain("Hello World"); + out.shouldHaveExitValue(0); + + // (4) AOTMode=off + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTCache=" + aotCacheFile, + "--show-version", + "-Xlog:cds", + "-XX:AOTMode=off", + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "prod"); + out.shouldNotContain(", sharing"); + out.shouldNotContain("Opened archive hello.aot."); + out.shouldContain("Hello World"); + out.shouldHaveExitValue(0); + + // (5) AOTMode=auto + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTCache=" + aotCacheFile, + "--show-version", + "-Xlog:cds", + "-XX:AOTMode=auto", + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "prod"); + out.shouldContain(", sharing"); + out.shouldContain("Opened archive hello.aot."); + out.shouldContain("Hello World"); + out.shouldHaveExitValue(0); + + // (5) AOTMode=on + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTCache=" + aotCacheFile, + "--show-version", + "-Xlog:cds", + "-XX:AOTMode=on", + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "prod"); + out.shouldContain(", sharing"); + out.shouldContain("Opened archive hello.aot."); + out.shouldContain("Hello World"); + out.shouldHaveExitValue(0); + } + + static void negativeTests() throws Exception { + // (1) Mixing old and new options + String mixOldNewErrSuffix = " cannot be used at the same time with -Xshare:on, -Xshare:auto, " + + "-Xshare:off, -Xshare:dump, DumpLoadedClassList, SharedClassListFile, " + + "or SharedArchiveFile"; + + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xshare:off", + "-XX:AOTConfiguration=" + aotConfigFile, + "-cp", appJar, helloClass); + + OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Option AOTConfiguration" + mixOldNewErrSuffix); + out.shouldNotHaveExitValue(0); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:SharedArchiveFile=" + aotCacheFile, + "-XX:AOTCache=" + aotCacheFile, + "-cp", appJar, helloClass); + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Option AOTCache" + mixOldNewErrSuffix); + out.shouldNotHaveExitValue(0); + + // (2) Use AOTConfiguration without AOTMode + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTConfiguration=" + aotConfigFile, + "-cp", appJar, helloClass); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create"); + out.shouldNotHaveExitValue(0); + + // (3) Use AOTMode without AOTConfiguration + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=record", + "-cp", appJar, helloClass); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("-XX:AOTMode=record cannot be used without setting AOTConfiguration"); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=create", + "-cp", appJar, helloClass); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("-XX:AOTMode=create cannot be used without setting AOTConfiguration"); + out.shouldNotHaveExitValue(0); + + // (4) Bad AOTMode + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=foo", + "-cp", appJar, helloClass); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Unrecognized value foo for AOTMode. Must be one of the following: off, record, create, auto, on"); + out.shouldNotHaveExitValue(0); + + // (5) AOTCache specified with -XX:AOTMode=record + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=record", + "-XX:AOTConfiguration=" + aotConfigFile, + "-XX:AOTCache=" + aotCacheFile, + "-cp", appJar, helloClass); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("AOTCache must not be specified when using -XX:AOTMode=record"); + out.shouldNotHaveExitValue(0); + + // (5) AOTCache not specified with -XX:AOTMode=create + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=create", + "-XX:AOTConfiguration=" + aotConfigFile, + "-cp", appJar, helloClass); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("AOTCache must be specified when using -XX:AOTMode=create"); + out.shouldNotHaveExitValue(0); + + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java b/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java index fe618256f65..df47e6bebc8 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java @@ -190,13 +190,20 @@ static void testNonExistentJars() throws Exception { Files.copy(Paths.get(cp), Paths.get(nonExistPath), StandardCopyOption.REPLACE_EXISTING); - TestCommon.run( + CDSTestUtils.Result result = TestCommon.run( "-Xlog:class+path", "-cp", cp, - "CpAttr6") - .assertNormalExit(output -> { - output.shouldMatch("Archived non-system classes are disabled because the file .*cpattrX.jar exists"); - }); + "CpAttr6"); + if (CDSTestUtils.isAOTClassLinkingEnabled()) { + result.assertAbnormalExit(output -> { + output.shouldMatch("CDS archive has aot-linked classes. It cannot be used because the file .*cpattrX.jar exists"); + }); + + } else { + result.assertNormalExit(output -> { + output.shouldMatch("Archived non-system classes are disabled because the file .*cpattrX.jar exists"); + }); + } } static void testClassPathAttrJarOnCP() throws Exception { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaContainsOldInf.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaContainsOldInf.java index 8dec80b9f58..6d1b23628c5 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaContainsOldInf.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaContainsOldInf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -64,7 +64,11 @@ public static void main(String[] args) throws Exception { OutputAnalyzer output = CDSTestUtils.createArchiveAndCheck(opts); TestCommon.checkExecReturn(output, 0, true, "Skipping OldProvider: Old class has been linked"); - output.shouldMatch("Skipping.LambdaContainsOldInfApp[$][$]Lambda.*0x.*:.*Old.class.has.been.linked"); + if (CDSTestUtils.isAOTClassLinkingEnabled()) { + output.shouldMatch("Cannot aot-resolve Lambda proxy because OldProvider is excluded"); + } else { + output.shouldMatch("Skipping.LambdaContainsOldInfApp[$][$]Lambda.*0x.*:.*Old.class.has.been.linked"); + } // run with archive CDSOptions runOpts = (new CDSOptions()) diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java index 3a0bb740387..d7ce22e3cf1 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -68,7 +68,11 @@ public static void main(String[] args) throws Exception { .addSuffix(mainClass); OutputAnalyzer output = CDSTestUtils.runWithArchive(runOpts); output.shouldContain("[class,load] LambdaWithOldClassApp source: shared objects file") - .shouldMatch(".class.load. LambdaWithOldClassApp[$][$]Lambda.*/0x.*source:.*shared objects file") .shouldHaveExitValue(0); + if (!CDSTestUtils.isAOTClassLinkingEnabled()) { + // With AOTClassLinking, we don't archive any lambda with old classes in the method + // signatures. + output.shouldMatch(".class.load. LambdaWithOldClassApp[$][$]Lambda.*/0x.*source:.*shared objects file"); + } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java index 513ec57d279..360fce5879a 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,11 @@ public class LambdaWithUseImplMethodHandle { // See pkg2/Child.jcod for details about the condition that triggers JDK-8290417 public static void main(String[] args) throws Exception { + test(false); + test(true); + } + + static void test(boolean aotClassLinking) throws Exception { String appJar = ClassFileInstaller.getJarPath("test.jar"); String mainClass = "LambdaWithUseImplMethodHandleApp"; String expectedMsg = "Called BaseWithProtectedMethod::protectedMethod"; @@ -57,6 +62,9 @@ public static void main(String[] args) throws Exception { .addPrefix("-XX:ExtraSharedClassListFile=" + classList, "-cp", appJar) .setArchiveName(archiveName); + if (aotClassLinking) { + opts.addPrefix("-XX:+AOTClassLinking"); + } CDSTestUtils.createArchiveAndCheck(opts); // run with archive diff --git a/test/hotspot/jtreg/runtime/cds/appcds/StaticArchiveWithLambda.java b/test/hotspot/jtreg/runtime/cds/appcds/StaticArchiveWithLambda.java index 9bab98a5d2c..76440c81fcf 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/StaticArchiveWithLambda.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/StaticArchiveWithLambda.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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,7 @@ public static void main(String[] args) throws Exception { "-Xlog:class+load,cds") .setArchiveName(archiveName); CDSTestUtils.createArchiveAndCheck(opts) - .shouldContain("Skipping java/lang/invoke/BoundMethodHandle$Species_LLLL because it is dynamically generated"); + .shouldHaveExitValue(0); // run with archive CDSOptions runOpts = (new CDSOptions()) diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java index 705df07f841..781e0276b27 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java @@ -148,6 +148,7 @@ static void test(boolean dumpWithParallel, boolean execWithParallel, boolean use } else { String pattern = "((Too small maximum heap)" + "|(GC triggered before VM initialization completed)" + + "|(CDS archive has aot-linked classes but the archived heap objects cannot be loaded)" + "|(Initial heap size set to a larger value than the maximum heap size)" + "|(java.lang.OutOfMemoryError)" + "|(Error: A JNI error has occurred, please check your installation and try again))"; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTClassLinkingVMOptions.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTClassLinkingVMOptions.java new file mode 100644 index 00000000000..05fdf7c06d6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTClassLinkingVMOptions.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2024, 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 + * @requires vm.cds + * @requires vm.cds.supports.aot.class.linking + * @requires vm.flagless + * @summary Disable CDS when incompatible options related to AOTClassLinking are used + * @library /test/jdk/lib/testlibrary + * /test/lib + * /test/hotspot/jtreg/runtime/cds/appcds + * /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @build Hello + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar Hello + * @run driver AOTClassLinkingVMOptions + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class AOTClassLinkingVMOptions { + static final String appJar = ClassFileInstaller.getJarPath("app.jar"); + + static int testCaseNum = 0; + static void testCase(String s) { + testCaseNum++; + System.out.println("Test case " + testCaseNum + ": " + s); + } + + public static void main(String[] args) throws Exception { + TestCommon.testDump(appJar, TestCommon.list("Hello"), + "-XX:+AOTClassLinking"); + + testCase("Archived full module graph must be enabled at runtime"); + TestCommon.run("-cp", appJar, "-Djdk.module.validation=1", "Hello") + .assertAbnormalExit("CDS archive has aot-linked classes." + + " It cannot be used when archived full module graph is not used"); + + testCase("Cannot use -Djava.system.class.loader"); + TestCommon.run("-cp", appJar, "-Djava.system.class.loader=dummy", "Hello") + .assertAbnormalExit("CDS archive has aot-linked classes." + + " It cannot be used when the java.system.class.loader property is specified."); + + testCase("Cannot use a different main module"); + TestCommon.run("-cp", appJar, "-Xlog:cds", "-m", "jdk.compiler/com.sun.tools.javac.Main") + .assertAbnormalExit("CDS archive has aot-linked classes." + + " It cannot be used when archived full module graph is not used."); + testCase("Cannot use security manager"); + TestCommon.run("-cp", appJar, "-Xlog:cds", "-Djava.security.manager=allow") + .assertAbnormalExit("CDS archive has aot-linked classes." + + " It cannot be used with -Djava.security.manager=allow."); + TestCommon.run("-cp", appJar, "-Xlog:cds", "-Djava.security.manager=default") + .assertAbnormalExit("CDS archive has aot-linked classes." + + " It cannot be used with -Djava.security.manager=default."); + + // NOTE: tests for ClassFileLoadHook + AOTClassLinking is in + // ../jvmti/ClassFileLoadHookTest.java + + boolean dynamicMode = Boolean.getBoolean("test.dynamic.cds.archive"); + if (!dynamicMode) { + // These tests need to dump the full module graph, which is not possible with + // dynamic dump. + modulePathTests(); + } + } + + static void modulePathTests() throws Exception { + CDSModulePathUtils.init(); + + testCase("Cannot use mis-matched module path"); + String goodModulePath = CDSModulePathUtils.getModulesDir().toString(); + TestCommon.testDump(null, CDSModulePathUtils.getAppClasses(), + "--module-path", goodModulePath, + "-XX:+AOTClassLinking", + "-m", CDSModulePathUtils.MAIN_MODULE); + TestCommon.run("-Xlog:cds", + "--module-path", goodModulePath, + "-m", CDSModulePathUtils.MAIN_MODULE) + .assertNormalExit("Using AOT-linked classes: true"); + + TestCommon.run("-Xlog:cds", + "--module-path", goodModulePath + "/bad", + "-m", CDSModulePathUtils.MAIN_MODULE) + .assertAbnormalExit("CDS archive has aot-linked classes. It cannot be used when archived full module graph is not used."); + + testCase("Cannot use mis-matched --add-modules"); + TestCommon.testDump(null, CDSModulePathUtils.getAppClasses(), + "--module-path", goodModulePath, + "-XX:+AOTClassLinking", + "--add-modules", CDSModulePathUtils.MAIN_MODULE); + TestCommon.run("-Xlog:cds", + "--module-path", goodModulePath, + "--add-modules", CDSModulePathUtils.MAIN_MODULE, + CDSModulePathUtils.MAIN_CLASS) + .assertNormalExit("Using AOT-linked classes: true"); + + TestCommon.run("-Xlog:cds", + "--module-path", goodModulePath + "/bad", + "--add-modules", CDSModulePathUtils.TEST_MODULE, + CDSModulePathUtils.MAIN_CLASS) + .assertAbnormalExit("Mismatched --add-modules module name(s)", + "CDS archive has aot-linked classes. It cannot be used when archived full module graph is not used."); + } +} + +// TODO: enhance and move this class to jdk.test.lib.cds.CDSModulePathUtils + +class CDSModulePathUtils { + private static String TEST_SRC = System.getProperty("test.root"); + private static Path USER_DIR = Paths.get(CDSTestUtils.getOutputDir()); + private static Path SRC_DIR = Paths.get(TEST_SRC, "runtime/cds/appcds/jigsaw/modulepath/src"); + private static Path MODS_DIR = Paths.get("mods"); + + public static String MAIN_MODULE = "com.bars"; + public static String TEST_MODULE = "com.foos"; + + public static String MAIN_CLASS = "com.bars.Main"; + public static String TEST_CLASS = "com.foos.Test"; + private static String appClasses[] = {MAIN_CLASS, TEST_CLASS}; + + private static Path modulesDir; + + // This directory contains all the modular jar files + // $USER_DIR/modules/com.bars.jar + // $USER_DIR/modules/com.foos.jar + static Path getModulesDir() { + return modulesDir; + } + + static String[] getAppClasses() { + return appClasses; + } + + static void init() throws Exception { + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE), + MODS_DIR.resolve(TEST_MODULE), + null); + JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE), + MODS_DIR.resolve(MAIN_MODULE), + MODS_DIR.toString()); + + String PATH_LIBS = "modules"; + modulesDir = Files.createTempDirectory(USER_DIR, PATH_LIBS); + Path mainJar = modulesDir.resolve(MAIN_MODULE + ".jar"); + Path testJar = modulesDir.resolve(TEST_MODULE + ".jar"); + + // modylibs contains both modules com.foos.jar, com.bars.jar + // build com.foos.jar + String classes = MODS_DIR.resolve(TEST_MODULE).toString(); + JarBuilder.createModularJar(testJar.toString(), classes, TEST_CLASS); + + // build com.bars.jar + classes = MODS_DIR.resolve(MAIN_MODULE).toString(); + JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java new file mode 100644 index 00000000000..49544f50032 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2024, 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. + * + */ + +// AOT-linked classes are loaded during VM bootstrap by the C++ class AOTLinkedClassBulkLoader. +// Make sure that the Module, Package, CodeSource and ProtectionDomain of these classes are +// set up properly. + +/* + * @test id=static + * @requires vm.cds.supports.aot.class.linking + * @library /test/jdk/lib/testlibrary /test/lib + * @build InitiatingLoaderTester + * @build BulkLoaderTest + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar BulkLoaderTestApp.jar BulkLoaderTestApp MyUtil InitiatingLoaderTester + * @run driver BulkLoaderTest STATIC + */ + +/* + * @test id=dynamic + * @requires vm.cds.supports.aot.class.linking + * @library /test/jdk/lib/testlibrary /test/lib + * @build InitiatingLoaderTester + * @build BulkLoaderTest + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar BulkLoaderTestApp.jar BulkLoaderTestApp MyUtil InitiatingLoaderTester + * @run driver BulkLoaderTest DYNAMIC + */ + +import java.io.File; +import java.lang.StackWalker.StackFrame; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.Set; +import jdk.test.lib.cds.CDSAppTester; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class BulkLoaderTest { + static final String appJar = ClassFileInstaller.getJarPath("BulkLoaderTestApp.jar"); + static final String mainClass = "BulkLoaderTestApp"; + + public static void main(String[] args) throws Exception { + Tester t = new Tester(); + + // Run with archived FMG loaded + t.run(args); + + // Run with an extra classpath -- archived FMG can still load. + { + String extraVmArgs[] = { + "-cp", + appJar + File.pathSeparator + "foobar.jar" + }; + OutputAnalyzer out = t.productionRun(extraVmArgs); + out.shouldHaveExitValue(0); + } + + // Run without archived FMG -- fail to load + { + String extraVmArgs[] = { + "-Xshare:on", + "-Xlog:cds", + "-Djdk.module.showModuleResolution=true" + }; + t.setCheckExitValue(false); + OutputAnalyzer out = t.productionRun(extraVmArgs); + out.shouldHaveExitValue(1); + out.shouldContain("CDS archive has aot-linked classes. It cannot be used when archived full module graph is not used."); + t.setCheckExitValue(true); + } + } + + static class Tester extends CDSAppTester { + public Tester() { + super(mainClass); + } + + @Override + public String classpath(RunMode runMode) { + return appJar; + } + + @Override + public String[] vmArgs(RunMode runMode) { + return new String[] { + "-Xlog:cds,cds+aot+load", + "-XX:+AOTClassLinking", + }; + } + + @Override + public String[] appCommandLine(RunMode runMode) { + return new String[] { + mainClass, + }; + } + } +} + +class BulkLoaderTestApp { + static String allPerms = "null.*<no principals>.*java.security.Permissions.*,*java.security.AllPermission.*<all permissions>.*<all actions>"; + + public static void main(String args[]) throws Exception { + checkClasses(); + checkInitiatingLoader(); + } + + // Check the ClassLoader/Module/Package/ProtectionDomain/CodeSource of classes that are aot-linked + static void checkClasses() throws Exception { + check(String.class, + "null", // loader + "module java.base", + "package java.lang", + "null", + allPerms); + + check(Class.forName("sun.util.logging.internal.LoggingProviderImpl"), + "null", + "module java.logging", + "package sun.util.logging.internal", + "null", + allPerms); + + + check(javax.tools.FileObject.class, + "^jdk.internal.loader.ClassLoaders[$]PlatformClassLoader@", + "module java.compiler", + "package javax.tools", + "jrt:/java.compiler <no signer certificates>", + "jdk.internal.loader.ClassLoaders[$]PlatformClassLoader.*<no principals>.*java.security.Permissions"); + + check(BulkLoaderTestApp.class, + "jdk.internal.loader.ClassLoaders[$]AppClassLoader@", + "^unnamed module @", + "package ", + "file:.*BulkLoaderTestApp.jar <no signer certificates>", + "jdk.internal.loader.ClassLoaders[$]AppClassLoader.*<no principals>.*java.security.Permissions"); + + check(Class.forName("com.sun.tools.javac.Main"), + "jdk.internal.loader.ClassLoaders[$]AppClassLoader@", + "module jdk.compiler", + "package com.sun.tools.javac", + "jrt:/jdk.compiler <no signer certificates>", + "jdk.internal.loader.ClassLoaders[$]AppClassLoader.*<no principals>.*java.security.Permissions"); + + doit(() -> { + Class<?> lambdaClass = MyUtil.getCallerClass(1); + check(lambdaClass, + "jdk.internal.loader.ClassLoaders[$]AppClassLoader@", + "unnamed module", + "package ", + "file:.*BulkLoaderTestApp.jar <no signer certificates>", + "jdk.internal.loader.ClassLoaders[$]AppClassLoader.*<no principals>.*java.security.Permissions"); + + }); + } + + static void check(Class c, String loader, String module, String pkg, String codeSource, String protectionDomain) { + System.out.println("===================================================================="); + System.out.println(c.getName() + ", loader = " + c.getClassLoader()); + System.out.println(c.getName() + ", module = " + c.getModule()); + System.out.println(c.getName() + ", package = " + c.getPackage()); + System.out.println(c.getName() + ", CS = " + c.getProtectionDomain().getCodeSource()); + System.out.println(c.getName() + ", PD = " + c.getProtectionDomain()); + + expectMatch("" + c.getClassLoader(), loader); + expectMatch("" + c.getModule(), module); + expectSame("" + c.getPackage(), pkg); + expectMatch("" + c.getProtectionDomain().getCodeSource(), codeSource); + expectMatch("" + c.getProtectionDomain(), protectionDomain); + } + + static void expectSame(String a, String b) { + if (!a.equals(b)) { + throw new RuntimeException("Expected \"" + b + "\" but got \"" + a + "\""); + } + } + static void expectMatch(String string, String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.DOTALL).matcher(string); + if (!matcher.find()) { + throw new RuntimeException("Expected pattern \"" + pattern + "\" but got \"" + string + "\""); + } + } + + static void doit(Runnable t) { + t.run(); + } + + static void checkInitiatingLoader() throws Exception { + try { + InitiatingLoaderTester.tryAccess(); + } catch (IllegalAccessError t) { + if (t.getMessage().contains("cannot access class jdk.internal.misc.Unsafe (in module java.base)")) { + System.out.println("Expected exception:"); + t.printStackTrace(System.out); + // Class.forName() should still work. We just can't resolve it in CP entries. + Class<?> c = Class.forName("jdk.internal.misc.Unsafe"); + System.out.println("App loader can still resolve by name: " + c); + return; + } + throw new RuntimeException("Unexpected exception", t); + } + + throw new RuntimeException("Should not have succeeded"); + } +} + +class MyUtil { + // depth is 0-based -- i.e., depth==0 returns the class of the immediate caller of getCallerClass + static Class<?> getCallerClass(int depth) { + // Need to add the frame of the getCallerClass -- so the immediate caller (depth==0) of this method + // is at stack.get(1) == stack.get(depth+1); + StackWalker walker = StackWalker.getInstance( + Set.of(StackWalker.Option.RETAIN_CLASS_REFERENCE, + StackWalker.Option.SHOW_HIDDEN_FRAMES)); + List<StackFrame> stack = walker.walk(s -> s.limit(depth+2).collect(Collectors.toList())); + return stack.get(depth+1).getDeclaringClass(); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/InitiatingLoaderTester.jasm b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/InitiatingLoaderTester.jasm new file mode 100644 index 00000000000..ae1b38e20a9 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/InitiatingLoaderTester.jasm @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024, 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. + * + */ + +/* + + +class InitiatingLoaderTester { + public static Object tryAccess() { + return jdk.internal.misc.Unsafe.getUnsafe(); + } +} + + + +*/ + + +super class InitiatingLoaderTester + version 66:0 +{ + Method "<init>":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."<init>":"()V"; + return; + } + public static Method tryAccess:"()Ljava/lang/Object;" + stack 2 locals 0 + { + invokestatic Method jdk/internal/misc/Unsafe."getUnsafe":"()Ljdk/internal/misc/Unsafe;"; + areturn; + } + +} // end Class InitiatingLoaderTester diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java index f5975569447..1603d8430b2 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -27,7 +27,7 @@ * @bug 8214781 8293187 * @summary Test for the -XX:ArchiveHeapTestClass flag * @requires vm.debug == true & vm.cds.write.archived.java.heap - * @modules java.base/sun.invoke.util java.logging + * @modules java.logging * @library /test/jdk/lib/testlibrary /test/lib * /test/hotspot/jtreg/runtime/cds/appcds * /test/hotspot/jtreg/runtime/cds/appcds/test-classes @@ -35,12 +35,13 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar * CDSTestClassA CDSTestClassA$XX CDSTestClassA$YY * CDSTestClassB CDSTestClassC CDSTestClassD - * CDSTestClassE CDSTestClassF CDSTestClassG + * CDSTestClassE CDSTestClassF CDSTestClassG CDSTestClassG$MyEnum CDSTestClassG$Wrapper * pkg.ClassInPackage * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar Hello * @run driver ArchiveHeapTestClass */ +import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.Platform; import jdk.test.lib.helpers.ClassFileInstaller; import jdk.test.lib.process.OutputAnalyzer; @@ -151,19 +152,24 @@ static void testDebugBuild() throws Exception { output = dumpBootAndHello(CDSTestClassD_name); mustFail(output, "Unable to find the static T_OBJECT field CDSTestClassD::archivedObjects"); - testCase("Use a disallowed class: in unnamed module but not in unname package"); - output = dumpBootAndHello(CDSTestClassE_name); - mustFail(output, "Class pkg.ClassInPackage not allowed in archive heap"); + if (!CDSTestUtils.isAOTClassLinkingEnabled()) { + testCase("Use a disallowed class: in unnamed module but not in unname package"); + output = dumpBootAndHello(CDSTestClassE_name); + mustFail(output, "Class pkg.ClassInPackage not allowed in archive heap"); - testCase("Use a disallowed class: not in java.base module"); - output = dumpBootAndHello(CDSTestClassF_name); - mustFail(output, "Class java.util.logging.Level not allowed in archive heap"); - - if (false) { // JDK-8293187 - testCase("sun.invoke.util.Wrapper"); - output = dumpBootAndHello(CDSTestClassG_name); - mustSucceed(output); + testCase("Use a disallowed class: not in java.base module"); + output = dumpBootAndHello(CDSTestClassF_name); + mustFail(output, "Class java.util.logging.Level not allowed in archive heap"); } + + testCase("Complex enums"); + output = dumpBootAndHello(CDSTestClassG_name, "-XX:+AOTClassLinking", "-Xlog:cds+class=debug"); + mustSucceed(output); + + TestCommon.run("-Xbootclasspath/a:" + bootJar, "-cp", appJar, "-Xlog:cds+heap,cds+init", + CDSTestClassG_name) + .assertNormalExit("init subgraph " + CDSTestClassG_name, + "Initialized from CDS"); } } @@ -171,12 +177,27 @@ class CDSTestClassA { static final String output = "CDSTestClassA.<clinit> was executed"; static Object[] archivedObjects; static { - archivedObjects = new Object[5]; - archivedObjects[0] = output; - archivedObjects[1] = new CDSTestClassA[0]; - archivedObjects[2] = new YY(); - archivedObjects[3] = new int[0]; - archivedObjects[4] = new int[2][2]; + // The usual convention would be to call this here: + // CDS.initializeFromArchive(CDSTestClassA.class); + // However, the CDS class is not exported to the unnamed module by default, + // and we don't want to use "--add-exports java.base/jdk.internal.misc=ALL-UNNAMED", as + // that would disable the archived full module graph, which will disable + // CDSConfig::is_using_aot_linked_classes(). + // + // Instead, HeapShared::initialize_test_class_from_archive() will set up the + // "archivedObjects" field first, before calling CDSTestClassA.<clinit>. So + // if we see that archivedObjects is magically non-null here, that means + // it has been restored from the CDS archive. + if (archivedObjects == null) { + archivedObjects = new Object[5]; + archivedObjects[0] = output; + archivedObjects[1] = new CDSTestClassA[0]; + archivedObjects[2] = new YY(); + archivedObjects[3] = new int[0]; + archivedObjects[4] = new int[2][2]; + } else { + System.out.println("Initialized from CDS"); + } System.out.println(output); System.out.println("CDSTestClassA module = " + CDSTestClassA.class.getModule()); System.out.println("CDSTestClassA package = " + CDSTestClassA.class.getPackage()); @@ -269,8 +290,143 @@ class CDSTestClassF { class CDSTestClassG { static Object[] archivedObjects; static { - // Not in java.base - archivedObjects = new Object[1]; - archivedObjects[0] = sun.invoke.util.Wrapper.BOOLEAN; + if (archivedObjects == null) { + archivedObjects = new Object[13]; + archivedObjects[0] = Wrapper.BOOLEAN; + archivedObjects[1] = Wrapper.INT.zero(); + archivedObjects[2] = Wrapper.DOUBLE.zero(); + archivedObjects[3] = MyEnum.DUMMY1; + + archivedObjects[4] = Boolean.class; + archivedObjects[5] = Byte.class; + archivedObjects[6] = Character.class; + archivedObjects[7] = Short.class; + archivedObjects[8] = Integer.class; + archivedObjects[9] = Long.class; + archivedObjects[10] = Float.class; + archivedObjects[11] = Double.class; + archivedObjects[12] = Void.class; + } else { + System.out.println("Initialized from CDS"); + } + } + + public static void main(String args[]) { + if (archivedObjects[0] != Wrapper.BOOLEAN) { + throw new RuntimeException("Huh 0"); + } + + if (archivedObjects[1] != Wrapper.INT.zero()) { + throw new RuntimeException("Huh 1"); + } + + if (archivedObjects[2] != Wrapper.DOUBLE.zero()) { + throw new RuntimeException("Huh 2"); + } + + if (archivedObjects[3] != MyEnum.DUMMY1) { + throw new RuntimeException("Huh 3"); + } + + if (MyEnum.BOOLEAN != true) { + throw new RuntimeException("Huh 10.1"); + } + if (MyEnum.BYTE != -128) { + throw new RuntimeException("Huh 10.2"); + } + if (MyEnum.CHAR != 'c') { + throw new RuntimeException("Huh 10.3"); + } + if (MyEnum.SHORT != -12345) { + throw new RuntimeException("Huh 10.4"); + } + if (MyEnum.INT != -123456) { + throw new RuntimeException("Huh 10.5"); + } + if (MyEnum.LONG != 0x1234567890L) { + throw new RuntimeException("Huh 10.6"); + } + if (MyEnum.LONG2 != -0x1234567890L) { + throw new RuntimeException("Huh 10.7"); + } + if (MyEnum.FLOAT != 567891.0f) { + throw new RuntimeException("Huh 10.8"); + } + if (MyEnum.DOUBLE != 12345678905678.890) { + throw new RuntimeException("Huh 10.9"); + } + + checkClass(4, Boolean.class); + checkClass(5, Byte.class); + checkClass(6, Character.class); + checkClass(7, Short.class); + checkClass(8, Integer.class); + checkClass(9, Long.class); + checkClass(10, Float.class); + checkClass(11, Double.class); + checkClass(12, Void.class); + + System.out.println("Success!"); + } + + static void checkClass(int index, Class c) { + if (archivedObjects[index] != c) { + throw new RuntimeException("archivedObjects[" + index + "] should be " + c); + } + } + + // Simplified version of sun.invoke.util.Wrapper + public enum Wrapper { + // wrapperType simple primitiveType simple char emptyArray + BOOLEAN( Boolean.class, "Boolean", boolean.class, "boolean", 'Z', new boolean[0]), + INT ( Integer.class, "Integer", int.class, "int", 'I', new int[0]), + DOUBLE ( Double.class, "Double", double.class, "double", 'D', new double[0]) + ; + + public static final int COUNT = 10; + private static final Object DOUBLE_ZERO = (Double)(double)0; + + private final Class<?> wrapperType; + private final Class<?> primitiveType; + private final char basicTypeChar; + private final String basicTypeString; + private final Object emptyArray; + + Wrapper(Class<?> wtype, + String wtypeName, + Class<?> ptype, + String ptypeName, + char tchar, + Object emptyArray) { + this.wrapperType = wtype; + this.primitiveType = ptype; + this.basicTypeChar = tchar; + this.basicTypeString = String.valueOf(this.basicTypeChar); + this.emptyArray = emptyArray; + } + + public Object zero() { + return switch (this) { + case BOOLEAN -> Boolean.FALSE; + case INT -> (Integer)0; + case DOUBLE -> DOUBLE_ZERO; + default -> null; + }; + } + } + + enum MyEnum { + DUMMY1, + DUMMY2; + + static final boolean BOOLEAN = true; + static final byte BYTE = -128; + static final short SHORT = -12345; + static final char CHAR = 'c'; + static final int INT = -123456; + static final long LONG = 0x1234567890L; + static final long LONG2 = -0x1234567890L; + static final float FLOAT = 567891.0f; + static final double DOUBLE = 12345678905678.890; } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomClassListDump.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomClassListDump.java index 625ef1fbc92..27072bea35e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomClassListDump.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomClassListDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -94,7 +94,7 @@ public static void main(String[] args) throws Exception { .shouldContain("unreg CustomLoadee") .shouldContain("unreg CustomLoadee2") .shouldContain("unreg CustomLoadee3Child") - .shouldContain("unreg OldClass ** unlinked"); + .shouldContain("unreg OldClass old unlinked"); // Use the dumped static archive opts = (new CDSOptions()) diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/addmods/AddmodsOption.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/addmods/AddmodsOption.java index 114dd6b9f3a..9328cc86569 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/addmods/AddmodsOption.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/addmods/AddmodsOption.java @@ -39,7 +39,7 @@ public class AddmodsOption { private static final WhiteBox WB = WhiteBox.getWhiteBox(); - private static final boolean isJVMCISupported = (WB.getBooleanVMFlag("EnableJVMCI") != null); + private static final boolean isJVMCISupported = WB.getBooleanVMFlag("EnableJVMCI"); public static void main(String[] args) throws Exception { final String moduleOption = "jdk.httpserver/sun.net.httpserver.simpleserver.Main"; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/ClassFileLoadHookTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/ClassFileLoadHookTest.java index 5751f62e148..7ccd4e5d312 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/ClassFileLoadHookTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/ClassFileLoadHookTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -96,5 +96,23 @@ public static void main(String[] args) throws Exception { "ClassFileLoadHook", "" + ClassFileLoadHook.TestCaseId.SHARING_ON_CFLH_ON); TestCommon.checkExec(out); + + // JEP 483: if dumped with -XX:+AOTClassLinking, cannot use archive when CFLH is enabled + TestCommon.testDump(appJar, sharedClasses, useWb, "-XX:+AOTClassLinking"); + out = TestCommon.exec(appJar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", useWb, + "-agentlib:SimpleClassFileLoadHook=LoadMe,beforeHook,after_Hook", + "-Xlog:cds", + "ClassFileLoadHook", + "" + ClassFileLoadHook.TestCaseId.SHARING_ON_CFLH_ON); + if (out.contains("Using AOT-linked classes: false (static archive: no aot-linked classes")) { + // JTREG is executed with VM options that do not support -XX:+AOTClassLinking, so + // the static archive was not created with aot-linked classes. + out.shouldHaveExitValue(0); + } else { + out.shouldContain("CDS archive has aot-linked classes. It cannot be used when JVMTI ClassFileLoadHook is in use."); + out.shouldNotHaveExitValue(0); + } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java index 242a78ca024..7581b2367aa 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java @@ -26,15 +26,15 @@ * @test * @bug 8342303 * @summary Test loading of shared old class when another class has been redefined. - * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes /test/hotspot/jtreg/runtime/cds/appcds/jvmti - * @requires vm.cds.write.archived.java.heap + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @requires vm.cds * @requires vm.jvmti + * @run driver RedefineClassHelper * @build jdk.test.whitebox.WhiteBox * OldClassAndRedefineClassApp * @compile ../../test-classes/OldSuper.jasm * ../../test-classes/ChildOldSuper.java * ../../test-classes/Hello.java - * @run driver RedefineClassHelper * @run driver OldClassAndRedefineClass */ @@ -61,8 +61,8 @@ public static void runTest() throws Throwable { String agentCmdArg = "-javaagent:redefineagent.jar"; OutputAnalyzer out = TestCommon.testDump(appJar, sharedClasses, "-Xlog:cds,cds+class=debug"); - out.shouldMatch("klasses.*OldSuper.[*][*].unlinked") - .shouldMatch("klasses.*ChildOldSuper.[*][*].unlinked"); + out.shouldMatch("klasses.*OldSuper.* unlinked") + .shouldMatch("klasses.*ChildOldSuper.* unlinked"); out = TestCommon.exec( appJar, diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java index bc14ec996f5..eeabce69a36 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java @@ -29,12 +29,12 @@ * @library /test/lib * /test/hotspot/jtreg/runtime/cds/appcds * /test/hotspot/jtreg/runtime/cds/appcds/test-classes - * /test/hotspot/jtreg/runtime/cds/appcds/jvmti + * @requires vm.cds * @requires vm.jvmti + * @run driver RedefineClassHelper * @build RedefineBootClassTest * RedefineBootClassApp * BootSuper BootChild - * @run driver RedefineClassHelper * @run driver RedefineBootClassTest */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java index a0c8fa7a448..4518a45651d 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java @@ -29,13 +29,13 @@ * @library /test/lib * /test/hotspot/jtreg/runtime/cds/appcds * /test/hotspot/jtreg/runtime/cds/appcds/test-classes - * /test/hotspot/jtreg/runtime/cds/appcds/jvmti + * @requires vm.cds * @requires vm.jvmti * @compile ../../test-classes/OldSuper.jasm + * @run driver RedefineClassHelper * @build RedefineOldSuperTest * RedefineOldSuperApp * NewChild - * @run driver RedefineClassHelper * @run driver RedefineOldSuperTest */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java index fbdec462e09..acbd0c948be 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java @@ -30,7 +30,7 @@ * @requires vm.jvmti * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds * @run driver RedefineClassHelper - * @build jdk.test.whitebox.WhiteBox jdk.test.lib.compiler.InMemoryJavaCompiler RedefineBasic + * @build jdk.test.whitebox.WhiteBox RedefineBasic * @run driver RedefineBasicTest */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java index 62bd62662a0..039aaef11cd 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java @@ -30,7 +30,7 @@ * @requires vm.jvmti * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds * @run driver RedefineClassHelper - * @build jdk.test.whitebox.WhiteBox jdk.test.lib.compiler.InMemoryJavaCompiler + * @build jdk.test.whitebox.WhiteBox * @compile RedefineRunningMethods_SharedHelper.java * @run driver RedefineRunningMethods_Shared */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java new file mode 100644 index 00000000000..5fb0a30cd61 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @summary AOT resolution of lambda expressions + * @bug 8340836 + * @requires vm.cds + * @requires vm.cds.supports.aot.class.linking + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes/ + * @build AOTLinkedLambdas + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar + * AOTLinkedLambdasApp InitTracker + * IntfWithNoClinit IntfWithNoClinit2 + * IA IB IC ID1 ID2 IE1 IE2 IF1 IF2 IG1 IG2 IH1 IH2 IH3 + * FooA FooB + * BarA BarB BarC + * @run driver AOTLinkedLambdas + */ + +import java.util.function.Supplier; +import static java.util.stream.Collectors.*; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class AOTLinkedLambdas { + static final String classList = "AOTLinkedLambdas.classlist"; + static final String appJar = ClassFileInstaller.getJarPath("app.jar"); + static final String mainClass = AOTLinkedLambdasApp.class.getName(); + + public static void main(String[] args) throws Exception { + CDSTestUtils.dumpClassList(classList, "-cp", appJar, mainClass) + .assertNormalExit(output -> { + output.shouldContain("Hello AOTLinkedLambdasApp"); + }); + + CDSOptions opts = (new CDSOptions()) + .addPrefix("-XX:ExtraSharedClassListFile=" + classList, + "-XX:+AOTClassLinking", + "-Xlog:cds+resolve=trace", + "-Xlog:cds+class=debug", + "-cp", appJar); + + OutputAnalyzer dumpOut = CDSTestUtils.createArchiveAndCheck(opts); + dumpOut.shouldContain("Can aot-resolve Lambda proxy of interface type IA"); + dumpOut.shouldContain("Can aot-resolve Lambda proxy of interface type IB"); + dumpOut.shouldContain("Cannot aot-resolve Lambda proxy of interface type IC"); + dumpOut.shouldContain("Can aot-resolve Lambda proxy of interface type ID2"); + dumpOut.shouldContain("Cannot aot-resolve Lambda proxy of interface type IE2"); // unsupported = IE1 + dumpOut.shouldContain("Cannot aot-resolve Lambda proxy of interface type IF2"); + dumpOut.shouldContain("Cannot aot-resolve Lambda proxy of interface type IG2"); + dumpOut.shouldContain("Cannot aot-resolve Lambda proxy of interface type IH3"); // unsupported = IH1 + + CDSOptions runOpts = (new CDSOptions()) + .setUseVersion(false) + .addPrefix("-Xlog:cds", + "-esa", // see JDK-8340836 + "-cp", appJar) + .addSuffix(mainClass); + + CDSTestUtils.run(runOpts) + .assertNormalExit("Hello AOTLinkedLambdasApp", + "hello, world"); + } +} + +class AOTLinkedLambdasApp { + static { + System.out.println("AOTLinkedLambdasApp.<clinit>"); + } + public static void main(String args[]) { + System.out.println("Hello AOTLinkedLambdasApp"); + + // (1) Simple tests + var words = java.util.List.of("hello", "fuzzy", "world"); + System.out.println(words.stream().filter(w->!w.contains("u")).collect(joining(", "))); + // => hello, world + + // (2) Test for <clinit> order. + testClinitOrder(); + } + + + // Check that aot-linking of lambdas does not cause <clinit> to be skipped or + // otherwise executed in the wrong order. + // + // A lambda is declared to implement an interface X, but it also implicitly + // implements all super interfaces of X. + // + // For any interface IN that's implemented by a lambda, if IN has declared + // a non-abstract, non-static method (JVMS 5.5. Initialization), IN must be + // initialized before the lambda can be linked. If IN::<clinit> exists, the + // initialization of IN can have side effects. + // + // AOTConstantPoolResolver::is_indy_resolution_deterministic() excludes + // any lambda if initializing its interfaces can cause side effects. This test + // checks that such exclusions are working as expected. + // + // This test also proves that is_indy_resolution_deterministic() doen't need to check + // for all other types that are mentioned by the lambda call site, as those classes + // will not be initialized as part of linking the lambda. + static void testClinitOrder() { + /* + * An indy callsite is associated with the following MethodType and MethodHandles: + * + * https://github.com/openjdk/jdk/blob/580eb62dc097efeb51c76b095c1404106859b673/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java#L293-L309 + * + * MethodType factoryType The expected signature of the {@code CallSite}. The + * parameter types represent the types of capture variables; + * the return type is the interface to implement. When + * used with {@code invokedynamic}, this is provided by + * the {@code NameAndType} of the {@code InvokeDynamic} + * + * MethodType interfaceMethodType Signature and return type of method to be + * implemented by the function object. + * + * MethodHandle implementation A direct method handle describing the implementation + * method which should be called (with suitable adaptation + * of argument types and return types, and with captured + * arguments prepended to the invocation arguments) at + * invocation time. + * + * MethodType dynamicMethodType The signature and return type that should + * be enforced dynamically at invocation time. + * In simple use cases this is the same as + * {@code interfaceMethodType}. + */ + + // Initial condition: no <clinit> used by our Foo* and Bar* types have been called. + InitTracker.assertOrder("InitTracker"); + + //============================== + // Case (i) -- Check for types used by factoryType, interfaceMethodType and dynamicMethodType + // (Note: no tests for captured variables in factoryType yet; will be tested in case (ii)) + // factoryType = "()LIntfWithNoClinit; + // interfaceMethodType = "(LFooB;)LFooA;" + // implementation = "REF_invokeStatic AOTLinkedLambdasApp.implAB:(LBarB;)LBarA;" + // dynamicMethodType = "(LBarB;)LBarA;" + IntfWithNoClinit<BarA, BarB> noclinit = AOTLinkedLambdasApp::implAB; + + // None of the Foo? and Bar? types used by the lambda should have been initialized yet, even though + // the indy callsite has been resolved now. + InitTracker.assertOrder("InitTracker"); + + BarB barB = new BarB(); + InitTracker.assertOrder("InitTracker, FooB, BarB"); + BarA barA = noclinit.doit(barB); + System.out.println(barB); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA"); + + //============================== + // Case (ii) -- Check for types used by captured variables in factoryType + BarC barC = null; + IntfWithNoClinit2 noclinit2 = () -> { return barC.hashCode(); }; + try { + noclinit2.doit(); + throw new RuntimeException("NullPointerException should have been thrown"); + } catch (NullPointerException npe) { + // expected + } + // BarC shouldn't be initialized as no instances of it has been created. + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA"); + + + //============================== + // (IA) No default methods -- is not initialized during lambda linking. Lambda can be archived. + IA ia = () -> {}; + ia.doit(); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA"); + System.out.println(IA._dummy); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA"); + + //============================== + // (IB) Has default method but has not <clinit> -- OK to initialize IB during lambda linking. Lambda can be archived. + IB ib = () -> {}; + ib.doit(); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA"); + + //============================== + // (IC) Has both default method and <clinit> -- cannot AOT link the lambda + IC ic = () -> {}; + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC"); + ic.doit(); + + //============================== + // ID1 - has default method, but no <clinit> + // ID2 - has <clinit>, but no default method + ID2 id2 = () -> {}; + id2.doit(); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC"); + System.out.println(ID2._dummy); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2"); + + //============================== + // IE1 - has both default method and <clinit> + // IE2 - has <clinit>, but no default method + IE2 ie2 = () -> {}; + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2, IE1"); + System.out.println(IE2._dummy); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2, IE1, IE2"); + + //============================== + // IF1 - has <clinit>, but no default method + // IF2 - has both default method and <clinit> + IF2 if2 = () -> {}; + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2, IE1, IE2, IF2"); + System.out.println(IF1._dummy); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2, IE1, IE2, IF2, IF1"); + + //============================== + // IG1 - has both default method and <clinit> + // IG2 - has both default method and <clinit> + IG2 ig2 = () -> {}; + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2, IE1, IE2, IF2, IF1, IG1, IG2"); + + //============================== + // Similar to IE1/IE2, but IH3 is one more level away from IH1 + // IH1 - has both default method and <clinit> + // IH2 - has <clinit>, but no default method + // IH3 - has <clinit>, but no default method + IH3 ih3 = () -> {}; + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2, IE1, IE2, IF2, IF1, IG1, IG2, IH1"); + System.out.println(IH3._dummy); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2, IE1, IE2, IF2, IF1, IG1, IG2, IH1, IH3"); + System.out.println(IH2._dummy); + InitTracker.assertOrder("InitTracker, FooB, BarB, FooA, BarA, IA, IC, ID2, IE1, IE2, IF2, IF1, IG1, IG2, IH1, IH3, IH2"); + } + + static BarA implAB(BarB param) { + return new BarA(param); + } +} + + +// An interface with no <clinit> method. A lambda implementing this +// interface can be AOT-linked. +@FunctionalInterface +interface IntfWithNoClinit<X extends FooA, Y extends FooB> { + X doit(Y param); +} + +// Another interface with no <clinit> method. A lambda implementing this +// interface can be AOT-linked. +@FunctionalInterface +interface IntfWithNoClinit2 { + int doit(); +} + + +// (IA) No default methods -- is not initialized during lambda linking. Lambda can be archived. +@FunctionalInterface interface IA { + static int _dummy = InitTracker.trackEvent("IA"); + void doit(); +} + +// (IB) Has default method but has not <clinit> -- OK to initialize IB during lambda linking. Lambda can be archived. +@FunctionalInterface interface IB { + default int dummy() { return 0; } + void doit(); +} + +// (IC) Has both default method and <clinit> -- cannot AOT link the lambda +@FunctionalInterface interface IC { + static int _dummy = InitTracker.trackEvent("IC"); + default int dummy() { return _dummy; } + void doit(); +} + +// (ID1/ID2) +@FunctionalInterface interface ID1 { // has default method, but no <clinit> + default int dummy() { return 0; } + void doit(); +} + +@FunctionalInterface interface ID2 extends ID1 { // has <clinit>, but no default method + static int _dummy = InitTracker.trackEvent("ID2"); +} + +// (IE1/IE2) +@FunctionalInterface interface IE1 { // has default method and <clinit> + static int _dummy = InitTracker.trackEvent("IE1"); + default int dummy() { return _dummy; } + void doit(); +} + +@FunctionalInterface interface IE2 extends IE1 { // has <clinit>, but no default method + static int _dummy = InitTracker.trackEvent("IE2"); +} + +// (IF1/IF2) +@FunctionalInterface interface IF1 { // has <clinit>, but no default method + static int _dummy = InitTracker.trackEvent("IF1"); + void doit(); +} + +@FunctionalInterface interface IF2 extends IF1 { // has default method and <clinit> + static int _dummy = InitTracker.trackEvent("IF2"); + default int dummy() { return 0; } +} + +// (IG1/IG2) +@FunctionalInterface interface IG1 { // has default method and <clinit> + static int _dummy = InitTracker.trackEvent("IG1"); + default int dummy() { return _dummy; } + void doit(); +} + +@FunctionalInterface interface IG2 extends IG1 { // has default method and <clinit> + static int _dummy = InitTracker.trackEvent("IG2"); + default int dummy() { return _dummy; } +} + +// (IH1/IH2/IH3) +@FunctionalInterface interface IH1 { // has default method and <clinit> + static int _dummy = InitTracker.trackEvent("IH1"); + default int dummy() { return _dummy; } + void doit(); +} + +@FunctionalInterface interface IH2 extends IH1 { // has <clinit> but no default method + static int _dummy = InitTracker.trackEvent("IH2"); +} + +@FunctionalInterface interface IH3 extends IH2 { // has <clinit> but no default method + static int _dummy = InitTracker.trackEvent("IH3"); +} + + +class InitTracker { + static String actualOrder = "InitTracker"; + static int trackEvent(String event) { + actualOrder += ", " + event; + return actualOrder.lastIndexOf(','); + } + static void assertOrder(String wantOrder) { + System.out.println("wantOrder = " + wantOrder); + System.out.println("actualOrder = " + actualOrder); + if (!actualOrder.equals(wantOrder)) { + throw new RuntimeException("Want <clinit> order: {" + wantOrder + "}, but got {" + actualOrder + "}"); + } + } +} + +interface FooA { + static final int _dummy = InitTracker.trackEvent("FooA"); + default int dummy() { return _dummy; } +} + +interface FooB { + static final int _dummy = InitTracker.trackEvent("FooB"); + default int dummy() { return _dummy; } +} + +class BarA implements FooA { + static {InitTracker.trackEvent("BarA");} + BarA(BarB dummy) {} +} + +class BarB implements FooB { + static {InitTracker.trackEvent("BarB");} +} + +class BarC { + static {InitTracker.trackEvent("BarC");} +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java new file mode 100644 index 00000000000..2098ebc2c71 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @summary AOT resolution of VarHandle invocation + * @bug 8343245 + * @requires vm.cds + * @requires vm.cds.supports.aot.class.linking + * @library /test/lib + * @build AOTLinkedVarHandles + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar + * AOTLinkedVarHandlesApp AOTLinkedVarHandlesApp$Data + * @run driver AOTLinkedVarHandles + */ + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class AOTLinkedVarHandles { + static final String classList = "AOTLinkedVarHandles.classlist"; + static final String appJar = ClassFileInstaller.getJarPath("app.jar"); + static final String mainClass = AOTLinkedVarHandlesApp.class.getName(); + + public static void main(String[] args) throws Exception { + CDSTestUtils.dumpClassList(classList, "-cp", appJar, mainClass) + .assertNormalExit(output -> { + output.shouldContain("Hello AOTLinkedVarHandlesApp"); + }); + + CDSOptions opts = (new CDSOptions()) + .addPrefix("-XX:ExtraSharedClassListFile=" + classList, + "-XX:+AOTClassLinking", + "-Xlog:cds+resolve=trace", + "-Xlog:cds+class=debug", + "-cp", appJar); + + String s = "archived method CP entry.* AOTLinkedVarHandlesApp "; + OutputAnalyzer dumpOut = CDSTestUtils.createArchiveAndCheck(opts); + dumpOut.shouldMatch(s + "java/lang/invoke/VarHandle.compareAndExchangeAcquire:\\(\\[DIDI\\)D =>"); + dumpOut.shouldMatch(s + "java/lang/invoke/VarHandle.get:\\(\\[DI\\)D => "); + + CDSOptions runOpts = (new CDSOptions()) + .setUseVersion(false) + .addPrefix("-Xlog:cds", + "-esa", + "-cp", appJar) + .addSuffix(mainClass); + + CDSTestUtils.run(runOpts) + .assertNormalExit("Hello AOTLinkedVarHandlesApp"); + } +} + +class AOTLinkedVarHandlesApp { + static final VarHandle initialized; + static final VarHandle lazy; + static long longField = 5678; + static long seed; + + static { + try { + lazy = MethodHandles.lookup().findStaticVarHandle(Data.class, "longField", long.class); + initialized = MethodHandles.lookup().findStaticVarHandle(AOTLinkedVarHandlesApp.class, "longField", long.class); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + static class Data { + static long longField = seed; + } + + public static void main(String args[]) { + seed = 1234; + System.out.println("Hello AOTLinkedVarHandlesApp"); + long a = (long) lazy.get(); + long b = (long) initialized.get(); + System.out.println(a); + System.out.println(b); + if (a != 1234) { + throw new RuntimeException("Data class should not be initialized: " + a); + } + if (b != 5678) { + throw new RuntimeException("VarHandle.get() failed: " + b); + } + + VarHandle vh = MethodHandles.arrayElementVarHandle(double[].class); + double[] array = new double[] {1.0}; + int index = 0; + int v = 4; + + // JDK-8343245 -- this generates "java.lang.invoke.LambdaForm$VH/0x80????" hidden class + double r = (double) vh.compareAndExchangeAcquire(array, index, 1.0, v); + if (r != 1.0) { + throw new RuntimeException("Unexpected result: " + r); + } + r = (double) vh.get(array, index); + if (r != 4.0) { + throw new RuntimeException("Unexpected result: " + r); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java index 474fa65d6ea..7d3335b9db6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java @@ -24,26 +24,40 @@ /* * @test - * @summary Dump time resolutiom of constant pool entries. + * @summary Dump time resolution of constant pool entries. * @requires vm.cds + * @requires vm.cds.supports.aot.class.linking * @requires vm.compMode != "Xcomp" - * @library /test/lib + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes/ + * @build OldProvider OldClass OldConsumer StringConcatTestOld * @build ResolvedConstants - * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar ResolvedConstantsApp ResolvedConstantsFoo ResolvedConstantsBar + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar + * ResolvedConstantsApp ResolvedConstantsFoo ResolvedConstantsBar + * MyInterface InterfaceWithClinit NormalClass + * OldProvider OldClass OldConsumer SubOfOldClass + * StringConcatTest StringConcatTestOld * @run driver ResolvedConstants */ +import java.util.function.Consumer; import jdk.test.lib.cds.CDSOptions; import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; public class ResolvedConstants { static final String classList = "ResolvedConstants.classlist"; static final String appJar = ClassFileInstaller.getJarPath("app.jar"); static final String mainClass = ResolvedConstantsApp.class.getName(); + static boolean aotClassLinking; public static void main(String[] args) throws Exception { - // dump class list + test(false); + test(true); + } + + static void test(boolean testMode) throws Exception { + aotClassLinking = testMode; CDSTestUtils.dumpClassList(classList, "-cp", appJar, mainClass) .assertNormalExit(output -> { output.shouldContain("Hello ResolvedConstantsApp"); @@ -52,78 +66,109 @@ public static void main(String[] args) throws Exception { CDSOptions opts = (new CDSOptions()) .addPrefix("-XX:ExtraSharedClassListFile=" + classList, "-cp", appJar, - "-Xlog:cds+resolve=trace"); - CDSTestUtils.createArchiveAndCheck(opts) + "-Xlog:cds+resolve=trace", + "-Xlog:cds+class=debug"); + if (aotClassLinking) { + opts.addPrefix("-XX:+AOTClassLinking"); + } else { + opts.addPrefix("-XX:-AOTClassLinking"); + } + + OutputAnalyzer out = CDSTestUtils.createArchiveAndCheck(opts); // Class References --- // Always resolve reference when a class references itself - .shouldMatch("cds,resolve.*archived klass.* ResolvedConstantsApp app => ResolvedConstantsApp app") + out.shouldMatch(ALWAYS("klass.* ResolvedConstantsApp app => ResolvedConstantsApp app")) // Always resolve reference when a class references a super class - .shouldMatch("cds,resolve.*archived klass.* ResolvedConstantsApp app => java/lang/Object boot") - .shouldMatch("cds,resolve.*archived klass.* ResolvedConstantsBar app => ResolvedConstantsFoo app") + .shouldMatch(ALWAYS("klass.* ResolvedConstantsApp app => java/lang/Object boot")) + .shouldMatch(ALWAYS("klass.* ResolvedConstantsBar app => ResolvedConstantsFoo app")) // Always resolve reference when a class references a super interface - .shouldMatch("cds,resolve.*archived klass.* ResolvedConstantsApp app => java/lang/Runnable boot") + .shouldMatch(ALWAYS("klass.* ResolvedConstantsApp app => java/lang/Runnable boot")) - // java/lang/System is in the root loader but ResolvedConstantsApp is loaded by the app loader. - // Even though System is in the vmClasses list, when ResolvedConstantsApp looks up - // "java/lang/System" in its ConstantPool, the app loader may not have resolved the System - // class yet (i.e., there's no initiaited class entry for System in the app loader's dictionary) - .shouldMatch("cds,resolve.*reverted klass.* ResolvedConstantsApp .*java/lang/System") + // Without -XX:+AOTClassLinking: + // java/lang/System is in the boot loader but ResolvedConstantsApp is loaded by the app loader. + // Even though System is in the vmClasses list, when ResolvedConstantsApp looks up + // "java/lang/System" in its ConstantPool, the app loader may not have resolved the System + // class yet (i.e., there's no initiaited class entry for System in the app loader's dictionary) + .shouldMatch(AOTLINK_ONLY("klass.* ResolvedConstantsApp .*java/lang/System")) // Field References --- // Always resolve references to fields in the current class or super class(es) - .shouldMatch("cds,resolve.*archived field.* ResolvedConstantsBar => ResolvedConstantsBar.b:I") - .shouldMatch("cds,resolve.*archived field.* ResolvedConstantsBar => ResolvedConstantsBar.a:I") - .shouldMatch("cds,resolve.*archived field.* ResolvedConstantsBar => ResolvedConstantsFoo.a:I") + .shouldMatch(ALWAYS("field.* ResolvedConstantsBar => ResolvedConstantsBar.b:I")) + .shouldMatch(ALWAYS("field.* ResolvedConstantsBar => ResolvedConstantsBar.a:I")) + .shouldMatch(ALWAYS("field.* ResolvedConstantsBar => ResolvedConstantsFoo.a:I")) + .shouldMatch(ALWAYS("field.* ResolvedConstantsFoo => ResolvedConstantsFoo.a:I")) - // Do not resolve field references to child classes - .shouldMatch("cds,resolve.*archived field.* ResolvedConstantsFoo => ResolvedConstantsFoo.a:I") - .shouldMatch("cds,resolve.*reverted field.* ResolvedConstantsFoo ResolvedConstantsBar.a:I") - .shouldMatch("cds,resolve.*reverted field.* ResolvedConstantsFoo ResolvedConstantsBar.b:I") + // Resolve field references to child classes ONLY when using -XX:+AOTClassLinking + .shouldMatch(AOTLINK_ONLY("field.* ResolvedConstantsFoo => ResolvedConstantsBar.a:I")) + .shouldMatch(AOTLINK_ONLY("field.* ResolvedConstantsFoo => ResolvedConstantsBar.b:I")) - // Do not resolve field references to unrelated classes - .shouldMatch("cds,resolve.*reverted field.* ResolvedConstantsApp ResolvedConstantsBar.a:I") - .shouldMatch("cds,resolve.*reverted field.* ResolvedConstantsApp ResolvedConstantsBar.b:I") + // Resolve field references to unrelated classes ONLY when using -XX:+AOTClassLinking + .shouldMatch(AOTLINK_ONLY("field.* ResolvedConstantsApp => ResolvedConstantsBar.a:I")) + .shouldMatch(AOTLINK_ONLY("field.* ResolvedConstantsApp => ResolvedConstantsBar.b:I")) // Method References --- // Should resolve references to own constructor - .shouldMatch("cds,resolve.*archived method .* ResolvedConstantsApp ResolvedConstantsApp.<init>:") + .shouldMatch(ALWAYS("method.* ResolvedConstantsApp ResolvedConstantsApp.<init>:")) // Should resolve references to super constructor - .shouldMatch("cds,resolve.*archived method .* ResolvedConstantsApp java/lang/Object.<init>:") + .shouldMatch(ALWAYS("method.* ResolvedConstantsApp java/lang/Object.<init>:")) // Should resolve interface methods in VM classes - .shouldMatch("cds,resolve.*archived interface method .* ResolvedConstantsApp java/lang/Runnable.run:") + .shouldMatch(ALWAYS("interface method .* ResolvedConstantsApp java/lang/Runnable.run:")) // Should resolve references to own non-static method (private or public) - .shouldMatch("archived method.*: ResolvedConstantsBar ResolvedConstantsBar.doBar:") - .shouldMatch("archived method.*: ResolvedConstantsApp ResolvedConstantsApp.privateInstanceCall:") - .shouldMatch("archived method.*: ResolvedConstantsApp ResolvedConstantsApp.publicInstanceCall:") + .shouldMatch(ALWAYS("method.*: ResolvedConstantsBar ResolvedConstantsBar.doBar:")) + .shouldMatch(ALWAYS("method.*: ResolvedConstantsApp ResolvedConstantsApp.privateInstanceCall:")) + .shouldMatch(ALWAYS("method.*: ResolvedConstantsApp ResolvedConstantsApp.publicInstanceCall:")) // Should not resolve references to static method - .shouldNotMatch(" archived method CP entry.*: ResolvedConstantsApp ResolvedConstantsApp.staticCall:") + .shouldNotMatch(ALWAYS("method.*: ResolvedConstantsApp ResolvedConstantsApp.staticCall:")) // Should resolve references to method in super type - .shouldMatch(" archived method CP entry.*: ResolvedConstantsBar ResolvedConstantsFoo.doBar:") + .shouldMatch(ALWAYS("method.*: ResolvedConstantsBar ResolvedConstantsFoo.doBar:")) - // App class cannot resolve references to methods in boot classes: + // Without -XX:+AOTClassLinking App class cannot resolve references to methods in boot classes: // When the app class loader tries to resolve a class X that's normally loaded by // the boot loader, it's possible for the app class loader to get a different copy of // X (by using MethodHandles.Lookup.defineClass(), etc). Therefore, let's be on // the side of safety and revert all such references. - // - // This will be addressed in JDK-8315737. - .shouldMatch("reverted method.*: ResolvedConstantsApp java/io/PrintStream.println:") - .shouldMatch("reverted method.*: ResolvedConstantsBar java/lang/Class.getName:") + .shouldMatch(AOTLINK_ONLY("method.*: ResolvedConstantsApp java/io/PrintStream.println:")) + .shouldMatch(AOTLINK_ONLY("method.*: ResolvedConstantsBar java/lang/Class.getName:")) - // Should not resolve methods in unrelated classes. - .shouldMatch("reverted method.*: ResolvedConstantsApp ResolvedConstantsBar.doit:") + // Resole resolve methods in unrelated classes ONLY when using -XX:+AOTClassLinking + .shouldMatch(AOTLINK_ONLY("method.*: ResolvedConstantsApp ResolvedConstantsBar.doit:")) // End --- ; + + + // Indy References --- + if (aotClassLinking) { + out.shouldContain("Cannot aot-resolve Lambda proxy because OldConsumer is excluded") + .shouldContain("Cannot aot-resolve Lambda proxy because OldProvider is excluded") + .shouldContain("Cannot aot-resolve Lambda proxy because OldClass is excluded") + .shouldContain("Cannot aot-resolve Lambda proxy of interface type InterfaceWithClinit") + .shouldMatch("klasses.* app *NormalClass[$][$]Lambda/.* hidden aot-linked inited") + .shouldNotMatch("klasses.* app *SubOfOldClass[$][$]Lambda/") + .shouldMatch("archived indy *CP entry.*StringConcatTest .* => java/lang/invoke/StringConcatFactory.makeConcatWithConstants") + .shouldNotMatch("archived indy *CP entry.*StringConcatTestOld .* => java/lang/invoke/StringConcatFactory.makeConcatWithConstants"); + } + } + + static String ALWAYS(String s) { + return "cds,resolve.*archived " + s; + } + + static String AOTLINK_ONLY(String s) { + if (aotClassLinking) { + return ALWAYS(s); + } else { + return "cds,resolve.*reverted " + s; + } } } @@ -142,12 +187,98 @@ public static void main(String args[]) { bar.a ++; bar.b ++; bar.doit(); + + testLambda(); + StringConcatTest.test(); + StringConcatTestOld.main(null); } private static void staticCall() {} private void privateInstanceCall() {} public void publicInstanceCall() {} public void run() {} + + static void testLambda() { + // The functional type used in the Lambda is an excluded class + OldProvider op = () -> { + return null; + }; + + // A captured value is an instance of an excluded Class + OldClass c = new OldClass(); + Runnable r = () -> { + System.out.println("Test 1 " + c); + }; + r.run(); + + // The functional interface accepts an argument that's an excluded class + MyInterface i = (o) -> { + System.out.println("Test 2 " + o); + }; + i.dispatch(c); + + // Method reference to old class + OldConsumer oldConsumer = new OldConsumer(); + Consumer<String> wrapper = oldConsumer::consumeString; + wrapper.accept("Hello"); + + // Lambda of interfaces that have <clinit> are not archived. + InterfaceWithClinit i2 = () -> { + System.out.println("Test 3"); + }; + i2.dispatch(); + + // These two classes have almost identical source code, but + // only NormalClass should have its lambdas pre-resolved. + // SubOfOldClass is "old" -- it should be excluded from the AOT cache, + // so none of its lambda proxies should be cached + NormalClass.testLambda(); // Lambda proxy should be cached + SubOfOldClass.testLambda(); // Lambda proxy shouldn't be cached + } +} + +class StringConcatTest { + static void test() { + System.out.println("StringConcatTest <concat> " + new StringConcatTest()); // concat should be aot-resolved + } +} + +/* see StringConcatTestOld.jasm + +class StringConcatTestOld { + public static void main(String args[]) { + // concat should be aot-resolved => the MethodType refers to an old class + System.out.println("StringConcatTestOld <concat> " + new OldConsumer()); + } +} +*/ + +class NormalClass { + static void testLambda() { + Runnable r = () -> { + System.out.println("NormalClass testLambda"); + }; + r.run(); + } +} + +class SubOfOldClass extends OldClass { + static void testLambda() { + Runnable r = () -> { + System.out.println("SubOfOldClass testLambda"); + }; + r.run(); + } +} + +interface MyInterface { + void dispatch(OldClass c); +} + +interface InterfaceWithClinit { + static final long X = System.currentTimeMillis(); + void dispatch(); + default long dummy() { return X; } } class ResolvedConstantsFoo { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/StringConcatTestOld.jasm b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/StringConcatTestOld.jasm new file mode 100644 index 00000000000..76460cad0a3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/StringConcatTestOld.jasm @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024, 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. + * + */ + +/* + +decompiled from + +class OldConsumer {} + +class StringConcatTestOld { + public static void main(String args[]) { + System.out.println("StringConcatTestOld <concat> " + new OldConsumer()); + } +} + + +(1) Comment out this line + + invokestatic Method java/lang/String.valueOf:"(Ljava/lang/Object;)Ljava/lang/String;"; + +(2) Change the MethodType parameter of makeConcatWithConstants from + + "(Ljava/lang/String;)Ljava/lang/String;" + -> + + "(LOldConsumer;)Ljava/lang/String;" + +*/ + +super class StringConcatTestOld + version 67:0 +{ + Method "<init>":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."<init>":"()V"; + return; + } + public static Method main:"([Ljava/lang/String;)V" + stack 3 locals 1 + { + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + new class OldConsumer; + dup; + invokespecial Method OldConsumer."<init>":"()V"; + //invokestatic Method java/lang/String.valueOf:"(Ljava/lang/Object;)Ljava/lang/String;"; + invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(LOldConsumer;)Ljava/lang/String;" { + String "StringConcatTestOld <concat> " + }; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; + return; + } + + public static final InnerClass Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles; + +} // end Class StringConcatTestOld diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/OldConsumer.jasm b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/OldConsumer.jasm new file mode 100644 index 00000000000..bffb5a27381 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/OldConsumer.jasm @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024, 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. + * + */ +super class OldConsumer + version 49:0 +{ + + +Method "<init>":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."<init>":"()V"; + return; +} + +public Method consumeString:"(Ljava/lang/String;)V" + stack 3 locals 2 +{ + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + new class java/lang/StringBuilder; + dup; + invokespecial Method java/lang/StringBuilder."<init>":"()V"; + ldc String "Hello: "; + invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; + aload_1; + invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; + invokevirtual Method java/lang/StringBuilder.toString:"()Ljava/lang/String;"; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; + return; +} + +} // end Class OldConsumer diff --git a/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java b/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java index 129d34bd2db..58891d09e02 100644 --- a/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java +++ b/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test ClassResolutionTest - * @bug 8144874 + * @bug 8144874 8343633 * @requires vm.flagless * @modules java.base/jdk.internal.misc * @library /test/lib @@ -36,6 +36,10 @@ import java.lang.ref.WeakReference; import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + public class ClassResolutionTest { public static class ClassResolutionTestMain { @@ -57,6 +61,15 @@ public static void main(String... args) throws Exception { } } + public static void checkOutput(String file, String decorators) throws Exception { + List<String> allLines = Files.readAllLines(Path.of(file)); + for (String line : allLines) { + if (!line.contains(decorators)) { + throw new RuntimeException("Logging should contain decorators " + decorators); + } + } + } + public static void main(String... args) throws Exception { // (1) class+resolve should turn on. @@ -74,6 +87,15 @@ public static void main(String... args) throws Exception { o = new OutputAnalyzer(pb.start()); o.shouldHaveExitValue(0); o.shouldNotContain("[class,resolve]"); + + // (3) Test perf+class+link writes to a file, not tty. + pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:perf+class+link:output.log", + ClassResolutionTestMain.class.getName()); + o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); + o.shouldNotContain("[perf,class,link]"); + + checkOutput("output.log", "[perf,class,link]"); }; } diff --git a/test/hotspot/jtreg/runtime/logging/FoldMultilinesTest.java b/test/hotspot/jtreg/runtime/logging/FoldMultilinesTest.java index 8df835245c8..e9a7bbc6496 100644 --- a/test/hotspot/jtreg/runtime/logging/FoldMultilinesTest.java +++ b/test/hotspot/jtreg/runtime/logging/FoldMultilinesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -41,7 +41,7 @@ public class FoldMultilinesTest { private static String XLOG_BASE = "-Xlog:exceptions=info:"; private static String EXCEPTION_MESSAGE = "line 1\nline 2\\nstring"; private static String FOLDED_EXCEPTION_MESSAGE = "line 1\\nline 2\\\\nstring"; - private static Pattern NEWLINE_LOG_PATTERN = Pattern.compile("line 1\\Rline 2\\\\nstring", Pattern.MULTILINE); + private static Pattern NEWLINE_LOG_PATTERN = Pattern.compile("line 1\\R\\[\\s+\\] line 2\\\\nstring", Pattern.MULTILINE); private static String getLog(String out, OutputAnalyzer output) throws Exception { return switch (out) { diff --git a/test/hotspot/jtreg/runtime/logging/ProtectionDomainVerificationTest.java b/test/hotspot/jtreg/runtime/logging/ProtectionDomainVerificationTest.java deleted file mode 100644 index e8e5c881125..00000000000 --- a/test/hotspot/jtreg/runtime/logging/ProtectionDomainVerificationTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2016, 2024, 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 ProtectionDomainVerificationTest - * @bug 8149064 - * @requires vm.flagless - * @modules java.base/jdk.internal.misc - * @library /test/lib - * @run driver ProtectionDomainVerificationTest - */ - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.Platform; -import jdk.test.lib.process.ProcessTools; - -public class ProtectionDomainVerificationTest { - - public static void main(String... args) throws Exception { - - // -Xlog:protectiondomain=trace - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:protectiondomain=trace", - "-Xmx128m", - "-Djava.security.manager=allow", - Hello.class.getName(), "security_manager"); - new OutputAnalyzer(pb.start()) - .shouldHaveExitValue(0) - .shouldContain("[protectiondomain] Checking package access") - .shouldContain("[protectiondomain] adding protection domain that can access class"); - - // -Xlog:protectiondomain=debug - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:protectiondomain=debug", - "-Xmx128m", - "-Djava.security.manager=allow", - Hello.class.getName(), "security_manager"); - new OutputAnalyzer(pb.start()) - .shouldHaveExitValue(0) - .shouldContain("[protectiondomain] Checking package access") - .shouldNotContain("[protectiondomain] adding protection domain that can access class"); - - // -Xlog:protectiondomain=debug - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:protectiondomain=trace", - "-Xmx128m", - "-Djava.security.manager=disallow", - Hello.class.getName()); - new OutputAnalyzer(pb.start()) - .shouldHaveExitValue(0) - .shouldNotContain("[protectiondomain] Checking package access") - .shouldNotContain("pd set count = #"); - } - - public static class Hello { - public static void main(String[] args) { - if (args.length == 1) { - // Need a security manager to trigger logging. - System.setSecurityManager(new SecurityManager()); - } - System.out.print("Hello!"); - } - } -} diff --git a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java index 714c05174eb..34c8900e616 100644 --- a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java +++ b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java @@ -30,7 +30,6 @@ * @modules java.compiler * java.instrument * @requires vm.jvmti - * @build jdk.test.lib.compiler.InMemoryJavaCompiler * @run main RedefineClassHelper * @run main/othervm -Xmx256m -XX:MaxMetaspaceSize=64m -javaagent:redefineagent.jar -Xlog:all=trace:file=all.log RedefineClasses */ diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/DictionaryStatsTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/DictionaryStatsTest.java index 29223efb8ee..50b6b53233e 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/vm/DictionaryStatsTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/DictionaryStatsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -67,14 +67,6 @@ public class DictionaryStatsTest { // Variance of bucket size : 0.281 // Std. dev. of bucket size: 0.530 // Maximum bucket size : 2 - // ProtectionDomainCacheTable statistics: - // Number of buckets : 1009 = 8072 bytes, each 8 - // Number of entries : 0 = 0 bytes, each 0 - // Total footprint : = 8072 bytes - // Average bucket size : 0.000 - // Variance of bucket size : 0.000 - // Std. dev. of bucket size: 0.000 - // Maximum bucket size : 0 public void run(CommandExecutor executor) throws ClassNotFoundException { @@ -99,10 +91,6 @@ public void run(CommandExecutor executor) throws ClassNotFoundException { output.shouldContain("Std. dev. of bucket size"); output.shouldContain("Maximum bucket size"); output.shouldMatch("LoaderConstraintTable statistics:"); - // Would be nice to run this with "-Djava.security.manager=allow" - // so the numbers aren't 0 (running make with VM_OPTIONS allowing - // security manager does get 12 entries in this table.) - output.shouldMatch("ProtectionDomainCacheTable statistics:"); // what is this? Reference.reachabilityFence(named_cl); diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLineNumbers.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLineNumbers.java index 5d9c3982fb6..87e664ef308 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLineNumbers.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLineNumbers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -35,6 +35,7 @@ /** * @test + * @bug 8214226 8243500 * @requires vm.hasSA * @requires os.arch=="amd64" | os.arch=="x86_64" * @requires os.family=="windows" | os.family == "linux" | os.family == "mac" @@ -53,7 +54,7 @@ * * The test works by spawning a process that sits in a 10 line loop in the busywork() method, * all while the main test does repeated jstacks on the process. The expectation is - * that at least 5 of the lines in the busywork() loop will eventually show up in at + * that at least 4 of the lines in the busywork() loop will eventually show up in at * least one of the jstack runs. */ @@ -94,8 +95,11 @@ public static void main(String... args) { public class TestJhsdbJstackLineNumbers { // This is the number of lines in the busywork main loop static final int TOTAL_BUSYWORK_LOOP_LINES = 10; - // The minimum number of lines that we must at some point see in the jstack output - static final int MIN_BUSYWORK_LOOP_LINES = 5; + // The minimum number of lines that we must see at some point in the jstack output. + // There's always a chance we could see fewer, but the chances are so low that + // it is unlikely to ever happen. We can always decrease the odds by lowering + // the required number of lines or increasing the number of jstack runs. + static final int MIN_BUSYWORK_LOOP_LINES = 4; static final int MAX_NUMBER_OF_JSTACK_RUNS = 25; diff --git a/test/jdk/ProblemList-AotJdk.txt b/test/jdk/ProblemList-AotJdk.txt new file mode 100644 index 00000000000..9030ba60c78 --- /dev/null +++ b/test/jdk/ProblemList-AotJdk.txt @@ -0,0 +1,11 @@ +java/math/BigInteger/largeMemory/DivisionOverflow.java 0000000 generic-all +java/math/BigInteger/largeMemory/StringConstructorOverflow.java 0000000 generic-all + +jdk/internal/misc/CDS/ArchivedEnumTest.java 0000000 generic-all + +java/lang/module/ModuleDescriptorHashCodeTest.java 0000000 generic-all + + +# The test case is incorrect. There's no guarantee that running a JVM with the following +# parameters will always cause the class java/lang/invoke/MethodHandleStatics to be initialized +java/lang/invoke/DumpMethodHandleInternals.java 0000000 generic-all diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index a87ab372da2..702a426df0a 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -707,7 +707,6 @@ javax/swing/JComboBox/TestComboBoxComponentRendering.java 8309734 linux-all # This test fails on macOS 14 javax/swing/plaf/synth/7158712/bug7158712.java 8324782 macosx-all -javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java 8316151 macosx-all ############################################################################ diff --git a/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java b/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java index 16fbccdafd1..919ea72a494 100644 --- a/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java +++ b/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java @@ -21,17 +21,6 @@ * questions. */ -/* - @test - @key headful - @bug 6190768 6190778 - @summary Tests that triggering events on AWT list by pressing CTRL + HOME, - CTRL + END, PG-UP, PG-DOWN similar Motif behavior - @library /test/lib - @build jdk.test.lib.Platform - @run main KeyEventsTest -*/ - import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.KeyboardFocusManager; @@ -50,6 +39,17 @@ import jdk.test.lib.Platform; +/* + * @test + * @key headful + * @bug 6190768 6190778 + * @requires os.family != "mac" + * @summary Tests that triggering events on AWT list by pressing CTRL + HOME, + * CTRL + END, PG-UP, PG-DOWN similar Motif behavior + * @library /test/lib + * @build jdk.test.lib.Platform + * @run main KeyEventsTest + */ public class KeyEventsTest { TestState currentState; final Object LOCK = new Object(); @@ -261,13 +261,7 @@ private void test(TestState currentState) throws Exception { private void doTest() throws Exception { - boolean isWin = false; - if (Platform.isWindows()) { - isWin = true; - } else if (Platform.isOSX()) { - System.out.println("Not for OS X"); - return; - } + boolean isWin = Platform.isWindows(); System.out.println("multiple? selectedMoved? ?scrollMoved keyID? template? action?"); test(new TestState(false, false, false, KeyEvent.VK_PAGE_UP, isWin?false:false)); diff --git a/test/jdk/java/awt/Robot/ScreenCaptureRobotTest.java b/test/jdk/java/awt/Robot/ScreenCaptureRobotTest.java new file mode 100644 index 00000000000..944636ebf2a --- /dev/null +++ b/test/jdk/java/awt/Robot/ScreenCaptureRobotTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.GraphicsEnvironment; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; + +/* + * @test + * @key headful + * @bug 8342098 + * @summary Verify that the image captured from the screen using a Robot + * and the source image are same. + * @run main/othervm -Dsun.java2d.uiScale=1 ScreenCaptureRobotTest + */ +public class ScreenCaptureRobotTest { + + private static final int IMAGE_WIDTH = 200; + private static final int IMAGE_HEIGHT = 100; + private static final int OFFSET = 10; + + private static Frame frame; + private static Canvas canvas; + + private static BufferedImage realImage; + + private static volatile Point point; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(ScreenCaptureRobotTest::initializeGUI); + doTest(); + } finally { + EventQueue.invokeAndWait(ScreenCaptureRobotTest::disposeFrame); + } + } + + private static void initializeGUI() { + frame = new Frame("ScreenCaptureRobotTest Frame"); + realImage = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice() + .getDefaultConfiguration() + .createCompatibleImage(IMAGE_WIDTH, IMAGE_HEIGHT); + + Graphics g = realImage.createGraphics(); + g.setColor(Color.YELLOW); + g.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); + g.setColor(Color.RED); + g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 20)); + g.drawString("Capture This", 10, 40); + g.dispose(); + + canvas = new ImageCanvas(); + canvas.setBackground(Color.YELLOW); + canvas.setPreferredSize(new Dimension(IMAGE_WIDTH + (OFFSET * 2), + IMAGE_HEIGHT + (OFFSET * 2))); + frame.setLayout(new BorderLayout()); + frame.add(canvas); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void doTest() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + EventQueue.invokeAndWait(() -> point = canvas.getLocationOnScreen()); + + Rectangle rect = new Rectangle(point.x + OFFSET, point.y + OFFSET, + IMAGE_WIDTH, IMAGE_HEIGHT); + + BufferedImage capturedImage = robot.createScreenCapture(rect); + + if (!compareImages(capturedImage, realImage)) { + String errorMessage = "FAIL : Captured Image is different from " + + "the real image"; + saveImage(capturedImage, "CapturedImage.png"); + saveImage(realImage, "RealImage.png"); + throw new RuntimeException(errorMessage); + } + } + + private static boolean compareImages(BufferedImage capturedImg, + BufferedImage realImg) { + int capturedPixel; + int realPixel; + int imgWidth = capturedImg.getWidth(); + int imgHeight = capturedImg.getHeight(); + + if (imgWidth != IMAGE_WIDTH || imgHeight != IMAGE_HEIGHT) { + System.out.println("Captured and real images are different in size"); + return false; + } + + for (int i = 0; i < imgWidth; i++) { + for (int j = 0; j < imgHeight; j++) { + capturedPixel = capturedImg.getRGB(i, j); + realPixel = realImg.getRGB(i, j); + if (capturedPixel != realPixel) { + System.out.println("Captured pixel (" + + Integer.toHexString(capturedPixel) + ") at " + + "(" + i + ", " + j + ") is not equal to real pixel (" + + Integer.toHexString(realPixel) + ")"); + return false; + } + } + } + return true; + } + + private static class ImageCanvas extends Canvas { + @Override + public void paint(Graphics g) { + g.drawImage(realImage, OFFSET, OFFSET, this); + } + } + + private static void saveImage(BufferedImage image, String fileName) { + try { + ImageIO.write(image, "png", new File(fileName)); + } catch (IOException ignored) { + System.err.println(ignored.getMessage()); + } + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + } + } +} diff --git a/test/jdk/java/awt/im/memoryleak/InputContextMemoryLeakTest.java b/test/jdk/java/awt/im/memoryleak/InputContextMemoryLeakTest.java index f04b635f9e7..2b933d8e223 100644 --- a/test/jdk/java/awt/im/memoryleak/InputContextMemoryLeakTest.java +++ b/test/jdk/java/awt/im/memoryleak/InputContextMemoryLeakTest.java @@ -61,10 +61,12 @@ public void run() { button = new JButton("Test"); p1.add(button); frame.add(p1); - text = new WeakReference<JTextField>(new JTextField("Text")); - p = new WeakReference<JPanel>(new JPanel(new FlowLayout())); - p.get().add(text.get()); - frame.add(p.get()); + JTextField tf = new JTextField("Text"); + text = new WeakReference<JTextField>(tf); + JPanel jp = new JPanel(new FlowLayout()); + p = new WeakReference<JPanel>(jp); + jp.add(tf); + frame.add(jp); frame.setBounds(500, 400, 200, 200); frame.setVisible(true); } @@ -79,13 +81,19 @@ public void run() { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { + // after this the JTextField as well as the JPanel + // are eligible to be GC'd frame.remove(p.get()); } }); Util.waitForIdle(null); //After the next caret blink it automatically TextField references - Thread.sleep(text.get().getCaret().getBlinkRate() * 2); + JTextField tf = text.get(); + if (tf != null) { + Thread.sleep(tf.getCaret().getBlinkRate() * 2); + tf = null; // allow to be GCed + } Util.waitForIdle(null); try { diff --git a/test/jdk/java/foreign/largestub/TestLargeStub.java b/test/jdk/java/foreign/largestub/TestLargeStub.java index e4dcb325c8f..13b635c7343 100644 --- a/test/jdk/java/foreign/largestub/TestLargeStub.java +++ b/test/jdk/java/foreign/largestub/TestLargeStub.java @@ -33,10 +33,14 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.stream.Stream; import static org.junit.jupiter.params.provider.Arguments.arguments; @@ -76,9 +80,17 @@ public void testDowncallAllowHeap() { @MethodSource("layouts") public void testUpcall(ValueLayout layout, int numSlots) { // Link a handle with a large number of arguments, to try and overflow the code buffer - Linker.nativeLinker().downcallHandle( - FunctionDescriptor.of(STRUCT_LL, - Stream.generate(() -> layout).limit(UPCALL_AVAILABLE_SLOTS / numSlots).toArray(MemoryLayout[]::new))); + try (Arena arena = Arena.ofConfined()) { + Linker.nativeLinker().upcallStub( + MethodHandles.empty(MethodType.methodType(MemorySegment.class, + Stream.generate(() -> layout).limit(UPCALL_AVAILABLE_SLOTS / numSlots) + .map(ValueLayout::carrier) + .toArray(Class<?>[]::new))), + FunctionDescriptor.of(STRUCT_LL, + Stream.generate(() -> layout).limit(UPCALL_AVAILABLE_SLOTS / numSlots) + .toArray(MemoryLayout[]::new)), + arena); + } } private static Stream<Arguments> layouts() { diff --git a/test/jdk/java/io/IO/IO.java b/test/jdk/java/io/IO/IO.java index 328c189fb2f..e4da1742030 100644 --- a/test/jdk/java/io/IO/IO.java +++ b/test/jdk/java/io/IO/IO.java @@ -21,6 +21,7 @@ * questions. */ +import java.io.Writer; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; @@ -33,6 +34,7 @@ import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; @@ -48,7 +50,7 @@ /* * @test - * @bug 8305457 + * @bug 8305457 8342936 * @summary java.io.IO tests * @library /test/lib * @run junit IO @@ -131,22 +133,26 @@ public void inputTestInteractive(String console, String prompt) throws Exception var testSrc = System.getProperty("test.src", "."); var command = new ArrayList<String>(); command.add(expect.toString()); - command.add(Path.of(testSrc, "input.exp").toAbsolutePath().toString()); + String expectInputName = PROMPT_NONE.equals(prompt) ? "input-no-prompt" + : "input"; + command.add(Path.of(testSrc, expectInputName + ".exp").toAbsolutePath().toString()); command.add(System.getProperty("test.jdk") + "/bin/java"); command.add("--enable-preview"); if (console != null) command.add("-Djdk.console=" + console); command.add(Path.of(testSrc, "Input.java").toAbsolutePath().toString()); - command.add(prompt == null ? "0" : "1"); + command.add(prompt == null ? "0" : PROMPT_NONE.equals(prompt) ? "2" : "1"); command.add(String.valueOf(prompt)); OutputAnalyzer output = ProcessTools.executeProcess(command.toArray(new String[]{})); output.reportDiagnosticSummary(); assertEquals(0, output.getExitValue()); } + private static final String PROMPT_NONE = "prompt-none"; + public static Stream<Arguments> args() { // cross product: consoles x prompts - return Stream.of(null, "gibberish").flatMap(console -> Stream.of(null, "?", "%s") + return Stream.of(null, "gibberish").flatMap(console -> Stream.of(null, "?", "%s", PROMPT_NONE) .map(prompt -> new String[]{console, prompt}).map(Arguments::of)); } } @@ -172,6 +178,33 @@ public void printTest(String mode) throws Exception { out.substring(out.length() / 2)); } + @Test //JDK-8342936 + public void printlnNoParamsTest() throws Exception { + var file = Path.of("PrintlnNoParams.java"); + try (Writer w = Files.newBufferedWriter(file)) { + w.write(""" + void main() { + print("1 "); + print("2 "); + print("3 "); + println(); + System.console().print("1 "); + System.console().print("2 "); + System.console().print("3 "); + System.console().println(); + } + """); + } + var pb = ProcessTools.createTestJavaProcessBuilder("--enable-preview", file.toString()); + OutputAnalyzer output = ProcessTools.executeProcess(pb); + assertEquals(0, output.getExitValue()); + assertTrue(output.getStderr().isEmpty()); + output.reportDiagnosticSummary(); + String out = output.getStdout(); + String nl = System.getProperty("line.separator"); + assertEquals("1 2 3 " + nl + "1 2 3 " + nl, out); + } + @ParameterizedTest @ValueSource(strings = {"println", "print", "input"}) diff --git a/test/jdk/java/io/IO/Input.java b/test/jdk/java/io/IO/Input.java index 1bc03c8bb8a..1a62fb77166 100644 --- a/test/jdk/java/io/IO/Input.java +++ b/test/jdk/java/io/IO/Input.java @@ -28,9 +28,11 @@ public class Input { public static void main(String[] args) throws IOException { - if (args[0].equals("0")) - System.out.print(readln(null)); - else - System.out.print(readln(args[1])); + switch (args[0]) { + case "0" -> System.out.print(readln(null)); + case "1" -> System.out.print(readln(args[1])); + case "2" -> System.out.print(readln()); + default -> throw new AssertionError("Unknown command: " + args[0]); + } } } diff --git a/test/jdk/java/io/IO/input-no-prompt.exp b/test/jdk/java/io/IO/input-no-prompt.exp new file mode 100644 index 00000000000..20cd481912b --- /dev/null +++ b/test/jdk/java/io/IO/input-no-prompt.exp @@ -0,0 +1,30 @@ +# +# Copyright (c) 2024, 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. +# + +set prompt [lindex $argv $argc-1] +set stty_init "rows 24 cols 80" +set timeout -1 + +spawn {*}$argv +send "hello\r" +expect eof diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index e1e2cef9a8a..68b3ab56b6d 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -32,7 +32,6 @@ * @summary Basic tests for Process and Environment Variable code * @modules java.base/java.lang:open * java.base/java.io:open - * java.base/jdk.internal.misc * @requires !vm.musl * @requires vm.flagless * @library /test/lib @@ -2676,17 +2675,6 @@ static void THROWS(Class<? extends Throwable> k, Fun... fs) { else unexpected(t);}} static boolean isLocked(BufferedInputStream bis) throws Exception { - Field lockField = BufferedInputStream.class.getDeclaredField("lock"); - lockField.setAccessible(true); - var lock = (jdk.internal.misc.InternalLock) lockField.get(bis); - if (lock != null) { - if (lock.tryLock()) { - lock.unlock(); - return false; - } else { - return true; - } - } return new Thread() { volatile boolean unlocked; diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenBlocking.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenBlocking.java index 5e15ea083e4..b68496bc7db 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenBlocking.java +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenBlocking.java @@ -28,7 +28,7 @@ * @requires vm.debug != true * @modules jdk.management * @library /test/lib - * @run main/othervm GetStackTraceALotWhenBlocking 500000 + * @run main/othervm/timeout=300 GetStackTraceALotWhenBlocking 100000 */ /* @@ -68,16 +68,24 @@ public static void main(String[] args) throws Exception { var thread1 = Thread.ofVirtual().start(task); var thread2 = Thread.ofVirtual().start(task); + long lastTime = System.nanoTime(); try { for (int i = 1; i <= iterations; i++) { - if ((i % 10_000) == 0) { - System.out.format("%s => %d of %d%n", Instant.now(), i, iterations); - } - thread1.getStackTrace(); pause(); thread2.getStackTrace(); pause(); + + long currentTime = System.nanoTime(); + if (i == iterations || ((currentTime - lastTime) > 1_000_000_000L)) { + System.out.format("%s => %d of %d%n", Instant.now(), i, iterations); + lastTime = currentTime; + } + + if (Thread.currentThread().isInterrupted()) { + // fail quickly if interrupted by jtreg + throw new RuntimeException("interrupted"); + } } } finally { done.set(true); diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java index 260446a1e3d..9d9d3eddce1 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java @@ -28,7 +28,7 @@ * @requires vm.debug != true * @modules jdk.management * @library /test/lib - * @run main/othervm --enable-native-access=ALL-UNNAMED GetStackTraceALotWhenPinned 500000 + * @run main/othervm/timeout=300 --enable-native-access=ALL-UNNAMED GetStackTraceALotWhenPinned 100000 */ /* @@ -36,7 +36,7 @@ * @requires vm.debug == true * @modules jdk.management * @library /test/lib - * @run main/othervm/timeout=300 --enable-native-access=ALL-UNNAMED GetStackTraceALotWhenPinned 200000 + * @run main/othervm/timeout=300 --enable-native-access=ALL-UNNAMED GetStackTraceALotWhenPinned 50000 */ import java.time.Instant; @@ -78,7 +78,7 @@ public static void main(String[] args) throws Exception { } }); - long lastTimestamp = System.currentTimeMillis(); + long lastTime = System.nanoTime(); for (int i = 1; i <= iterations; i++) { // wait for virtual thread to arrive barrier.await(); @@ -86,10 +86,15 @@ public static void main(String[] args) throws Exception { thread.getStackTrace(); LockSupport.unpark(thread); - long currentTime = System.currentTimeMillis(); - if (i == iterations || ((currentTime - lastTimestamp) > 500)) { + long currentTime = System.nanoTime(); + if (i == iterations || ((currentTime - lastTime) > 1_000_000_000L)) { System.out.format("%s => %d of %d%n", Instant.now(), i, iterations); - lastTimestamp = currentTime; + lastTime = currentTime; + } + + if (Thread.currentThread().isInterrupted()) { + // fail quickly if interrupted by jtreg + throw new RuntimeException("interrupted"); } } } diff --git a/test/jdk/java/lang/invoke/lambda/LambdaHiddenCaller.java b/test/jdk/java/lang/invoke/lambda/LambdaHiddenCaller.java new file mode 100644 index 00000000000..aed19e6ca17 --- /dev/null +++ b/test/jdk/java/lang/invoke/lambda/LambdaHiddenCaller.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.Serializable; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.function.IntSupplier; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/* + * @test + * @bug 8343064 + * @summary Test about when lambda caller/target class is a hidden class + * @run junit LambdaHiddenCaller + */ +public class LambdaHiddenCaller { + static Hooks hiddenCaller; + + @BeforeAll + static void setup() throws Throwable { + byte[] bytes; + try (var in = LambdaHiddenCaller.class.getResourceAsStream("HiddenHooks.class")) { + bytes = in.readAllBytes(); + } + var hiddenClassLookup = MethodHandles.lookup().defineHiddenClass(bytes, true); + hiddenCaller = (Hooks) hiddenClassLookup.findConstructor(hiddenClassLookup.lookupClass(), MethodType.methodType(void.class)) + .asType(MethodType.methodType(Hooks.class)).invokeExact(); + } + + @Test + void testStaticMethod() { + var is = hiddenCaller.callStaticMethodLambda(); + assertEquals(42, is.getAsInt()); + } + + @Test + void testSerializableLambda() { + var is = hiddenCaller.callSerializableLambda(); + assertEquals(42, is.getAsInt()); + assertTrue(Serializable.class.isAssignableFrom(is.getClass())); + // We do not guarantee serialization functionalities yet + } +} + +/** + * Hooks to call hidden class methods easily. + */ +interface Hooks { + IntSupplier callStaticMethodLambda(); + + IntSupplier callSerializableLambda(); +} + +class HiddenHooks implements Hooks { + private static int compute() { + return 42; + } + + @Override + public IntSupplier callStaticMethodLambda() { + return HiddenHooks::compute; + } + + @Override + public IntSupplier callSerializableLambda() { + return (IntSupplier & Serializable) HiddenHooks::compute; + } +} \ No newline at end of file diff --git a/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java b/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java index fd148d37785..33f18a4e533 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java +++ b/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -33,7 +33,7 @@ * @library /test/lib * @modules jdk.management * @build CollectionUsageThreshold MemoryUtil RunUtil - * @requires vm.opt.ExplicitGCInvokesConcurrent == "false" | vm.opt.ExplicitGCInvokesConcurrent == "null" + * @requires (vm.opt.ExplicitGCInvokesConcurrent == "false" | vm.opt.ExplicitGCInvokesConcurrent == "null") & vm.compMode != "Xcomp" * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/timeout=300 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CollectionUsageThreshold diff --git a/test/jdk/java/lang/module/ClassFileVersionsTest.java b/test/jdk/java/lang/module/ClassFileVersionsTest.java index 849a56301a1..1ffc5878651 100644 --- a/test/jdk/java/lang/module/ClassFileVersionsTest.java +++ b/test/jdk/java/lang/module/ClassFileVersionsTest.java @@ -31,10 +31,13 @@ * @summary Test parsing of module-info.class with different class file versions */ +import java.lang.classfile.ClassFile; import java.lang.module.InvalidModuleDescriptorException; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Requires.Modifier; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import static java.lang.module.ModuleDescriptor.Requires.Modifier.*; @@ -46,6 +49,8 @@ import static org.testng.Assert.*; public class ClassFileVersionsTest { + private static final int PREVIEW_MINOR_VERSION = + ClassFile.PREVIEW_MINOR_VERSION; private static final int FEATURE; static { FEATURE = Runtime.version().feature(); @@ -56,26 +61,34 @@ public class ClassFileVersionsTest { @DataProvider(name = "supported") public Object[][] supported() { /* - * There are four test cases for JDK 9 and then one test case + * There are four test cases for JDK 9, one test case * for each subsequent JDK version from JDK 10 to the current - * feature release for a total of (4 + (FEATURE - 9) ) => - * (feature - 5) rows. + * feature release, and two tests for the current release with + * a preview flag set, for a total of (4 + (FEATURE - 9) + 2) + * rows. */ - Object[][] result = new Object[(FEATURE - 5)][]; + List<Object[]> result = new ArrayList<>(4 + (FEATURE - 9) + 2); // Class file version of JDK 9 is 53.0 - result[0] = new Object[]{ 53, 0, Set.of()}; - result[1] = new Object[]{ 53, 0, Set.of(STATIC) }; - result[2] = new Object[]{ 53, 0, Set.of(TRANSITIVE) }; - result[3] = new Object[]{ 53, 0, Set.of(STATIC, TRANSITIVE) }; + result.add(new Object[]{ 53, 0, Set.of()}); + result.add(new Object[]{ 53, 0, Set.of(STATIC) }); + result.add(new Object[]{ 53, 0, Set.of(TRANSITIVE) }); + result.add(new Object[]{ 53, 0, Set.of(STATIC, TRANSITIVE) }); // Major class file version of JDK N is 44 + n. Create rows // for JDK 10 through FEATURE. - for (int i = 4; i < (FEATURE - 5) ; i++) { - result[i] = new Object[]{i + 50, 0, Set.of()}; + for (int i = 10; i <= FEATURE; i++) { + result.add(new Object[]{ 44 + i, 0, Set.of()}); } - return result; + result.add(new Object[]{ 44 + FEATURE, + PREVIEW_MINOR_VERSION, + Set.of()}); + result.add(new Object[]{ 44 + FEATURE, + PREVIEW_MINOR_VERSION, + Set.of(TRANSITIVE) }); + + return result.toArray(s -> new Object[s][]); } // major, minor, modifiers for requires java.base @@ -84,27 +97,34 @@ public Object[][] unsupported() { /* * There are three test cases for releases prior to JDK 9, * three test cases for each JDK version from JDK 10 to the - * current feature release, plus one addition test case for - * the next release for a total of (3 + (FEATURE - 9) * 3 + 1) + * current feature release, two tests for the current release with + * the preview flag set, plus one addition test case for + * the next release for a total of (3 + (FEATURE - 9) * 3 + 2 + 1) * rows. */ - int unsupportedCount = 3 + (FEATURE - 9)*3 + 1; - Object[][] result = new Object[unsupportedCount][]; + List<Object[]> result = new ArrayList<>(3 + (FEATURE - 9) * 3 + 2 + 1); - result[0] = new Object[]{50, 0, Set.of()}; // JDK 6 - result[1] = new Object[]{51, 0, Set.of()}; // JDK 7 - result[2] = new Object[]{52, 0, Set.of()}; // JDK 8 + result.add(new Object[]{50, 0, Set.of()}); // JDK 6 + result.add(new Object[]{51, 0, Set.of()}); // JDK 7 + result.add(new Object[]{52, 0, Set.of()}); // JDK 8 for (int i = 10; i <= FEATURE ; i++) { - int base = 3 + (i-10)*3; // Major class file version of JDK N is 44+n - result[base] = new Object[]{i + 44, 0, Set.of(STATIC)}; - result[base + 1] = new Object[]{i + 44, 0, Set.of(TRANSITIVE)}; - result[base + 2] = new Object[]{i + 44, 0, Set.of(STATIC, TRANSITIVE)}; + result.add(new Object[]{i + 44, 0, Set.of(STATIC)}); + result.add(new Object[]{i + 44, 0, Set.of(TRANSITIVE)}); + result.add(new Object[]{i + 44, 0, Set.of(STATIC, TRANSITIVE)}); } - result[unsupportedCount - 1] = new Object[]{FEATURE+1+44, 0, Set.of()}; - return result; + result.add(new Object[]{FEATURE + 44, + PREVIEW_MINOR_VERSION, + Set.of(STATIC)}); + result.add(new Object[]{FEATURE + 44, + PREVIEW_MINOR_VERSION, + Set.of(STATIC, TRANSITIVE)}); + + result.add(new Object[]{FEATURE+1+44, 0, Set.of()}); + + return result.toArray(s -> new Object[s][]); } @Test(dataProvider = "supported") diff --git a/test/jdk/java/lang/module/ModuleDescriptorTest.java b/test/jdk/java/lang/module/ModuleDescriptorTest.java index c9267f3db3d..c46bb4a1e9e 100644 --- a/test/jdk/java/lang/module/ModuleDescriptorTest.java +++ b/test/jdk/java/lang/module/ModuleDescriptorTest.java @@ -61,6 +61,8 @@ import jdk.internal.access.JavaLangModuleAccess; import jdk.internal.access.SharedSecrets; import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFileVersion; +import java.lang.classfile.ClassTransform; import java.lang.classfile.attribute.ModuleAttribute; import java.lang.constant.PackageDesc; import java.lang.constant.ModuleDesc; @@ -1522,4 +1524,68 @@ public void testToString() { assertTrue(s.contains("p1")); } + @Test(expectedExceptions = InvalidModuleDescriptorException.class) + public void testRequiresTransitiveJavaBaseNotPermitted1() throws Exception { + ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo") + .requires(Set.of(Modifier.TRANSITIVE), "java.base") + .build(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ModuleInfoWriter.write(descriptor, baos); + ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray()); + + ModuleDescriptor.read(bb, () -> Set.of("p", "q")); + } + + @Test(expectedExceptions = InvalidModuleDescriptorException.class) + public void testRequiresTransitiveJavaBaseNotPermitted2() throws Exception { + ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo") + .requires(Set.of(Modifier.TRANSITIVE), "java.base") + .build(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ModuleInfoWriter.write(descriptor, baos); + byte[] bytecode = baos.toByteArray(); + ByteBuffer bb = ByteBuffer.wrap(bytecode); + setClassFileVersion(bb, ClassFile.JAVA_21_VERSION, -1); + + ModuleDescriptor.read(bb, () -> Set.of("p", "q")); + } + + public void testRequiresTransitiveJavaBasePermitted() throws Exception { + ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo") + .requires(Set.of(Modifier.TRANSITIVE), "java.base") + .build(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ModuleInfoWriter.write(descriptor, baos); + byte[] bytecode = baos.toByteArray(); + ByteBuffer bb = ByteBuffer.wrap(bytecode); + setClassFileVersion(bb, -1, ClassFile.PREVIEW_MINOR_VERSION); + + descriptor = ModuleDescriptor.read(bb, () -> Set.of("p", "q")); + + assertEquals(descriptor.requires().size(), 1); + Requires javaBase = descriptor.requires().iterator().next(); + assertEquals(javaBase.name(), "java.base"); + assertEquals(javaBase.modifiers(), Set.of(Modifier.TRANSITIVE)); + } + + /**Change the classfile versions of the provided classfile to the provided + * values. + * + * @param bytecode the classfile content to modify + * @param major the major classfile version to set, + * -1 if the existing version should be kept + * @param minor the minor classfile version to set, + * -1 if the existing version should be kept + */ + private void setClassFileVersion(ByteBuffer bb, int major, int minor) { + if (minor != (-1)) { + bb.putShort(4, (short) minor); + } + if (major != (-1)) { + bb.putShort(6, (short) major); + } + } } diff --git a/test/jdk/java/net/Socket/asyncClose/Socket_getInputStream_read.java b/test/jdk/java/net/Socket/asyncClose/Socket_getInputStream_read.java index f2082fcf374..812541c9daa 100644 --- a/test/jdk/java/net/Socket/asyncClose/Socket_getInputStream_read.java +++ b/test/jdk/java/net/Socket/asyncClose/Socket_getInputStream_read.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -60,7 +60,7 @@ public void run() { } latch.countDown(); int n = in.read(); - failed("Socket.getInputStream().read() returned unexpectedly!!"); + failed("Socket.getInputStream().read() returned unexpectedly, n=" + n); } catch (SocketException se) { if (latch.getCount() != 1) { closed(); @@ -77,20 +77,22 @@ public void run() { public AsyncCloseTest go() { try { InetAddress lh = InetAddress.getLocalHost(); - ServerSocket ss = new ServerSocket(0, 0, lh); - s.connect( new InetSocketAddress(lh, ss.getLocalPort()) ); - Socket s2 = ss.accept(); - Thread thr = new Thread(this); - thr.start(); - latch.await(); - Thread.sleep(5000); //sleep, so Socket.getInputStream().read() can block - s.close(); - thr.join(); + try (ServerSocket ss = new ServerSocket(0, 0, lh)) { + s.connect(new InetSocketAddress(lh, ss.getLocalPort())); + try (Socket s2 = ss.accept()) { + Thread thr = new Thread(this); + thr.start(); + latch.await(); + Thread.sleep(5000); //sleep, so Socket.getInputStream().read() can block + s.close(); + thr.join(); + } - if (isClosed()) { - return passed(); - } else { - return failed("Socket.getInputStream().read() wasn't preempted"); + if (isClosed()) { + return passed(); + } else { + return failed("Socket.getInputStream().read() wasn't preempted"); + } } } catch (Exception x) { failed(x.getMessage()); diff --git a/test/jdk/java/net/Socket/asyncClose/Socket_getOutputStream_write.java b/test/jdk/java/net/Socket/asyncClose/Socket_getOutputStream_write.java index dc5eda06078..6a967ebcf8d 100644 --- a/test/jdk/java/net/Socket/asyncClose/Socket_getOutputStream_write.java +++ b/test/jdk/java/net/Socket/asyncClose/Socket_getOutputStream_write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,20 +66,22 @@ public void run() { public AsyncCloseTest go() { try { InetAddress lh = InetAddress.getLocalHost(); - ServerSocket ss = new ServerSocket(0, 0, lh); - s.connect( new InetSocketAddress(lh, ss.getLocalPort()) ); - Socket s2 = ss.accept(); - Thread thr = new Thread(this); - thr.start(); - latch.await(); - Thread.sleep(1000); - s.close(); - thr.join(); + try (ServerSocket ss = new ServerSocket(0, 0, lh)) { + s.connect(new InetSocketAddress(lh, ss.getLocalPort())); + try (Socket s2 = ss.accept()) { + Thread thr = new Thread(this); + thr.start(); + latch.await(); + Thread.sleep(1000); + s.close(); + thr.join(); + } - if (isClosed()) { - return passed(); - } else { - return failed("Socket.getOutputStream().write() wasn't preempted"); + if (isClosed()) { + return passed(); + } else { + return failed("Socket.getOutputStream().write() wasn't preempted"); + } } } catch (Exception x) { failed(x.getMessage()); diff --git a/test/jdk/java/net/URLPermission/nstest/LookupTest.java b/test/jdk/java/net/URLPermission/nstest/LookupTest.java index 2d6f39a4191..3cbc7a9f124 100644 --- a/test/jdk/java/net/URLPermission/nstest/LookupTest.java +++ b/test/jdk/java/net/URLPermission/nstest/LookupTest.java @@ -201,7 +201,6 @@ static class LookupTestPermisions { final PermissionCollection perms = new Permissions(); LookupTestPermisions(int port) { - perms.add(new NetPermission("setProxySelector")); perms.add(new SocketPermission("localhost:1024-", "resolve,accept")); perms.add(new URLPermission("http://allowedAndFound.com:" + port + "/-", "*:*")); perms.add(new URLPermission("http://allowedButNotfound.com:" + port + "/-", "*:*")); diff --git a/test/jdk/java/net/httpclient/DebugLoggerTest.java b/test/jdk/java/net/httpclient/DebugLoggerTest.java index ec36d62e38e..8d81e5cbe69 100644 --- a/test/jdk/java/net/httpclient/DebugLoggerTest.java +++ b/test/jdk/java/net/httpclient/DebugLoggerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -213,7 +213,7 @@ public void publish(LogRecord record) { public void flush() { } @Override - public void close() throws SecurityException { + public void close() { } } diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java index 29976edec9a..bafe1496a86 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java +++ b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java @@ -40,7 +40,6 @@ import javax.net.ssl.SSLContext; import java.io.FileNotFoundException; -import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -211,9 +210,6 @@ public void handle(HttpServerAdapters.HttpTestExchange t) throws IOException { @BeforeTest public void setup() throws Exception { - policyFile = System.getProperty("java.security.policy"); - out.println(policyFile); - sslContext = new SimpleSSLContext().get(); if (sslContext == null) throw new AssertionError("Unexpected null sslContext"); diff --git a/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java b/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java index 333996496cd..00f532ba47c 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java +++ b/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -92,13 +92,6 @@ public Path getPath(URI uri) { public InputStream newInputStream(Path path, OpenOption... options) throws IOException { Path p = toTestPath(path).unwrap(); - - // Added permission checks before opening the file - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("customPermission")); - sm.checkRead(p.toString()); - } return defaultProvider.newInputStream(p, options); } diff --git a/test/jdk/java/net/httpclient/PlainProxyConnectionTest.java b/test/jdk/java/net/httpclient/PlainProxyConnectionTest.java index a3157b0ac37..f8671103ec4 100644 --- a/test/jdk/java/net/httpclient/PlainProxyConnectionTest.java +++ b/test/jdk/java/net/httpclient/PlainProxyConnectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; +import jdk.httpclient.test.lib.common.HttpServerAdapters; + import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; @@ -54,15 +56,28 @@ * @bug 8230526 * @summary Verifies that PlainProxyConnections are cached and reused properly. We do this by * verifying that the remote address of the HTTP exchange (on the fake proxy server) - * is always the same InetSocketAddress. - * @modules jdk.httpserver - * @run main/othervm -Djdk.tracePinnedThreads=full PlainProxyConnectionTest - * @author danielfuchs + * is always the same InetSocketAddress. Logging verbosity is increased to aid in + * diagnosis of intermittent failures. + * @library /test/lib + * /test/jdk/java/net/httpclient/lib + * @run main/othervm -Djdk.tracePinnedThreads=full + * -Djdk.httpclient.HttpClient.log=headers,requests,trace + * -Djdk.internal.httpclient.debug=true + * PlainProxyConnectionTest */ public class PlainProxyConnectionTest { + // Increase logging verbosity to troubleshoot intermittent failures + static { + HttpServerAdapters.enableServerLogging(); + } + static final String RESPONSE = "<html><body><p>Hello World!</body></html>"; - static final String PATH = "/foo/"; + + // Adding some salt to the path to avoid other parallel running tests mistakenly connect to our test server + private static final String PATH = String.format( + "/%s-%d", PlainProxyConnectionTest.class.getSimpleName(), PlainProxyConnectionTest.class.hashCode()); + static final ConcurrentLinkedQueue<InetSocketAddress> connections = new ConcurrentLinkedQueue<>(); private static final AtomicInteger IDS = new AtomicInteger(); diff --git a/test/jdk/java/net/httpclient/ProxyServer.java b/test/jdk/java/net/httpclient/ProxyServer.java index 7de14a79225..747a20772d1 100644 --- a/test/jdk/java/net/httpclient/ProxyServer.java +++ b/test/jdk/java/net/httpclient/ProxyServer.java @@ -27,10 +27,8 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.*; -import java.security.*; import java.util.concurrent.CopyOnWriteArrayList; -import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.util.Arrays.asList; @@ -49,9 +47,9 @@ public class ProxyServer extends Thread implements Closeable { // build it. Let's keep it simple. static final boolean IS_WINDOWS; static { - PrivilegedAction<String> action = - () -> System.getProperty("os.name", "unknown"); - String osName = AccessController.doPrivileged(action); + // Parses os.name directly in order to avoid depending on test + // libraries in an auxiliary test class + String osName = System.getProperty("os.name", "unknown"); IS_WINDOWS = osName.toLowerCase(Locale.ROOT).startsWith("win"); } @@ -151,20 +149,6 @@ public void close() throws IOException { volatile boolean done; public void run() { - if (System.getSecurityManager() == null) { - execute(); - } else { - // so calling domain does not need to have socket permission - AccessController.doPrivileged(new PrivilegedAction<Void>() { - public Void run() { - execute(); - return null; - } - }); - } - } - - public void execute() { int id = 0; try { while (!done) { diff --git a/test/jdk/java/net/httpclient/http2/ConnectionFlowControlTest.java b/test/jdk/java/net/httpclient/http2/ConnectionFlowControlTest.java index 6b0b3727ee2..30cc9122d9d 100644 --- a/test/jdk/java/net/httpclient/http2/ConnectionFlowControlTest.java +++ b/test/jdk/java/net/httpclient/http2/ConnectionFlowControlTest.java @@ -171,7 +171,11 @@ void test(String uri) throws Exception { var response = responses.get(keys[i]); String ckey = response.headers().firstValue("X-Connection-Key").get(); if (label == null) label = ckey; - assertEquals(ckey, label, "Unexpected key for " + query); + if (i < max - 1) { + // the connection window might be exceeded at i == max - 2, which + // means that the last request could go on a new connection. + assertEquals(ckey, label, "Unexpected key for " + query); + } int wait = uri.startsWith("https://") ? 500 : 250; try (InputStream is = response.body()) { Thread.sleep(Utils.adjustTimeout(wait)); diff --git a/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java b/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java index 36b727e3a22..39768b68dc5 100644 --- a/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java +++ b/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8342075 + * @bug 8342075 8343855 * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.http2.Http2TestServer jdk.test.lib.net.SimpleSSLContext * @run testng/othervm -Djdk.internal.httpclient.debug=true @@ -40,7 +40,6 @@ import java.net.http.HttpClient; import java.net.http.HttpHeaders; import java.net.http.HttpRequest; -import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.StandardCharsets; @@ -53,6 +52,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpHeadOrGetHandler; import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer; import jdk.httpclient.test.lib.http2.BodyOutputStream; import jdk.httpclient.test.lib.http2.Http2Handler; @@ -69,6 +69,7 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; @@ -92,6 +93,19 @@ public Object[][] variants() { }; } + static void sleep(long wait) throws InterruptedException { + if (wait <= 0) return; + long remaining = Utils.adjustTimeout(wait); + long start = System.nanoTime(); + while (remaining > 0) { + Thread.sleep(remaining); + long end = System.nanoTime(); + remaining = remaining - NANOSECONDS.toMillis(end - start); + } + System.out.printf("Waited %s ms%n", + NANOSECONDS.toMillis(System.nanoTime() - start)); + } + @Test(dataProvider = "variants") void test(String uri, @@ -115,7 +129,7 @@ void test(String uri, CompletableFuture<String> sent = new CompletableFuture<>(); responseSent.put(query, sent); HttpRequest request = HttpRequest.newBuilder(uriWithQuery) - .POST(BodyPublishers.ofString("Hello there!")) + .GET() .build(); System.out.println("\nSending request:" + uriWithQuery); final HttpClient cc = client; @@ -130,9 +144,9 @@ void test(String uri, // we have to pull to get the exception, but slow enough // so that DataFrames are buffered up to the point that // the window is exceeded... - int wait = uri.startsWith("https://") ? 500 : 350; + long wait = uri.startsWith("https://") ? 800 : 350; try (InputStream is = response.body()) { - Thread.sleep(Utils.adjustTimeout(wait)); + sleep(wait); is.readAllBytes(); } // we could fail here if we haven't waited long enough @@ -174,7 +188,7 @@ void testAsync(String uri, CompletableFuture<String> sent = new CompletableFuture<>(); responseSent.put(query, sent); HttpRequest request = HttpRequest.newBuilder(uriWithQuery) - .POST(BodyPublishers.ofString("Hello there!")) + .GET() .build(); System.out.println("\nSending request:" + uriWithQuery); final HttpClient cc = client; @@ -188,9 +202,9 @@ void testAsync(String uri, assertEquals(key, label, "Unexpected key for " + query); } sent.join(); - int wait = uri.startsWith("https://") ? 600 : 300; + long wait = uri.startsWith("https://") ? 800 : 350; try (InputStream is = response.body()) { - Thread.sleep(Utils.adjustTimeout(wait)); + sleep(wait); is.readAllBytes(); } // we could fail here if we haven't waited long enough @@ -252,7 +266,9 @@ public void setup() throws Exception { var https2TestServer = new Http2TestServer("localhost", true, sslContext); https2TestServer.addHandler(new Http2TestHandler(), "/https2/"); this.https2TestServer = HttpTestServer.of(https2TestServer); + this.https2TestServer.addHandler(new HttpHeadOrGetHandler(), "/https2/head/"); https2URI = "https://" + this.https2TestServer.serverAuthority() + "/https2/x"; + String h2Head = "https://" + this.https2TestServer.serverAuthority() + "/https2/head/z"; // Override the default exchange supplier with a custom one to enable // particular test scenarios @@ -261,6 +277,13 @@ public void setup() throws Exception { this.http2TestServer.start(); this.https2TestServer.start(); + + // warmup to eliminate delay due to SSL class loading and initialization. + try (var client = HttpClient.newBuilder().sslContext(sslContext).build()) { + var request = HttpRequest.newBuilder(URI.create(h2Head)).HEAD().build(); + var resp = client.send(request, BodyHandlers.discarding()); + assertEquals(resp.statusCode(), 200); + } } @AfterTest @@ -279,11 +302,19 @@ public void handle(Http2TestExchange t) throws IOException { OutputStream os = t.getResponseBody()) { byte[] bytes = is.readAllBytes(); - System.out.println("Server " + t.getLocalAddress() + " received:\n" - + t.getRequestURI() + ": " + new String(bytes, StandardCharsets.UTF_8)); + if (bytes.length != 0) { + System.out.println("Server " + t.getLocalAddress() + " received:\n" + + t.getRequestURI() + ": " + new String(bytes, StandardCharsets.UTF_8)); + } else { + System.out.println("No request body for " + t.getRequestMethod()); + } + t.getResponseHeaders().setHeader("X-Connection-Key", t.getConnectionKey()); - if (bytes.length == 0) bytes = "no request body!".getBytes(StandardCharsets.UTF_8); + if (bytes.length == 0) { + bytes = "no request body!" + .repeat(100).getBytes(StandardCharsets.UTF_8); + } int window = Integer.getInteger("jdk.httpclient.windowsize", 2 * 16 * 1024); final int maxChunkSize; if (t instanceof FCHttp2TestExchange fct) { @@ -307,13 +338,22 @@ public void handle(Http2TestExchange t) throws IOException { // ignore and continue... } } - ((BodyOutputStream) os).writeUncontrolled(resp, 0, resp.length); + try { + ((BodyOutputStream) os).writeUncontrolled(resp, 0, resp.length); + } catch (IOException x) { + if (t instanceof FCHttp2TestExchange fct) { + fct.conn.updateConnectionWindow(resp.length); + } + } + } + } finally { + if (t instanceof FCHttp2TestExchange fct) { + fct.responseSent(query); + } else { + fail("Exchange is not %s but %s" + .formatted(FCHttp2TestExchange.class.getName(), t.getClass().getName())); } } - if (t instanceof FCHttp2TestExchange fct) { - fct.responseSent(query); - } else fail("Exchange is not %s but %s" - .formatted(FCHttp2TestExchange.class.getName(), t.getClass().getName())); } } diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java index 27dbe637b94..4b00c0eea7b 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java @@ -49,6 +49,7 @@ import java.net.InetSocketAddress; import java.net.URI; import java.net.http.HttpHeaders; +import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.List; import java.util.ListIterator; @@ -66,6 +67,9 @@ import javax.net.ssl.SSLContext; +import static java.net.http.HttpClient.Version.HTTP_1_1; +import static java.net.http.HttpClient.Version.HTTP_2; + /** * Defines an adaptation layers so that a test server handlers and filters * can be implemented independently of the underlying server version. @@ -268,9 +272,9 @@ private static final class Http1TestExchange extends HttpTestExchange { this.exchange = exch; } @Override - public Version getServerVersion() { return Version.HTTP_1_1; } + public Version getServerVersion() { return HTTP_1_1; } @Override - public Version getExchangeVersion() { return Version.HTTP_1_1; } + public Version getExchangeVersion() { return HTTP_1_1; } @Override public InputStream getRequestBody() { return exchange.getRequestBody(); @@ -330,9 +334,9 @@ private static final class H2ExchangeImpl extends HttpTestExchange { this.exchange = exch; } @Override - public Version getServerVersion() { return Version.HTTP_2; } + public Version getServerVersion() { return HTTP_2; } @Override - public Version getExchangeVersion() { return Version.HTTP_2; } + public Version getExchangeVersion() { return HTTP_2; } @Override public InputStream getRequestBody() { return exchange.getRequestBody(); @@ -421,6 +425,53 @@ private void doHandle(HttpTestExchange t) throws IOException { } } + /** + * An {@link HttpTestHandler} that handles only HEAD and GET + * requests. If another method is used 405 is returned with + * an empty body. + * The response is always returned with fixed length. + */ + public static class HttpHeadOrGetHandler implements HttpTestHandler { + final String responseBody; + public HttpHeadOrGetHandler() { + this("pâté de tête persillé"); + } + public HttpHeadOrGetHandler(String responseBody) { + this.responseBody = Objects.requireNonNull(responseBody); + } + + @Override + public void handle(HttpTestExchange t) throws IOException { + try (var exchg = t) { + exchg.getRequestBody().readAllBytes(); + String method = exchg.getRequestMethod(); + switch (method) { + case "HEAD" -> { + byte[] resp = responseBody.getBytes(StandardCharsets.UTF_8); + if (exchg.getExchangeVersion() != HTTP_1_1) { + // with HTTP/2 or HTTP/3 the server will not send content-length + exchg.getResponseHeaders() + .addHeader("Content-Length", String.valueOf(resp.length)); + } + exchg.sendResponseHeaders(200, resp.length); + exchg.getResponseBody().close(); + } + case "GET" -> { + byte[] resp = responseBody.getBytes(StandardCharsets.UTF_8); + exchg.sendResponseHeaders(200, resp.length); + try (var os = exchg.getResponseBody()) { + os.write(resp); + } + } + default -> { + exchg.sendResponseHeaders(405, 0); + exchg.getResponseBody().close(); + } + } + } + } + } + public static class HttpTestEchoHandler implements HttpTestHandler { @Override @@ -877,7 +928,7 @@ public InetSocketAddress getAddress() { return new InetSocketAddress(InetAddress.getLoopbackAddress(), impl.getAddress().getPort()); } - public Version getVersion() { return Version.HTTP_1_1; } + public Version getVersion() { return HTTP_1_1; } @Override public void setRequestApprover(final Predicate<String> approver) { @@ -902,7 +953,7 @@ public void addFilter(HttpTestFilter filter) { public void setAuthenticator(com.sun.net.httpserver.Authenticator authenticator) { context.setAuthenticator(authenticator); } - @Override public Version getVersion() { return Version.HTTP_1_1; } + @Override public Version getVersion() { return HTTP_1_1; } } private static class Http2TestServerImpl extends HttpTestServer { @@ -933,7 +984,7 @@ public InetSocketAddress getAddress() { return new InetSocketAddress(InetAddress.getLoopbackAddress(), impl.getAddress().getPort()); } - public Version getVersion() { return Version.HTTP_2; } + public Version getVersion() { return HTTP_2; } @Override public void setRequestApprover(final Predicate<String> approver) { @@ -971,7 +1022,7 @@ public void setAuthenticator(final Authenticator authenticator) { "only BasicAuthenticator is supported on HTTP/2 context"); } } - @Override public Version getVersion() { return Version.HTTP_2; } + @Override public Version getVersion() { return HTTP_2; } } } diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestServerConfigurator.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestServerConfigurator.java index 5d16ac24155..a471f3ce07f 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestServerConfigurator.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestServerConfigurator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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,8 +23,6 @@ package jdk.httpclient.test.lib.common; import java.net.InetAddress; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.List; import javax.net.ssl.SNIMatcher; @@ -59,14 +57,8 @@ public TestServerConfigurator(final InetAddress serverAddr, final SSLContext con @Override public void configure(final HttpsParameters params) { final SSLParameters sslParams = getSSLContext().getDefaultSSLParameters(); - @SuppressWarnings("removal") final SecurityManager sm = System.getSecurityManager(); - final String hostname; - if (sm == null) { - hostname = serverAddr.getHostName(); - } else { - final PrivilegedAction<String> action = () -> serverAddr.getHostName(); - hostname = AccessController.doPrivileged(action); - } + final String hostname = serverAddr.getHostName(); + final List<SNIMatcher> sniMatchers = List.of(new ServerNameMatcher(hostname)); sslParams.setSNIMatchers(sniMatchers); // configure the server with these custom SSLParameters diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java index 068d2a49e57..fb0ce92cd1d 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java @@ -1384,7 +1384,7 @@ public synchronized void obtainConnectionWindow(int amount) throws InterruptedEx } } - void updateConnectionWindow(int amount) { + public void updateConnectionWindow(int amount) { System.out.printf("sendWindow (window=%s, amount=%s) is now: %s%n", sendWindow, amount, sendWindow + amount); synchronized (this) { diff --git a/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java b/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java index 3c857ba1b48..c8920771727 100644 --- a/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java +++ b/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java @@ -29,7 +29,6 @@ import java.nio.file.Path; import java.nio.file.Paths; -import java.security.PrivilegedExceptionAction; import java.util.List; import java.net.http.HttpRequest; import java.net.http.HttpResponse.BodyHandlers; @@ -43,11 +42,14 @@ public class FileProcessorPermissionTest { static final Path fromFilePath = Paths.get(testSrc, "FileProcessorPermissionTest.java"); static final Path asFilePath = Paths.get(testSrc, "asFile.txt"); static final Path CWD = Paths.get("."); - static final Class<SecurityException> SE = SecurityException.class; + + interface ExceptionAction<T> { + T run() throws Exception; + } @Test public void test() throws Exception { - List<PrivilegedExceptionAction<?>> list = List.of( + List<ExceptionAction<?>> list = List.of( () -> HttpRequest.BodyPublishers.ofFile(fromFilePath), () -> BodyHandlers.ofFile(asFilePath), @@ -59,7 +61,7 @@ public void test() throws Exception { () -> BodyHandlers.ofFileDownload(CWD, CREATE, WRITE) ); - for (PrivilegedExceptionAction pa : list) { + for (ExceptionAction<?> pa : list) { pa.run(); } diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java index 7a960892aec..415caeb1196 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,6 @@ import java.net.http.HttpHeaders; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; -import java.security.AccessController; import java.util.Arrays; import java.util.Base64; import java.util.Collections; @@ -196,8 +195,7 @@ private void doTestAuthentication(String uri, Version v, String proxy) throws Ex HttpRequestImpl origReq = new HttpRequestImpl(reqBuilder); HttpRequestImpl req = new HttpRequestImpl(origReq, ps); MultiExchange<?> multi = new MultiExchange<Void>(origReq, req, client, - BodyHandlers.replacing(null), - null, AccessController.getContext()); + BodyHandlers.replacing(null), null); Exchange<?> exchange = new Exchange<>(req, multi); out.println("\nSimulating unauthenticated request to " + uri); filter.request(req, multi); @@ -266,8 +264,7 @@ private void doTestAuthentication(String uri, Version v, String proxy) throws Ex HttpRequestImpl origReq2 = new HttpRequestImpl(reqBuilder2); HttpRequestImpl req2 = new HttpRequestImpl(origReq2, ps); MultiExchange<?> multi2 = new MultiExchange<Void>(origReq2, req2, client, - HttpResponse.BodyHandlers.replacing(null), - null, AccessController.getContext()); + HttpResponse.BodyHandlers.replacing(null), null); filter.request(req2, multi2); out.println("Check that filter has added credentials from cache for " + reqURI2 + " with proxy " + req2.proxy()); @@ -298,8 +295,7 @@ && isNullOrEmpty(reqURI.getFragment()) HttpRequestImpl origReq3 = new HttpRequestImpl(reqBuilder3); HttpRequestImpl req3 = new HttpRequestImpl(origReq3, ps); MultiExchange<?> multi3 = new MultiExchange<Void>(origReq3, req3, client, - HttpResponse.BodyHandlers.replacing(null), - null, AccessController.getContext()); + HttpResponse.BodyHandlers.replacing(null), null); filter.request(req3, multi3); HttpHeaders h3 = req3.getSystemHeadersBuilder().build(); if (proxy == null) { @@ -342,8 +338,7 @@ && isNullOrEmpty(reqURI.getFragment()) HttpRequestImpl origReq4 = new HttpRequestImpl(reqBuilder4); HttpRequestImpl req4 = new HttpRequestImpl(origReq4, fakeProxy); MultiExchange<?> multi4 = new MultiExchange<Void>(origReq4, req4, client, - HttpResponse.BodyHandlers.replacing(null), null, - AccessController.getContext()); + HttpResponse.BodyHandlers.replacing(null), null); out.println("Simulating new request to " + reqURI4 + " with a proxy " + req4.proxy()); assertTrue((req4.proxy() == null) == (proxy != null), "(req4.proxy() == null) == (proxy != null) should be true"); @@ -383,8 +378,7 @@ && isNullOrEmpty(reqURI.getFragment()) HttpRequestImpl origReq5 = new HttpRequestImpl(reqBuilder5); HttpRequestImpl req5 = new HttpRequestImpl(origReq5, NO_PROXY); MultiExchange<?> multi5 = new MultiExchange<Void>(origReq5, req5, client, - HttpResponse.BodyHandlers.replacing(null), null, - AccessController.getContext()); + HttpResponse.BodyHandlers.replacing(null), null); out.println("Simulating new request to " + reqURI + " with a proxy " + req5.proxy()); assertTrue(req5.proxy() == null, "req5.proxy() should be null"); Exchange<?> exchange5 = new Exchange<>(req5, multi5); @@ -437,8 +431,7 @@ && isNullOrEmpty(reqURI.getFragment()) HttpRequestImpl origReq6 = new HttpRequestImpl(reqBuilder6); HttpRequestImpl req6 = new HttpRequestImpl(origReq6, ps); MultiExchange<?> multi6 = new MultiExchange<Void>(origReq6, req6, client, - HttpResponse.BodyHandlers.replacing(null), null, - AccessController.getContext()); + HttpResponse.BodyHandlers.replacing(null), null); out.println("Simulating new request to " + reqURI + " with a proxy " + req6.proxy()); assertTrue(req6.proxy() != null, "req6.proxy() should not be null"); Exchange<?> exchange6 = new Exchange<>(req6, multi6); @@ -461,8 +454,7 @@ && isNullOrEmpty(reqURI.getFragment()) HttpRequestImpl origReq7 = new HttpRequestImpl(reqBuilder7); HttpRequestImpl req7 = new HttpRequestImpl(origReq7, ps); MultiExchange<?> multi7 = new MultiExchange<Void>(origReq7, req7, client, - HttpResponse.BodyHandlers.replacing(null), null, - AccessController.getContext()); + HttpResponse.BodyHandlers.replacing(null), null); out.println("Simulating new request to " + reqURI7 + " with a proxy " + req7.proxy()); assertTrue(req7.proxy() == null, "req7.proxy() should be null"); Exchange<?> exchange7 = new Exchange<>(req7, multi7); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java index 6619eff008a..9b5764735b2 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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 @@ -221,7 +221,6 @@ private static RawChannel channelOf(int port) throws Exception { requestImpl, clientImpl, discarding(), - null, null); HttpResponse<?> r = mex.responseAsync(clientImpl.theExecutor()) .get(30, SECONDS); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java index 5277eed3ac0..e6897a83de4 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java @@ -42,13 +42,6 @@ /** * Creates a simple usable SSLContext for SSLSocketFactory * or a HttpsServer using a default keystore in the test tree. - * <p> - * Using this class with a security manager requires the following - * permissions to be granted: - * <p> - * permission "java.util.PropertyPermission" "test.src.path", "read"; - * permission java.io.FilePermission "/path/to/test/lib/jdk/test/lib/testkeys", "read"; - * The exact path above depends on the location of the test. */ public class SimpleSSLContext { @@ -60,27 +53,17 @@ public class SimpleSSLContext { public SimpleSSLContext() throws IOException { String paths = System.getProperty("test.src.path"); StringTokenizer st = new StringTokenizer(paths, File.pathSeparator); - boolean securityExceptions = false; SSLContext sslContext = null; while (st.hasMoreTokens()) { String path = st.nextToken(); - try { - File f = new File(path, "../../../../../lib/jdk/test/lib/net/testkeys"); - if (f.exists()) { - try (FileInputStream fis = new FileInputStream(f)) { - sslContext = init(fis); - break; - } + File f = new File(path, "../../../../../lib/jdk/test/lib/net/testkeys"); + if (f.exists()) { + try (FileInputStream fis = new FileInputStream(f)) { + sslContext = init(fis); + break; } - } catch (SecurityException e) { - // catch and ignore because permission only required - // for one entry on path (at most) - securityExceptions = true; } } - if (securityExceptions) { - System.out.println("SecurityExceptions thrown on loading testkeys"); - } ssl = sslContext; } diff --git a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java index d71b9407bbc..acdff692601 100644 --- a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java +++ b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java @@ -24,7 +24,6 @@ /* @test * @bug 8181493 8231174 8343417 * @summary Verify that nanosecond precision is maintained for file timestamps - * @requires (os.family == "linux") | (os.family == "mac") | (os.family == "windows") * @library ../.. /test/lib * @build jdk.test.lib.Platform * @modules java.base/sun.nio.fs:+open @@ -51,18 +50,6 @@ public class SetTimesNanos { public static void main(String[] args) throws Exception { - if (!Platform.isWindows()) { - // Check whether futimens() system call is supported - Class unixNativeDispatcherClass = - Class.forName("sun.nio.fs.UnixNativeDispatcher"); - Method futimensSupported = - unixNativeDispatcherClass.getDeclaredMethod("futimensSupported"); - futimensSupported.setAccessible(true); - if (!(boolean)futimensSupported.invoke(null)) { - throw new SkippedException("futimens() not supported"); - } - } - Path dirPath = Path.of("test"); Path dir = Files.createDirectory(dirPath); FileStore store = Files.getFileStore(dir); @@ -80,10 +67,8 @@ public static void main(String[] args) throws Exception { Path file = Files.createFile(dir.resolve("test.dat")); testNanos(file); - if (Platform.isLinux()) { - testNanosLink(false); - testNanosLink(true); - } + testNanosLink(false); + testNanosLink(true); } private static void testNanos(Path path) throws IOException { @@ -130,7 +115,14 @@ private static void testNanosLink(boolean absolute) throws IOException { Files.createFile(target); Files.createSymbolicLink(symlink, target); - var newTime = FileTime.from(1730417633157646106L, NANOSECONDS); + long timeNanos = 1730417633157646106L; + + // Windows file time resolution is 100ns so truncate + if (Platform.isWindows()) { + timeNanos = 100L*(timeNanos/100L); + } + + var newTime = FileTime.from(timeNanos, NANOSECONDS); System.out.println("newTime: " + newTime.to(NANOSECONDS)); for (Path p : List.of(target, symlink)) { diff --git a/test/jdk/java/sql/testng/util/TestPolicy.java b/test/jdk/java/sql/testng/util/TestPolicy.java deleted file mode 100644 index 013dfad563c..00000000000 --- a/test/jdk/java/sql/testng/util/TestPolicy.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2014, 2021, 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 util; - -import java.io.FilePermission; -import java.lang.reflect.ReflectPermission; -import java.security.AllPermission; -import java.security.CodeSource; -import java.security.Permission; -import java.security.PermissionCollection; -import java.security.Permissions; -import java.security.Policy; -import java.security.ProtectionDomain; -import java.security.SecurityPermission; -import java.sql.SQLPermission; -import java.util.Enumeration; -import java.util.PropertyPermission; -import java.util.StringJoiner; -import java.util.logging.LoggingPermission; - -/* - * Simple Policy class that supports the required Permissions to validate the - * JDBC concrete classes - */ -public class TestPolicy extends Policy { - static final Policy DEFAULT_POLICY = Policy.getPolicy(); - - final PermissionCollection permissions = new Permissions(); - - /** - * Constructor which sets the minimum permissions allowing testNG to work - * with a SecurityManager - */ - public TestPolicy() { - setMinimalPermissions(); - } - - /* - * Constructor which determines which permissions are defined for this - * Policy used by the JDBC tests Possible values are: all (ALLPermissions), - * setLog (SQLPemission("setLog"), deregisterDriver - * (SQLPermission("deregisterDriver") (SQLPermission("deregisterDriver"), - * setSyncFactory(SQLPermission(setSyncFactory), and also - * LoggerPermission("control", null) when setting a Level - * - * @param policy Permissions to set - */ - public TestPolicy(String policy) { - - switch (policy) { - case "all": - permissions.add(new AllPermission()); - break; - case "setLog": - setMinimalPermissions(); - permissions.add(new SQLPermission("setLog")); - break; - case "deregisterDriver": - setMinimalPermissions(); - permissions.add(new SQLPermission("deregisterDriver")); - break; - case "setSyncFactory": - setMinimalPermissions(); - permissions.add(new SQLPermission("setSyncFactory")); - break; - case "setSyncFactoryLogger": - setMinimalPermissions(); - permissions.add(new SQLPermission("setSyncFactory")); - permissions.add(new LoggingPermission("control", null)); - break; - default: - setMinimalPermissions(); - } - } - - /* - * Defines the minimal permissions required by testNG when running these - * tests - */ - private void setMinimalPermissions() { - permissions.add(new SecurityPermission("getPolicy")); - permissions.add(new SecurityPermission("setPolicy")); - permissions.add(new RuntimePermission("getClassLoader")); - permissions.add(new RuntimePermission("setSecurityManager")); - permissions.add(new RuntimePermission("createSecurityManager")); - permissions.add(new PropertyPermission("line.separator", "read")); - permissions.add(new PropertyPermission("fileStringBuffer", "read")); - permissions.add(new PropertyPermission("dataproviderthreadcount", "read")); - permissions.add(new PropertyPermission("java.io.tmpdir", "read")); - permissions.add(new PropertyPermission("testng.show.stack.frames", - "read")); - permissions.add(new PropertyPermission("testng.thread.affinity", "read")); - permissions.add(new PropertyPermission("testng.memory.friendly", "read")); - permissions.add(new PropertyPermission("testng.mode.dryrun", "read")); - permissions.add(new PropertyPermission("testng.report.xml.name", "read")); - permissions.add(new PropertyPermission("testng.timezone", "read")); - permissions.add(new ReflectPermission("suppressAccessChecks")); - permissions.add(new FilePermission("<<ALL FILES>>", - "read, write, delete")); - } - - /* - * Overloaded methods from the Policy class - */ - @Override - public String toString() { - StringJoiner sj = new StringJoiner("\n", "policy: ", ""); - Enumeration<Permission> perms = permissions.elements(); - while (perms.hasMoreElements()) { - sj.add(perms.nextElement().toString()); - } - return sj.toString(); - - } - - @Override - public PermissionCollection getPermissions(ProtectionDomain domain) { - return permissions; - } - - @Override - public PermissionCollection getPermissions(CodeSource codesource) { - return permissions; - } - - @Override - public boolean implies(ProtectionDomain domain, Permission perm) { - return permissions.implies(perm) || DEFAULT_POLICY.implies(domain, perm); - } -} diff --git a/test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java b/test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java index 044f126dd9e..5560b9ed4fe 100644 --- a/test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java +++ b/test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java @@ -1323,6 +1323,37 @@ private int lastAscending() { } } + /** + * Spliterators.trySplit() returns null with an empty map and non-null when + * it is not empty. + */ + public void testSpliterators() { + // To test JDK-8343426 + ConcurrentSkipListMap<Integer, Integer> map = new ConcurrentSkipListMap<>(); + for (int i = 1; i <= 1000; i++) map.put(i, i); + // ensure that the splits do happen + assertNotNull(map.keySet().spliterator().trySplit()); + assertNotNull(map.entrySet().spliterator().trySplit()); + assertNotNull(map.values().spliterator().trySplit()); + // ensure that the splits return *all* the items in the set + assertEquals(500_500, map.keySet() + .parallelStream() + .mapToInt(Integer::valueOf) + .sum()); + assertEquals(500_500, map.values() + .parallelStream() + .mapToInt(Integer::valueOf) + .sum()); + assertEquals(500_500 * 2, map.entrySet() + .parallelStream() + .mapToInt(entry -> entry.getKey() + entry.getValue()) + .sum()); + map.clear(); + assertNull(map.keySet().spliterator().trySplit()); + assertNull(map.entrySet().spliterator().trySplit()); + assertNull(map.values().spliterator().trySplit()); + } + static void assertEq(Item i, int j) { if (i == null) mustEqual(j, -1); diff --git a/test/jdk/javax/swing/JInternalFrame/bug6726866.java b/test/jdk/javax/swing/JInternalFrame/bug6726866.java index 88b890d7b2c..a8f267fedc2 100644 --- a/test/jdk/javax/swing/JInternalFrame/bug6726866.java +++ b/test/jdk/javax/swing/JInternalFrame/bug6726866.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6726866 8186617 + * @bug 6726866 8186617 8343123 * @summary Repainting artifacts when resizing or dragging JInternalFrames in non-opaque toplevel * @library /java/awt/regtesthelpers @@ -34,7 +34,6 @@ import java.awt.Color; import java.awt.Window; -import javax.swing.JApplet; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; diff --git a/test/jdk/javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java b/test/jdk/javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java index 18f78d88f52..e495c929891 100644 --- a/test/jdk/javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java +++ b/test/jdk/javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java @@ -26,28 +26,41 @@ * @key headful * @bug 4983388 8015600 * @summary shortcuts on menus do not work on JDS - * @author Oleg Mokhovikov * @library ../../../../regtesthelpers * @build Util * @run main bug4983388 */ -import java.awt.*; -import javax.swing.*; -import javax.swing.event.MenuListener; -import javax.swing.event.MenuEvent; +import java.awt.Robot; import java.awt.event.KeyEvent; +import java.util.concurrent.CountDownLatch; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +import static java.util.concurrent.TimeUnit.SECONDS; public class bug4983388 { - static volatile boolean bMenuSelected = false; static JFrame frame; + private static final CountDownLatch menuSelected = new CountDownLatch(1); + private static class TestMenuListener implements MenuListener { + @Override public void menuCanceled(MenuEvent e) {} + @Override public void menuDeselected(MenuEvent e) {} + + @Override public void menuSelected(MenuEvent e) { System.out.println("menuSelected"); - bMenuSelected = true; + menuSelected.countDown(); } } @@ -56,28 +69,24 @@ private static void createAndShowGUI() { JMenu menu = new JMenu("File"); menu.setMnemonic('F'); menuBar.add(menu); - frame = new JFrame(); + menu.addMenuListener(new TestMenuListener()); + + frame = new JFrame("bug4983388"); frame.setJMenuBar(menuBar); frame.setLocationRelativeTo(null); - frame.pack(); + frame.setSize(250, 100); frame.setVisible(true); - MenuListener listener = new TestMenuListener(); - menu.addMenuListener(listener); } public static void main(String[] args) throws Exception { - try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); } catch (UnsupportedLookAndFeelException | ClassNotFoundException ex) { - System.err.println("GTKLookAndFeel is not supported on this platform. Using defailt LaF for this platform."); + System.err.println("GTKLookAndFeel is not supported on this platform. " + + "Using default LaF for this platform."); } - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); + SwingUtilities.invokeAndWait(bug4983388::createAndShowGUI); Robot robot = new Robot(); robot.setAutoDelay(50); @@ -85,13 +94,13 @@ public void run() { robot.delay(500); Util.hitMnemonics(robot, KeyEvent.VK_F); - robot.waitForIdle(); - robot.delay(500); - - SwingUtilities.invokeAndWait(() -> frame.dispose()); - if (!bMenuSelected) { - throw new RuntimeException("shortcuts on menus do not work"); + try { + if (!menuSelected.await(1, SECONDS)) { + throw new RuntimeException("shortcuts on menus do not work"); + } + } finally { + SwingUtilities.invokeAndWait(frame::dispose); } } } diff --git a/test/jdk/javax/swing/plaf/nimbus/8041642/bug8041642.java b/test/jdk/javax/swing/plaf/nimbus/8041642/bug8041642.java index 9eeaa0e1b9e..7779a4d6bd4 100644 --- a/test/jdk/javax/swing/plaf/nimbus/8041642/bug8041642.java +++ b/test/jdk/javax/swing/plaf/nimbus/8041642/bug8041642.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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,11 +26,21 @@ * @key headful * @bug 8041642 8079450 8140237 * @summary Incorrect paint of JProgressBar in Nimbus LF - * @author Semyon Sadetsky */ -import javax.swing.*; -import java.awt.*; +import java.io.File; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import javax.imageio.ImageIO; +import javax.swing.JFrame; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; public class bug8041642 { @@ -50,7 +60,8 @@ public void run() { } }); final Robot robot = new Robot(); - robot.delay(300); + robot.waitForIdle(); + robot.delay(1000); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { @@ -58,9 +69,15 @@ public void run() { } }); Color color = robot.getPixelColor(point.x + 1, point.y + 7); - System.out.println(color); + System.out.println("point " + point + " color " + color); if (color.getGreen() < 150 || color.getBlue() > 30 || color.getRed() > 200) { + Rectangle bounds = frame.getBounds(); + BufferedImage img = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_ARGB); + Graphics g = img.getGraphics(); + frame.paint(g); + g.dispose(); + ImageIO.write(img, "png", new File("bug8041642.png")); throw new RuntimeException("Bar padding color should be green"); } diff --git a/test/jdk/jdk/classfile/BoundAttributeTest.java b/test/jdk/jdk/classfile/BoundAttributeTest.java index 6a164bec2f9..e8f12356128 100644 --- a/test/jdk/jdk/classfile/BoundAttributeTest.java +++ b/test/jdk/jdk/classfile/BoundAttributeTest.java @@ -41,6 +41,7 @@ import java.lang.classfile.attribute.MethodParameterInfo; import java.lang.classfile.attribute.MethodParametersAttribute; import java.lang.classfile.constantpool.ConstantPoolException; +import java.lang.classfile.constantpool.Utf8Entry; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDescs; import java.lang.constant.MethodTypeDesc; @@ -89,6 +90,11 @@ public void writeBody(BufWriterImpl b) { b.writeIndex(oneClass); b.writeIndex(oneClassString); } + + @Override + public Utf8Entry attributeName() { + return cp.utf8Entry(Attributes.NAME_NEST_MEMBERS); + } }); }); diff --git a/test/jdk/jdk/classfile/CorpusTest.java b/test/jdk/jdk/classfile/CorpusTest.java index 631e2f8afaa..513005370e7 100644 --- a/test/jdk/jdk/classfile/CorpusTest.java +++ b/test/jdk/jdk/classfile/CorpusTest.java @@ -93,6 +93,11 @@ public void writeBody(BufWriterImpl b) { b.writeU2(curPc); b.writeU2(ln.line()); } + + @Override + public Utf8Entry attributeName() { + return cob.constantPool().utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE); + } }); case LocalVariable lv -> dcob.writeAttribute(new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTable()) { @Override @@ -100,6 +105,11 @@ public void writeBody(BufWriterImpl b) { b.writeU2(1); Util.writeLocalVariable(b, lv); } + + @Override + public Utf8Entry attributeName() { + return cob.constantPool().utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE); + } }); case LocalVariableType lvt -> dcob.writeAttribute(new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTypeTable()) { @Override @@ -107,6 +117,11 @@ public void writeBody(BufWriterImpl b) { b.writeU2(1); Util.writeLocalVariable(b, lvt); } + + @Override + public Utf8Entry attributeName() { + return cob.constantPool().utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TYPE_TABLE); + } }); default -> cob.with(coe); } diff --git a/test/jdk/jdk/classfile/LimitsTest.java b/test/jdk/jdk/classfile/LimitsTest.java index a1899ac1c84..6f3dc04c665 100644 --- a/test/jdk/jdk/classfile/LimitsTest.java +++ b/test/jdk/jdk/classfile/LimitsTest.java @@ -41,6 +41,7 @@ import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.ConstantPoolException; import java.lang.classfile.constantpool.IntegerEntry; +import java.lang.classfile.constantpool.Utf8Entry; import java.util.List; import jdk.internal.classfile.impl.BufWriterImpl; @@ -49,6 +50,7 @@ import jdk.internal.classfile.impl.LabelContext; import jdk.internal.classfile.impl.UnboundAttribute; import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.*; class LimitsTest { @@ -145,7 +147,13 @@ public void writeBody(BufWriterImpl b) { b.writeInt(-2); //npairs to jump back and cause OOME if not checked b.writeU2(0);//exception handlers b.writeU2(0);//attributes - }})))).methods().get(0).code().get().elementList()); + } + + @Override + public Utf8Entry attributeName() { + return mb.constantPool().utf8Entry(Attributes.NAME_CODE); + } + })))).methods().get(0).code().get().elementList()); } @Test @@ -167,7 +175,13 @@ public void writeBody(BufWriterImpl b) { b.writeInt(-5); //high to jump back and cause OOME if not checked b.writeU2(0);//exception handlers b.writeU2(0);//attributes - }})))).methods().get(0).code().get().elementList()); + } + + @Override + public Utf8Entry attributeName() { + return mb.constantPool().utf8Entry(Attributes.NAME_CODE); + } + })))).methods().get(0).code().get().elementList()); assertThrows(IllegalArgumentException.class, () -> ClassFile.of().parse(ClassFile.of().build(ClassDesc.of("TableSwitchClass"), cb -> cb.withMethod( "tableSwitchMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, mb -> @@ -189,7 +203,13 @@ public void writeBody(BufWriterImpl b) { b.writeInt(Integer.MAX_VALUE - 4); //high to jump back and cause infinite loop b.writeU2(0);//exception handlers b.writeU2(0);//attributes - }})))).methods().get(0).code().get().elementList()); + } + + @Override + public Utf8Entry attributeName() { + return mb.constantPool().utf8Entry(Attributes.NAME_CODE); + } + })))).methods().get(0).code().get().elementList()); } @Test diff --git a/test/jdk/jdk/classfile/LowJCovAttributeTest.java b/test/jdk/jdk/classfile/LowJCovAttributeTest.java index 858b9c90416..ed29a057357 100644 --- a/test/jdk/jdk/classfile/LowJCovAttributeTest.java +++ b/test/jdk/jdk/classfile/LowJCovAttributeTest.java @@ -76,7 +76,7 @@ void testRead() { private void testRead0() { int[] mask = new int[1]; for (Attribute<?> attr : classLow.attributes()) { - switch (attr.attributeName()) { + switch (attr.attributeName().stringValue()) { case Attributes.NAME_COMPILATION_ID: { CompilationIDAttribute cid = (CompilationIDAttribute) attr; Utf8Entry v = cid.compilationId(); diff --git a/test/jdk/jdk/classfile/LowModuleTest.java b/test/jdk/jdk/classfile/LowModuleTest.java index e78eff74d1d..b017fe84756 100644 --- a/test/jdk/jdk/classfile/LowModuleTest.java +++ b/test/jdk/jdk/classfile/LowModuleTest.java @@ -77,7 +77,7 @@ void testRead(Path path, TestInfo test) throws Exception { private void testRead0(ClassModel classLow) { for (Attribute<?> attr : classLow.attributes()) { - switch (attr.attributeName()) { + switch (attr.attributeName().stringValue()) { case Attributes.NAME_SOURCE_FILE: { SourceFileAttribute sfa = (SourceFileAttribute) attr; Utf8Entry sf = sfa.sourceFile(); diff --git a/test/jdk/jdk/classfile/VerifierSelfTest.java b/test/jdk/jdk/classfile/VerifierSelfTest.java index b6a2f08c9ec..1f9f199a33b 100644 --- a/test/jdk/jdk/classfile/VerifierSelfTest.java +++ b/test/jdk/jdk/classfile/VerifierSelfTest.java @@ -31,7 +31,9 @@ import java.io.IOException; import java.lang.classfile.constantpool.PoolEntry; import java.lang.constant.ClassDesc; + import static java.lang.constant.ConstantDescs.*; + import java.lang.invoke.MethodHandleInfo; import java.net.URI; import java.nio.file.FileSystem; @@ -47,12 +49,14 @@ import java.lang.classfile.*; import java.lang.classfile.attribute.*; import java.lang.classfile.components.ClassPrinter; +import java.lang.classfile.constantpool.Utf8Entry; import java.lang.constant.ModuleDesc; import jdk.internal.classfile.impl.BufWriterImpl; import jdk.internal.classfile.impl.DirectClassBuilder; import jdk.internal.classfile.impl.UnboundAttribute; import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.*; class VerifierSelfTest { @@ -109,6 +113,11 @@ void testInvalidAttrLocation() { public void writeBody(BufWriterImpl b) { b.writeU2(0); } + + @Override + public Utf8Entry attributeName() { + return cb.constantPool().utf8Entry(Attributes.NAME_LOCAL_VARIABLE_TABLE); + } })); assertTrue(cc.verify(bytes).stream().anyMatch(e -> e.getMessage().contains("Invalid LocalVariableTable attribute location"))); } @@ -366,7 +375,7 @@ private static class CloneAttribute extends CustomAttribute<CloneAttribute> { super(new AttributeMapper<CloneAttribute>(){ @Override public String name() { - return a.attributeName(); + return a.attributeName().stringValue(); } @Override diff --git a/test/jdk/jdk/classfile/helpers/ClassRecord.java b/test/jdk/jdk/classfile/helpers/ClassRecord.java index e7a239015f6..c663721ec9f 100644 --- a/test/jdk/jdk/classfile/helpers/ClassRecord.java +++ b/test/jdk/jdk/classfile/helpers/ClassRecord.java @@ -234,7 +234,7 @@ public record AttributesRecord( public static AttributesRecord ofStreamingElements(Supplier<Stream<? extends ClassFileElement>> elements, ConstantPool cp, CompatibilityFilter... cf) { Map<String, Attribute<?>> attrs = elements.get().filter(e -> e instanceof Attribute<?>) .map(e -> (Attribute<?>) e) - .collect(toMap(Attribute::attributeName, e -> e)); + .collect(toMap(a -> a.attributeName().stringValue(), e -> e)); return new AttributesRecord( mapAttr(attrs, annotationDefault(), a -> ElementValueRecord.ofElementValue(a.defaultValue())), cp == null ? null : IntStream.range(0, cp.bootstrapMethodCount()).mapToObj(i -> BootstrapMethodRecord.ofBootstrapMethodEntry(cp.bootstrapMethodEntry(i))).collect(toSetOrNull()), diff --git a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java index c1d9781b6ce..b0e1d6c312d 100644 --- a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java +++ b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java @@ -59,8 +59,8 @@ static byte[] transform(ClassModel clm) { case RuntimeVisibleTypeAnnotationsAttribute a -> fb.with(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); case SignatureAttribute a -> fb.with(SignatureAttribute.of(Signature.parseFrom(a.asTypeSignature().signatureString()))); case SyntheticAttribute a -> fb.with(SyntheticAttribute.of()); - case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName()); - case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName()); + case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName().stringValue()); + case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName().stringValue()); } } }); @@ -91,8 +91,8 @@ static byte[] transform(ClassModel clm) { case RuntimeVisibleTypeAnnotationsAttribute a -> mb.with(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); case SignatureAttribute a -> mb.with(SignatureAttribute.of(MethodSignature.parseFrom(a.asMethodSignature().signatureString()))); case SyntheticAttribute a -> mb.with(SyntheticAttribute.of()); - case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName()); - case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName()); + case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName().stringValue()); + case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName().stringValue()); } } }); @@ -131,7 +131,7 @@ static byte[] transform(ClassModel clm) { case RuntimeVisibleAnnotationsAttribute rvaa -> rcac.accept(RuntimeVisibleAnnotationsAttribute.of(transformAnnotations(rvaa.annotations()))); case RuntimeVisibleTypeAnnotationsAttribute rvtaa -> rcac.accept(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(rvtaa.annotations(), null, null))); case SignatureAttribute sa -> rcac.accept(SignatureAttribute.of(Signature.parseFrom(sa.asTypeSignature().signatureString()))); - default -> throw new AssertionError("Unexpected record component attribute: " + rca.attributeName()); + default -> throw new AssertionError("Unexpected record component attribute: " + rca.attributeName().stringValue()); }}).toArray(Attribute[]::new))).toArray(RecordComponentInfo[]::new))); case RuntimeInvisibleAnnotationsAttribute a -> clb.with(RuntimeInvisibleAnnotationsAttribute.of(transformAnnotations(a.annotations()))); case RuntimeInvisibleTypeAnnotationsAttribute a -> clb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); @@ -142,8 +142,8 @@ static byte[] transform(ClassModel clm) { case SourceFileAttribute a -> clb.with(SourceFileAttribute.of(a.sourceFile().stringValue())); case SourceIDAttribute a -> clb.with(SourceIDAttribute.of(a.sourceId().stringValue())); case SyntheticAttribute a -> clb.with(SyntheticAttribute.of()); - case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName()); - case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName()); + case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName().stringValue()); + case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName().stringValue()); } } }); @@ -595,7 +595,7 @@ else switch (i.constantValue()) { transformFrameTypeInfos(fr.locals(), cob, labels), transformFrameTypeInfos(fr.stack(), cob, labels))).toList())); case CustomAttribute a -> - throw new AssertionError("Unexpected custom attribute: " + a.attributeName()); + throw new AssertionError("Unexpected custom attribute: " + a.attributeName().stringValue()); } } } diff --git a/test/jdk/jdk/internal/math/FloatingDecimal/TestFDBigInteger.java b/test/jdk/jdk/internal/math/FloatingDecimal/TestFDBigInteger.java index 9eb8cfe7844..04be8efa38c 100644 --- a/test/jdk/jdk/internal/math/FloatingDecimal/TestFDBigInteger.java +++ b/test/jdk/jdk/internal/math/FloatingDecimal/TestFDBigInteger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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,13 +22,13 @@ */ import java.math.BigInteger; -import java.util.Random; +import java.nio.charset.StandardCharsets; import jdk.internal.math.FDBigInteger; /** * @test - * @bug 7032154 - * @summary unit testys of FDBigInteger + * @bug 7032154 8342693 + * @summary unit tests of FDBigInteger * @modules java.base/jdk.internal.math * @author Dmitry Nadezhin */ @@ -52,7 +52,7 @@ public class TestFDBigInteger { } private static FDBigInteger mutable(String hex, int offset) { - char[] chars = new BigInteger(hex, 16).toString().toCharArray(); + byte[] chars = new BigInteger(hex, 16).toString().getBytes(StandardCharsets.US_ASCII); return new FDBigInteger(0, chars, 0, chars.length).multByPow52(0, offset * 32); } diff --git a/test/jdk/jdk/internal/misc/CDS/ArchivedEnumTest.java b/test/jdk/jdk/internal/misc/CDS/ArchivedEnumTest.java index ec1bd213834..3a2d0f9539f 100644 --- a/test/jdk/jdk/internal/misc/CDS/ArchivedEnumTest.java +++ b/test/jdk/jdk/internal/misc/CDS/ArchivedEnumTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -35,6 +35,7 @@ * @run driver ArchivedEnumTest */ +import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.helpers.ClassFileInstaller; import jdk.test.lib.process.OutputAnalyzer; @@ -46,7 +47,7 @@ public static void main(String[] args) throws Exception { TestCommon.list("ArchivedEnumApp")); // Note: You can get the following line to fail by commenting out // the ADD_EXCL(...) lines in cdsHeapVerifier.cpp - out.shouldNotContain("object points to a static field that may be reinitialized at runtime"); + out.shouldNotContain(CDSTestUtils.MSG_STATIC_FIELD_MAY_HOLD_DIFFERENT_VALUE); TestCommon.run("-cp", appJar, "-Xlog:cds=debug", diff --git a/test/jdk/jdk/internal/reflect/CallerSensitive/CheckCSMs.java b/test/jdk/jdk/internal/reflect/CallerSensitive/CheckCSMs.java index ee4d2021b87..83841fe104b 100644 --- a/test/jdk/jdk/internal/reflect/CallerSensitive/CheckCSMs.java +++ b/test/jdk/jdk/internal/reflect/CallerSensitive/CheckCSMs.java @@ -70,18 +70,13 @@ public class CheckCSMs { // The goal is to remove this list of Non-final instance @CS methods // over time. Do not add any new one to this list. private static final Set<String> KNOWN_NON_FINAL_CSMS = - Set.of("java/io/ObjectStreamField#getType ()Ljava/lang/Class;", - "java/lang/Runtime#load (Ljava/lang/String;)V", - "java/lang/Runtime#loadLibrary (Ljava/lang/String;)V", - "javax/sql/rowset/serial/SerialJavaObject#getFields ()[Ljava/lang/reflect/Field;" + Set.of("java/lang/Runtime#load (Ljava/lang/String;)V", + "java/lang/Runtime#loadLibrary (Ljava/lang/String;)V" ); // These non-static non-final methods must not have @CallerSensitiveAdapter // methods that takes an additional caller class parameter. - private static Set<String> UNSUPPORTED_VIRTUAL_METHODS = - Set.of("java/io/ObjectStreamField#getType (Ljava/lang/Class;)Ljava/lang/Class;", - "javax/sql/rowset/serial/SerialJavaObject#getFields (Ljava/lang/Class;)[Ljava/lang/reflect/Field;" - ); + private static Set<String> UNSUPPORTED_VIRTUAL_METHODS = Set.of(); public static void main(String[] args) throws Exception { if (args.length > 0 && args[0].equals("--list")) { diff --git a/test/jdk/jdk/jfr/event/oldobject/TestClassLoaderLeak.java b/test/jdk/jdk/jfr/event/oldobject/TestClassLoaderLeak.java index aa74c631389..6f7337d3777 100644 --- a/test/jdk/jdk/jfr/event/oldobject/TestClassLoaderLeak.java +++ b/test/jdk/jdk/jfr/event/oldobject/TestClassLoaderLeak.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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,8 @@ * @test * @key jfr * @requires vm.hasJFR + * @requires vm.flagless + * @comment Marked as flagless until JDK-8322597 is fixed * @library /test/lib /test/jdk * @modules jdk.jfr/jdk.jfr.internal.test * @run main/othervm -XX:TLABSize=2k -Xmx64m jdk.jfr.event.oldobject.TestClassLoaderLeak diff --git a/test/jdk/jdk/jfr/event/oldobject/TestObjectDescription.java b/test/jdk/jdk/jfr/event/oldobject/TestObjectDescription.java index d62b20bc995..447d2bb9cec 100644 --- a/test/jdk/jdk/jfr/event/oldobject/TestObjectDescription.java +++ b/test/jdk/jdk/jfr/event/oldobject/TestObjectDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,9 @@ * @test * @key jfr * @requires vm.hasJFR - * @requires vm.gc != "Z" & vm.gc != "Shenandoah" + * @requires vm.gc != "Shenandoah" + * @requires vm.flagless + * @comment Marked as flagless until JDK-8344015 is fixed * @library /test/lib /test/jdk * @modules jdk.jfr/jdk.jfr.internal.test * @run main/othervm -XX:TLABSize=2k jdk.jfr.event.oldobject.TestObjectDescription diff --git a/test/jdk/jdk/jfr/threading/TestDeepVirtualStackTrace.java b/test/jdk/jdk/jfr/threading/TestDeepVirtualStackTrace.java index d754d9cb598..3fecd91ea62 100644 --- a/test/jdk/jdk/jfr/threading/TestDeepVirtualStackTrace.java +++ b/test/jdk/jdk/jfr/threading/TestDeepVirtualStackTrace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -42,7 +42,7 @@ * @requires vm.hasJFR & vm.continuations * @library /test/lib /test/jdk * @modules jdk.jfr/jdk.jfr.internal - * @run main/othervm -XX:FlightRecorderOptions:stackdepth=2048 + * @run main/othervm -XX:MaxNewSize=40M -XX:FlightRecorderOptions:stackdepth=2048 * jdk.jfr.threading.TestDeepVirtualStackTrace */ public class TestDeepVirtualStackTrace { @@ -80,6 +80,8 @@ private static void testNativeEvent() throws Exception { private static void deepsleep(int depth) { if (depth == 0) { + // The TLAB max size is not limited explicitly + // So the test limit max size of young generation to allocate outside TLAB allocated = new Object[10_000_000]; System.out.println("Emitted ObjectAllocationOutsideTLAB event"); return; diff --git a/test/jdk/jdk/nio/zipfs/TestPosix.java b/test/jdk/jdk/nio/zipfs/TestPosix.java index f63f091c32e..420c1618e12 100644 --- a/test/jdk/jdk/nio/zipfs/TestPosix.java +++ b/test/jdk/jdk/nio/zipfs/TestPosix.java @@ -29,10 +29,6 @@ import java.nio.ByteOrder; import java.nio.file.*; import java.nio.file.attribute.*; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.time.Instant; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -219,35 +215,28 @@ static interface Executor { private static String expectedDefaultOwner(Path zf) { try { - try { - PrivilegedExceptionAction<String> pa = ()->Files.getOwner(zf).getName(); - return AccessController.doPrivileged(pa); - } catch (UnsupportedOperationException e) { - // if we can't get the owner of the file, we fall back to system property user.name - PrivilegedAction<String> pa = ()->System.getProperty("user.name"); - return AccessController.doPrivileged(pa); - } - } catch (PrivilegedActionException | SecurityException e) { + return Files.getOwner(zf).getName(); + } catch (UnsupportedOperationException e) { + // if we can't get the owner of the file, we fall back to system property user.name + return System.getProperty("user.name"); + } catch (IOException e) { System.out.println("Caught " + e.getClass().getName() + "(" + e.getMessage() + - ") when running a privileged operation to get the default owner."); + ") when getting the default owner."); return null; } } private static String expectedDefaultGroup(Path zf, String defaultOwner) { try { - try { - PosixFileAttributeView zfpv = Files.getFileAttributeView(zf, PosixFileAttributeView.class); - if (zfpv == null) { - return defaultOwner; - } - PrivilegedExceptionAction<String> pa = ()->zfpv.readAttributes().group().getName(); - return AccessController.doPrivileged(pa); - } catch (UnsupportedOperationException e) { + PosixFileAttributeView zfpv = Files.getFileAttributeView(zf, PosixFileAttributeView.class); + if (zfpv == null) { return defaultOwner; } - } catch (PrivilegedActionException | SecurityException e) { - System.out.println("Caught an exception when running a privileged operation to get the default group."); + return zfpv.readAttributes().group().getName(); + } catch (UnsupportedOperationException e) { + return defaultOwner; + } catch (IOException e) { + System.out.println("Caught an exception when getting the default group."); e.printStackTrace(); return null; } diff --git a/test/jdk/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java b/test/jdk/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java index 03dade05b14..b86ee4db0b9 100644 --- a/test/jdk/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java +++ b/test/jdk/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java @@ -29,12 +29,16 @@ import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; import java.io.ObjectStreamException; +import java.io.ObjectStreamField; import java.io.OptionalDataException; +import java.io.Serial; import java.io.Serializable; import java.lang.invoke.MethodHandle; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; import sun.reflect.ReflectionFactory; @@ -46,7 +50,7 @@ /* * @test - * @bug 8137058 8164908 8168980 8275137 + * @bug 8137058 8164908 8168980 8275137 8333796 * @summary Basic test for the unsupported ReflectionFactory * @modules jdk.unsupported * @run testng ReflectionFactoryTest @@ -327,6 +331,509 @@ static void newOptionalDataException() { } + private static final String[] names = { + "boolean_", + "final_boolean", + "byte_", + "final_byte", + "char_", + "final_char", + "short_", + "final_short", + "int_", + "final_int", + "long_", + "final_long", + "float_", + "final_float", + "double_", + "final_double", + "str", + "final_str", + "writeFields", + }; + + // test that the generated read/write objects are working properly + @Test + static void testDefaultReadWriteObject() throws Throwable { + Ser2 ser = new Ser2((byte) 0x33, (short) 0x2244, (char) 0x5342, 0x05382716, 0xf035a73b09113bacL, 1234f, 3456.0, true, new Ser3(0x004917aa)); + ser.byte_ = (byte) 0x44; + ser.short_ = (short) 0x3355; + ser.char_ = (char) 0x6593; + ser.int_ = 0x4928a299; + ser.long_ = 0x24aa19883f4b9138L; + ser.float_ = 4321f; + ser.double_ = 6543.0; + ser.boolean_ = false; + ser.ser = new Ser3(0x70b030a0); + // first, ensure that each field gets written + MethodHandle writeObject = factory.defaultWriteObjectForSerialization(Ser2.class); + Assert.assertNotNull(writeObject, "writeObject not created"); + boolean[] called = new boolean[19]; + @SuppressWarnings("removal") + ObjectOutputStream oos = new ObjectOutputStream() { + protected void writeObjectOverride(final Object obj) throws IOException { + throw new IOException("Wrong method called"); + } + + public void defaultWriteObject() throws IOException { + throw new IOException("Wrong method called"); + } + + public void writeFields() { + called[18] = true; + } + + public PutField putFields() { + return new PutField() { + public void put(final String name, final boolean val) { + switch (name) { + case "boolean_" -> { + Assert.assertFalse(val); + called[0] = true; + } + case "final_boolean" -> { + Assert.assertTrue(val); + called[1] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + public void put(final String name, final byte val) { + switch (name) { + case "byte_" -> { + Assert.assertEquals(val, (byte) 0x44); + called[2] = true; + } + case "final_byte" -> { + Assert.assertEquals(val, (byte) 0x33); + called[3] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + public void put(final String name, final char val) { + switch (name) { + case "char_" -> { + Assert.assertEquals(val, (char) 0x6593); + called[4] = true; + } + case "final_char" -> { + Assert.assertEquals(val, (char) 0x5342); + called[5] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + public void put(final String name, final short val) { + switch (name) { + case "short_" -> { + Assert.assertEquals(val, (short) 0x3355); + called[6] = true; + } + case "final_short" -> { + Assert.assertEquals(val, (short) 0x2244); + called[7] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + public void put(final String name, final int val) { + switch (name) { + case "int_" -> { + Assert.assertEquals(val, 0x4928a299); + called[8] = true; + } + case "final_int" -> { + Assert.assertEquals(val, 0x05382716); + called[9] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + public void put(final String name, final long val) { + switch (name) { + case "long_" -> { + Assert.assertEquals(val, 0x24aa19883f4b9138L); + called[10] = true; + } + case "final_long" -> { + Assert.assertEquals(val, 0xf035a73b09113bacL); + called[11] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + public void put(final String name, final float val) { + switch (name) { + case "float_" -> { + Assert.assertEquals(val, 4321f); + called[12] = true; + } + case "final_float" -> { + Assert.assertEquals(val, 1234f); + called[13] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + public void put(final String name, final double val) { + switch (name) { + case "double_" -> { + Assert.assertEquals(val, 6543.0); + called[14] = true; + } + case "final_double" -> { + Assert.assertEquals(val, 3456.0); + called[15] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + public void put(final String name, final Object val) { + switch (name) { + case "ser" -> { + Assert.assertEquals(val, new Ser3(0x70b030a0)); + called[16] = true; + } + case "final_ser" -> { + Assert.assertEquals(val, new Ser3(0x004917aa)); + called[17] = true; + } + default -> throw new Error("Unexpected field " + name); + } + } + + @SuppressWarnings("removal") + public void write(final ObjectOutput out) throws IOException { + throw new IOException("Wrong method called"); + } + }; + } + }; + writeObject.invokeExact(ser, oos); + for (int i = 0; i < 19; i ++) { + Assert.assertTrue(called[i], names[i]); + } + // now, test the read side + MethodHandle readObject = factory.defaultReadObjectForSerialization(Ser2.class); + Assert.assertNotNull(readObject, "readObject not created"); + @SuppressWarnings("removal") + ObjectInputStream ois = new ObjectInputStream() { + protected Object readObjectOverride() throws IOException { + throw new IOException("Wrong method called"); + } + + public GetField readFields() { + return new GetField() { + public ObjectStreamClass getObjectStreamClass() { + throw new Error("Wrong method called"); + } + + public boolean defaulted(final String name) throws IOException { + throw new IOException("Wrong method called"); + } + + public boolean get(final String name, final boolean val) { + return switch (name) { + case "boolean_" -> { + called[0] = true; + yield true; + } + case "final_boolean" -> { + called[1] = true; + yield true; + } + default -> throw new Error("Unexpected field " + name); + }; + } + + public byte get(final String name, final byte val) { + return switch (name) { + case "byte_" -> { + called[2] = true; + yield (byte) 0x11; + } + case "final_byte" -> { + called[3] = true; + yield (byte) 0x9f; + } + default -> throw new Error("Unexpected field " + name); + }; + } + + public char get(final String name, final char val) { + return switch (name) { + case "char_" -> { + called[4] = true; + yield (char) 0x59a2; + } + case "final_char" -> { + called[5] = true; + yield (char) 0xe0d0; + } + default -> throw new Error("Unexpected field " + name); + }; + } + + public short get(final String name, final short val) { + return switch (name) { + case "short_" -> { + called[6] = true; + yield (short) 0x0917; + } + case "final_short" -> { + called[7] = true; + yield (short) 0x110e; + } + default -> throw new Error("Unexpected field " + name); + }; + } + + public int get(final String name, final int val) { + return switch (name) { + case "int_" -> { + called[8] = true; + yield 0xd0244e19; + } + case "final_int" -> { + called[9] = true; + yield 0x011004da; + } + default -> throw new Error("Unexpected field " + name); + }; + } + + public long get(final String name, final long val) { + return switch (name) { + case "long_" -> { + called[10] = true; + yield 0x0b8101d84aa31711L; + } + case "final_long" -> { + called[11] = true; + yield 0x30558aa7189ed821L; + } + default -> throw new Error("Unexpected field " + name); + }; + } + + public float get(final String name, final float val) { + return switch (name) { + case "float_" -> { + called[12] = true; + yield 0x5.01923ap18f; + } + case "final_float" -> { + called[13] = true; + yield 0x0.882afap1f; + } + default -> throw new Error("Unexpected field " + name); + }; + } + + public double get(final String name, final double val) { + return switch (name) { + case "double_" -> { + called[14] = true; + yield 0x9.4a8fp6; + } + case "final_double" -> { + called[15] = true; + yield 0xf.881a8p4; + } + default -> throw new Error("Unexpected field " + name); + }; + } + + public Object get(final String name, final Object val) { + return switch (name) { + case "ser" -> { + called[16] = true; + yield new Ser3(0x44cc55dd); + } + case "final_ser" -> { + called[17] = true; + yield new Ser3(0x9a8b7c6d); + } + default -> throw new Error("Unexpected field " + name); + }; + } + }; + } + }; + // all the same methods, except for `writeFields` + Arrays.fill(called, false); + Constructor<?> ctor = factory.newConstructorForSerialization(Ser2.class, Object.class.getDeclaredConstructor()); + ser = (Ser2) ctor.newInstance(); + readObject.invokeExact(ser, ois); + // excluding "writeFields", so 18 instead of 19 + for (int i = 0; i < 18; i ++) { + Assert.assertTrue(called[i], names[i]); + } + Assert.assertEquals(ser.byte_, (byte)0x11); + Assert.assertEquals(ser.final_byte, (byte)0x9f); + Assert.assertEquals(ser.char_, (char)0x59a2); + Assert.assertEquals(ser.final_char, (char)0xe0d0); + Assert.assertEquals(ser.short_, (short)0x0917); + Assert.assertEquals(ser.final_short, (short)0x110e); + Assert.assertEquals(ser.int_, 0xd0244e19); + Assert.assertEquals(ser.final_int, 0x011004da); + Assert.assertEquals(ser.long_, 0x0b8101d84aa31711L); + Assert.assertEquals(ser.final_long, 0x30558aa7189ed821L); + Assert.assertEquals(ser.float_, 0x5.01923ap18f); + Assert.assertEquals(ser.final_float, 0x0.882afap1f); + Assert.assertEquals(ser.double_, 0x9.4a8fp6); + Assert.assertEquals(ser.final_double, 0xf.881a8p4); + Assert.assertEquals(ser.ser, new Ser3(0x44cc55dd)); + Assert.assertEquals(ser.final_ser, new Ser3(0x9a8b7c6d)); + } + + static class Ser2 implements Serializable { + @Serial + private static final long serialVersionUID = -2852896623833548574L; + + byte byte_; + short short_; + char char_; + int int_; + long long_; + float float_; + double double_; + boolean boolean_; + Ser3 ser; + + final byte final_byte; + final short final_short; + final char final_char; + final int final_int; + final long final_long; + final float final_float; + final double final_double; + final boolean final_boolean; + final Ser3 final_ser; + + Ser2(final byte final_byte, final short final_short, final char final_char, final int final_int, + final long final_long, final float final_float, final double final_double, + final boolean final_boolean, final Ser3 final_ser) { + + this.final_byte = final_byte; + this.final_short = final_short; + this.final_char = final_char; + this.final_int = final_int; + this.final_long = final_long; + this.final_float = final_float; + this.final_double = final_double; + this.final_boolean = final_boolean; + this.final_ser = final_ser; + } + } + + static class Ser3 implements Serializable { + @Serial + private static final long serialVersionUID = -1234752876749422678L; + + @Serial + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("value", int.class) + }; + + final int value; + + Ser3(final int value) { + this.value = value; + } + + public boolean equals(final Object obj) { + return obj instanceof Ser3 s && value == s.value; + } + + public int hashCode() { + return value; + } + } + + static class SerInvalidFields implements Serializable { + // this is deliberately wrong + @SuppressWarnings({"unused", "serial"}) + @Serial + private static final String serialPersistentFields = "Oops!"; + @Serial + private static final long serialVersionUID = -8090960816811629489L; + } + + static class Ext1 implements Externalizable { + + @Serial + private static final long serialVersionUID = 7109990719266285013L; + + public void writeExternal(final ObjectOutput objectOutput) { + } + + public void readExternal(final ObjectInput objectInput) { + } + } + + static class Ext2 implements Externalizable { + public void writeExternal(final ObjectOutput objectOutput) { + } + + public void readExternal(final ObjectInput objectInput) { + } + } + + record Rec1(int hello, boolean world) implements Serializable { + @Serial + private static final long serialVersionUID = 12349876L; + } + + enum Enum1 { + hello, + world, + ; + private static final long serialVersionUID = 1020304050L; + } + + interface Proxy1 { + void hello(); + } + + static class SerialPersistentFields implements Serializable { + @Serial + private static final long serialVersionUID = -4947917866973382882L; + @Serial + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("array1", Object[].class), + new ObjectStreamField("nonExistent", String.class) + }; + + private int int1; + private Object[] array1; + } + + // Check our simple accessors + @Test + static void testAccessors() { + Assert.assertEquals(factory.serialPersistentFields(Ser3.class), Ser3.serialPersistentFields); + Assert.assertNotSame(factory.serialPersistentFields(Ser3.class), Ser3.serialPersistentFields); + Assert.assertNull(factory.serialPersistentFields(SerInvalidFields.class)); + } + + // Ensure that classes with serialPersistentFields do not allow default setting/getting + @Test + static void testDisallowed() { + Assert.assertNull(factory.defaultWriteObjectForSerialization(SerialPersistentFields.class)); + Assert.assertNull(factory.defaultReadObjectForSerialization(SerialPersistentFields.class)); + } + // Main can be used to run the tests from the command line with only testng.jar. @SuppressWarnings("raw_types") @Test(enabled = false) diff --git a/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java b/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java new file mode 100644 index 00000000000..3f428e458ca --- /dev/null +++ b/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSession; + +/** + * This is not a test. Actual tests are implemented by concrete subclasses. + * The abstract class AbstractDisableCipherSuites provides a base framework + * for testing cipher suite disablement. + */ +public abstract class AbstractDisableCipherSuites { + + private static final byte RECTYPE_HS = 0x16; + private static final byte HSMSG_CLIHELLO = 0x01; + private static final ByteBuffer CLIOUTBUF = + ByteBuffer.wrap("Client Side".getBytes()); + + /** + * Create an engine with the default set of cipher suites enabled and make + * sure none of the disabled suites are present in the client hello. + * + * @param disabledSuiteIds the {@code List} of disabled cipher suite IDs + * to be checked for. + * + * @return true if the test passed (No disabled suites), false otherwise + */ + protected boolean testDefaultCase(List<Integer> disabledSuiteIds) + throws Exception { + System.err.println("\nTest: Default SSLEngine suite set"); + SSLEngine ssle = makeEngine(); + if (getDebug()) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (getDebug()) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + boolean foundSuite = areSuitesPresentCH(cTOs, disabledSuiteIds); + if (foundSuite) { + System.err.println("FAIL: Found disabled suites!"); + return false; + } else { + System.err.println("PASS: No disabled suites found."); + return true; + } + } + + /** + * Create an engine and set only disabled cipher suites. + * The engine should not create the client hello message since the only + * available suites to assert in the client hello are disabled ones. + * + * @param disabledSuiteNames an array of cipher suite names that + * should be disabled cipher suites. + * + * @return true if the engine throws SSLHandshakeException during client + * hello creation, false otherwise. + */ + protected boolean testEngOnlyDisabled(String[] disabledSuiteNames) + throws Exception { + System.err.println( + "\nTest: SSLEngine configured with only disabled suites"); + try { + SSLEngine ssle = makeEngine(); + ssle.setEnabledCipherSuites(disabledSuiteNames); + if (getDebug()) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (getDebug()) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + } catch (SSLHandshakeException shse) { + System.err.println("PASS: Caught expected exception: " + shse); + return true; + } + System.err.println("FAIL: Expected SSLHandshakeException not thrown"); + return false; + } + + /** + * Create an engine and add some disabled suites to the default + * set of cipher suites. Make sure none of the disabled suites show up + * in the client hello even though they were explicitly added. + * + * @param disabledNames an array of cipher suite names that + * should be disabled cipher suites. + * @param disabledIds the {@code List} of disabled cipher suite IDs + * to be checked for. + * + * @return true if the test passed (No disabled suites), false otherwise + */ + protected boolean testEngAddDisabled(String[] disabledNames, + List<Integer> disabledIds) throws Exception { + System.err.println("\nTest: SSLEngine with disabled suites added"); + SSLEngine ssle = makeEngine(); + + // Add disabled suites to the existing engine's set of enabled suites + String[] initialSuites = ssle.getEnabledCipherSuites(); + String[] plusDisSuites = Arrays.copyOf(initialSuites, + initialSuites.length + disabledNames.length); + System.arraycopy(disabledNames, 0, plusDisSuites, + initialSuites.length, disabledNames.length); + ssle.setEnabledCipherSuites(plusDisSuites); + + if (getDebug()) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (getDebug()) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + boolean foundDisabled = areSuitesPresentCH(cTOs, disabledIds); + if (foundDisabled) { + System.err.println("FAIL: Found disabled suites!"); + return false; + } else { + System.err.println("PASS: No disabled suites found."); + return true; + } + } + + protected String getProtocol() { + return "TLSv1.2"; + } + + private SSLEngine makeEngine() throws GeneralSecurityException { + SSLContext ctx = SSLContext.getInstance(getProtocol()); + ctx.init(null, null, null); + return ctx.createSSLEngine(); + } + + private static ByteBuffer makeClientBuf(SSLEngine ssle) { + ssle.setUseClientMode(true); + ssle.setNeedClientAuth(false); + SSLSession sess = ssle.getSession(); + ByteBuffer cTOs = ByteBuffer.allocateDirect(sess.getPacketBufferSize()); + return cTOs; + } + + private static void listCiphers(String prefix, SSLEngine ssle) { + System.err.println(prefix + "\n---------------"); + String[] suites = ssle.getEnabledCipherSuites(); + for (String suite : suites) { + System.err.println(suite); + } + System.err.println("---------------"); + } + + /** + * Walk a TLS 1.2 or earlier ClientHello looking for any of the suites + * in the suiteIdList. + * + * @param clientHello a ByteBuffer containing the ClientHello message as + * a complete TLS record. The position of the buffer should be + * at the first byte of the TLS record header. + * @param suiteIdList a List of integer values corresponding to + * TLS cipher suite identifiers. + * + * @return true if at least one of the suites in {@code suiteIdList} + * is found in the ClientHello's cipher suite list + * + * @throws IOException if the data in the {@code clientHello} + * buffer is not a TLS handshake message or is not a client hello. + */ + private boolean areSuitesPresentCH(ByteBuffer clientHello, + List<Integer> suiteIdList) throws IOException { + byte val; + + // Process the TLS Record + val = clientHello.get(); + if (val != RECTYPE_HS) { + throw new IOException( + "Not a handshake record, type = " + val); + } + + // Just skip over the version and length + clientHello.position(clientHello.position() + 4); + + // Check the handshake message type + val = clientHello.get(); + if (val != HSMSG_CLIHELLO) { + throw new IOException( + "Not a ClientHello handshake message, type = " + val); + } + + // Skip over the length + clientHello.position(clientHello.position() + 3); + + // Skip over the protocol version (2) and random (32); + clientHello.position(clientHello.position() + 34); + + // Skip past the session ID (variable length <= 32) + int len = Byte.toUnsignedInt(clientHello.get()); + if (len > 32) { + throw new IOException("Session ID is too large, len = " + len); + } + clientHello.position(clientHello.position() + len); + + // Finally, we are at the cipher suites. Walk the list and place them + // into a List. + int csLen = Short.toUnsignedInt(clientHello.getShort()); + if (csLen % 2 != 0) { + throw new IOException("CipherSuite length is invalid, len = " + + csLen); + } + int csCount = csLen / 2; + List<Integer> csSuiteList = new ArrayList<>(csCount); + log("Found following suite IDs in hello:"); + for (int i = 0; i < csCount; i++) { + int curSuite = Short.toUnsignedInt(clientHello.getShort()); + log(String.format("Suite ID: 0x%04x", curSuite)); + csSuiteList.add(curSuite); + } + + // Now check to see if any of the suites passed in match what is in + // the suite list. + boolean foundMatch = false; + for (Integer cs : suiteIdList) { + if (csSuiteList.contains(cs)) { + System.err.format("Found match for suite ID 0x%04x\n", cs); + foundMatch = true; + break; + } + } + + // We don't care about the rest of the ClientHello message. + // Rewind and return whether we found a match or not. + clientHello.rewind(); + return foundMatch; + } + + private static void dumpResult(String str, SSLEngineResult result) { + System.err.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + HandshakeStatus hsStatus = result.getHandshakeStatus(); + System.err.println(str + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + System.err.println("\t...ready for application data"); + } + } + + private void log(String str) { + if (getDebug()) { + System.err.println(str); + } + } + + protected boolean getDebug() { + return false; + } +} diff --git a/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java b/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java index c9861324237..6b86dacc640 100644 --- a/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java +++ b/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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,21 +34,11 @@ */ import java.security.Security; -import javax.net.ssl.*; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.security.GeneralSecurityException; -import java.util.List; -import java.util.ArrayList; import java.util.Arrays; +import java.util.List; -public class NoDesRC4DesEdeCiphSuite { - - private static final boolean DEBUG = false; +public class NoDesRC4DesEdeCiphSuite extends AbstractDisableCipherSuites { - private static final byte RECTYPE_HS = 0x16; - private static final byte HSMSG_CLIHELLO = 0x01; // These are some groups of Cipher Suites by names and IDs private static final List<Integer> DES_CS_LIST = Arrays.asList( @@ -93,28 +83,27 @@ public class NoDesRC4DesEdeCiphSuite { "SSL_RSA_WITH_3DES_EDE_CBC_SHA" }; - private static final ByteBuffer CLIOUTBUF = - ByteBuffer.wrap("Client Side".getBytes()); public static void main(String[] args) throws Exception { boolean allGood = true; String disAlg = Security.getProperty("jdk.tls.disabledAlgorithms"); System.err.println("Disabled Algs: " + disAlg); + NoDesRC4DesEdeCiphSuite test = new NoDesRC4DesEdeCiphSuite(); // Disabled DES tests - allGood &= testDefaultCase(DES_CS_LIST); - allGood &= testEngAddDisabled(DES_CS_LIST_NAMES, DES_CS_LIST); - allGood &= testEngOnlyDisabled(DES_CS_LIST_NAMES); + allGood &= test.testDefaultCase(DES_CS_LIST); + allGood &= test.testEngAddDisabled(DES_CS_LIST_NAMES, DES_CS_LIST); + allGood &= test.testEngOnlyDisabled(DES_CS_LIST_NAMES); // Disabled RC4 tests - allGood &= testDefaultCase(RC4_CS_LIST); - allGood &= testEngAddDisabled(RC4_CS_LIST_NAMES, RC4_CS_LIST); - allGood &= testEngOnlyDisabled(RC4_CS_LIST_NAMES); + allGood &= test.testDefaultCase(RC4_CS_LIST); + allGood &= test.testEngAddDisabled(RC4_CS_LIST_NAMES, RC4_CS_LIST); + allGood &= test.testEngOnlyDisabled(RC4_CS_LIST_NAMES); // Disabled 3DES tests - allGood &= testDefaultCase(DESEDE_CS_LIST); - allGood &= testEngAddDisabled(DESEDE_CS_LIST_NAMES, DESEDE_CS_LIST); - allGood &= testEngOnlyDisabled(DESEDE_CS_LIST_NAMES); + allGood &= test.testDefaultCase(DESEDE_CS_LIST); + allGood &= test.testEngAddDisabled(DESEDE_CS_LIST_NAMES, DESEDE_CS_LIST); + allGood &= test.testEngOnlyDisabled(DESEDE_CS_LIST_NAMES); if (allGood) { System.err.println("All tests passed"); @@ -122,242 +111,4 @@ public static void main(String[] args) throws Exception { throw new RuntimeException("One or more tests failed"); } } - - /** - * Create an engine with the default set of cipher suites enabled and make - * sure none of the disabled suites are present in the client hello. - * - * @param disabledSuiteIds the {@code List} of disabled cipher suite IDs - * to be checked for. - * - * @return true if the test passed (No disabled suites), false otherwise - */ - private static boolean testDefaultCase(List<Integer> disabledSuiteIds) - throws Exception { - System.err.println("\nTest: Default SSLEngine suite set"); - SSLEngine ssle = makeEngine(); - if (DEBUG) { - listCiphers("Suite set upon creation", ssle); - } - SSLEngineResult clientResult; - ByteBuffer cTOs = makeClientBuf(ssle); - clientResult = ssle.wrap(CLIOUTBUF, cTOs); - if (DEBUG) { - dumpResult("ClientHello: ", clientResult); - } - cTOs.flip(); - boolean foundSuite = areSuitesPresentCH(cTOs, disabledSuiteIds); - if (foundSuite) { - System.err.println("FAIL: Found disabled suites!"); - return false; - } else { - System.err.println("PASS: No disabled suites found."); - return true; - } - } - - /** - * Create an engine and set only disabled cipher suites. - * The engine should not create the client hello message since the only - * available suites to assert in the client hello are disabled ones. - * - * @param disabledSuiteNames an array of cipher suite names that - * should be disabled cipher suites. - * - * @return true if the engine throws SSLHandshakeException during client - * hello creation, false otherwise. - */ - private static boolean testEngOnlyDisabled(String[] disabledSuiteNames) - throws Exception { - System.err.println( - "\nTest: SSLEngine configured with only disabled suites"); - try { - SSLEngine ssle = makeEngine(); - ssle.setEnabledCipherSuites(disabledSuiteNames); - if (DEBUG) { - listCiphers("Suite set upon creation", ssle); - } - SSLEngineResult clientResult; - ByteBuffer cTOs = makeClientBuf(ssle); - clientResult = ssle.wrap(CLIOUTBUF, cTOs); - if (DEBUG) { - dumpResult("ClientHello: ", clientResult); - } - cTOs.flip(); - } catch (SSLHandshakeException shse) { - System.err.println("PASS: Caught expected exception: " + shse); - return true; - } - System.err.println("FAIL: Expected SSLHandshakeException not thrown"); - return false; - } - - /** - * Create an engine and add some disabled suites to the default - * set of cipher suites. Make sure none of the disabled suites show up - * in the client hello even though they were explicitly added. - * - * @param disabledSuiteNames an array of cipher suite names that - * should be disabled cipher suites. - * @param disabledIds the {@code List} of disabled cipher suite IDs - * to be checked for. - * - * @return true if the test passed (No disabled suites), false otherwise - */ - private static boolean testEngAddDisabled(String[] disabledNames, - List<Integer> disabledIds) throws Exception { - System.err.println("\nTest: SSLEngine with disabled suites added"); - SSLEngine ssle = makeEngine(); - - // Add disabled suites to the existing engine's set of enabled suites - String[] initialSuites = ssle.getEnabledCipherSuites(); - String[] plusDisSuites = Arrays.copyOf(initialSuites, - initialSuites.length + disabledNames.length); - System.arraycopy(disabledNames, 0, plusDisSuites, - initialSuites.length, disabledNames.length); - ssle.setEnabledCipherSuites(plusDisSuites); - - if (DEBUG) { - listCiphers("Suite set upon creation", ssle); - } - SSLEngineResult clientResult; - ByteBuffer cTOs = makeClientBuf(ssle); - clientResult = ssle.wrap(CLIOUTBUF, cTOs); - if (DEBUG) { - dumpResult("ClientHello: ", clientResult); - } - cTOs.flip(); - boolean foundDisabled = areSuitesPresentCH(cTOs, disabledIds); - if (foundDisabled) { - System.err.println("FAIL: Found disabled suites!"); - return false; - } else { - System.err.println("PASS: No disabled suites found."); - return true; - } - } - - private static SSLEngine makeEngine() throws GeneralSecurityException { - SSLContext ctx = SSLContext.getInstance("TLSv1.2"); - ctx.init(null, null, null); - return ctx.createSSLEngine(); - } - - private static ByteBuffer makeClientBuf(SSLEngine ssle) { - ssle.setUseClientMode(true); - ssle.setNeedClientAuth(false); - SSLSession sess = ssle.getSession(); - ByteBuffer cTOs = ByteBuffer.allocateDirect(sess.getPacketBufferSize()); - return cTOs; - } - - private static void listCiphers(String prefix, SSLEngine ssle) { - System.err.println(prefix + "\n---------------"); - String[] suites = ssle.getEnabledCipherSuites(); - for (String suite : suites) { - System.err.println(suite); - } - System.err.println("---------------"); - } - - /** - * Walk a TLS 1.2 or earlier ClientHello looking for any of the suites - * in the suiteIdList. - * - * @param clientHello a ByteBuffer containing the ClientHello message as - * a complete TLS record. The position of the buffer should be - * at the first byte of the TLS record header. - * @param suiteIdList a List of integer values corresponding to - * TLS cipher suite identifiers. - * - * @return true if at least one of the suites in {@code suiteIdList} - * is found in the ClientHello's cipher suite list - * - * @throws IOException if the data in the {@code clientHello} - * buffer is not a TLS handshake message or is not a client hello. - */ - private static boolean areSuitesPresentCH(ByteBuffer clientHello, - List<Integer> suiteIdList) throws IOException { - byte val; - - // Process the TLS Record - val = clientHello.get(); - if (val != RECTYPE_HS) { - throw new IOException( - "Not a handshake record, type = " + val); - } - - // Just skip over the version and length - clientHello.position(clientHello.position() + 4); - - // Check the handshake message type - val = clientHello.get(); - if (val != HSMSG_CLIHELLO) { - throw new IOException( - "Not a ClientHello handshake message, type = " + val); - } - - // Skip over the length - clientHello.position(clientHello.position() + 3); - - // Skip over the protocol version (2) and random (32); - clientHello.position(clientHello.position() + 34); - - // Skip past the session ID (variable length <= 32) - int len = Byte.toUnsignedInt(clientHello.get()); - if (len > 32) { - throw new IOException("Session ID is too large, len = " + len); - } - clientHello.position(clientHello.position() + len); - - // Finally, we are at the cipher suites. Walk the list and place them - // into a List. - int csLen = Short.toUnsignedInt(clientHello.getShort()); - if (csLen % 2 != 0) { - throw new IOException("CipherSuite length is invalid, len = " + - csLen); - } - int csCount = csLen / 2; - List<Integer> csSuiteList = new ArrayList<>(csCount); - log("Found following suite IDs in hello:"); - for (int i = 0; i < csCount; i++) { - int curSuite = Short.toUnsignedInt(clientHello.getShort()); - log(String.format("Suite ID: 0x%04x", curSuite)); - csSuiteList.add(curSuite); - } - - // Now check to see if any of the suites passed in match what is in - // the suite list. - boolean foundMatch = false; - for (Integer cs : suiteIdList) { - if (csSuiteList.contains(cs)) { - System.err.format("Found match for suite ID 0x%04x\n", cs); - foundMatch = true; - break; - } - } - - // We don't care about the rest of the ClientHello message. - // Rewind and return whether we found a match or not. - clientHello.rewind(); - return foundMatch; - } - - private static void dumpResult(String str, SSLEngineResult result) { - System.err.println("The format of the SSLEngineResult is: \n" + - "\t\"getStatus() / getHandshakeStatus()\" +\n" + - "\t\"bytesConsumed() / bytesProduced()\"\n"); - HandshakeStatus hsStatus = result.getHandshakeStatus(); - System.err.println(str + result.getStatus() + "/" + hsStatus + ", " + - result.bytesConsumed() + "/" + result.bytesProduced() + " bytes"); - if (hsStatus == HandshakeStatus.FINISHED) { - System.err.println("\t...ready for application data"); - } - } - - private static void log(String str) { - if (DEBUG) { - System.err.println(str); - } - } } diff --git a/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java b/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java new file mode 100644 index 00000000000..57919da9a5a --- /dev/null +++ b/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, 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 8341964 + * @summary Add mechanism to disable different parts of TLS cipher suite + * @run testng/othervm TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite + */ + +import static org.testng.AssertJUnit.assertTrue; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.security.Security; +import java.util.List; + +public class TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite extends + AbstractDisableCipherSuites { + + private static final String SECURITY_PROPERTY = "jdk.tls.disabledAlgorithms"; + private static final String TEST_ALGORITHMS = + "TLS_RSA_*," + + " TLS_ECDH*WITH_AES_256_GCM_*," + + " TLS_*_anon_WITH_AES_*_SHA," + + " TLS_.*"; // This pattern should not disable anything + private static final String[] CIPHER_SUITES = new String[] { + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_DH_anon_WITH_AES_128_CBC_SHA", + "TLS_ECDH_anon_WITH_AES_256_CBC_SHA" + }; + static final List<Integer> CIPHER_SUITES_IDS = List.of( + 0x009D, + 0x009C, + 0x003D, + 0xC02E, + 0xC02C, + 0x0034, + 0xC018 + ); + + @BeforeTest + void setUp() throws Exception { + Security.setProperty(SECURITY_PROPERTY, TEST_ALGORITHMS); + } + + @Test + public void testDefault() throws Exception { + assertTrue(testDefaultCase(CIPHER_SUITES_IDS)); + } + + @Test + public void testAddDisabled() throws Exception { + assertTrue(testEngAddDisabled(CIPHER_SUITES, CIPHER_SUITES_IDS)); + } + + @Test + public void testOnlyDisabled() throws Exception { + assertTrue(testEngOnlyDisabled(CIPHER_SUITES)); + } +} diff --git a/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java b/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java new file mode 100644 index 00000000000..d9894868337 --- /dev/null +++ b/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024, 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 8341964 + * @summary Add mechanism to disable different parts of TLS cipher suite + * @run testng/othervm TLSCipherSuiteWildCardMatchingIllegalArgument + */ + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.fail; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.security.Security; + +import javax.net.ssl.SSLContext; + +/** + * SSLContext loads "jdk.tls.disabledAlgorithms" system property statically + * when it's being loaded into memory, so we can't call + * Security.setProperty("jdk.tls.disabledAlgorithms") more than once per test + * class. Thus, we need a separate test class each time we need to modify + * "jdk.tls.disabledAlgorithms" config value for testing. + */ +public class TLSCipherSuiteWildCardMatchingIllegalArgument { + + private static final String SECURITY_PROPERTY = + "jdk.tls.disabledAlgorithms"; + private static final String TEST_ALGORITHMS = "ECDHE_*_WITH_AES_256_GCM_*"; + + @BeforeTest + void setUp() throws Exception { + Security.setProperty(SECURITY_PROPERTY, TEST_ALGORITHMS); + } + + @Test + public void testChainedBefore() throws Exception { + try { + SSLContext.getInstance("TLS"); + fail("No IllegalArgumentException was thrown"); + } catch (ExceptionInInitializerError e) { + assertEquals(IllegalArgumentException.class, + e.getCause().getClass()); + assertEquals("Wildcard pattern must start with \"TLS_\"", + e.getCause().getMessage()); + } + } +} diff --git a/test/jdk/tools/jlink/runtimeImage/AddOptionsTest.java b/test/jdk/tools/jlink/runtimeImage/AddOptionsTest.java index 1ffe1240d07..827f7da624d 100644 --- a/test/jdk/tools/jlink/runtimeImage/AddOptionsTest.java +++ b/test/jdk/tools/jlink/runtimeImage/AddOptionsTest.java @@ -40,7 +40,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g AddOptionsTest + * @run main/othervm -Xmx1400m AddOptionsTest */ public class AddOptionsTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/BasicJlinkMissingJavaBase.java b/test/jdk/tools/jlink/runtimeImage/BasicJlinkMissingJavaBase.java index b0d2a2d66f5..ebf5b060665 100644 --- a/test/jdk/tools/jlink/runtimeImage/BasicJlinkMissingJavaBase.java +++ b/test/jdk/tools/jlink/runtimeImage/BasicJlinkMissingJavaBase.java @@ -41,7 +41,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g BasicJlinkMissingJavaBase + * @run main/othervm -Xmx1400m BasicJlinkMissingJavaBase */ public class BasicJlinkMissingJavaBase extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/BasicJlinkTest.java b/test/jdk/tools/jlink/runtimeImage/BasicJlinkTest.java index b97ebff9b49..8cbd74e5ed1 100644 --- a/test/jdk/tools/jlink/runtimeImage/BasicJlinkTest.java +++ b/test/jdk/tools/jlink/runtimeImage/BasicJlinkTest.java @@ -39,7 +39,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g BasicJlinkTest false + * @run main/othervm -Xmx1400m BasicJlinkTest false */ public class BasicJlinkTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/CustomModuleJlinkTest.java b/test/jdk/tools/jlink/runtimeImage/CustomModuleJlinkTest.java index 369bccfecfc..d6c237a173b 100644 --- a/test/jdk/tools/jlink/runtimeImage/CustomModuleJlinkTest.java +++ b/test/jdk/tools/jlink/runtimeImage/CustomModuleJlinkTest.java @@ -39,7 +39,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g CustomModuleJlinkTest + * @run main/othervm -Xmx1400m CustomModuleJlinkTest */ public class CustomModuleJlinkTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/GenerateJLIClassesTest.java b/test/jdk/tools/jlink/runtimeImage/GenerateJLIClassesTest.java index 533a8db30d0..e59d18bd6f0 100644 --- a/test/jdk/tools/jlink/runtimeImage/GenerateJLIClassesTest.java +++ b/test/jdk/tools/jlink/runtimeImage/GenerateJLIClassesTest.java @@ -39,7 +39,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g GenerateJLIClassesTest + * @run main/othervm -Xmx1400m GenerateJLIClassesTest */ public class GenerateJLIClassesTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/JavaSEReproducibleTest.java b/test/jdk/tools/jlink/runtimeImage/JavaSEReproducibleTest.java index d923358aed9..a376d075ecd 100644 --- a/test/jdk/tools/jlink/runtimeImage/JavaSEReproducibleTest.java +++ b/test/jdk/tools/jlink/runtimeImage/JavaSEReproducibleTest.java @@ -40,7 +40,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g JavaSEReproducibleTest + * @run main/othervm -Xmx1400m JavaSEReproducibleTest */ public class JavaSEReproducibleTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/KeepPackagedModulesFailTest.java b/test/jdk/tools/jlink/runtimeImage/KeepPackagedModulesFailTest.java index 8094579ecd5..6fdaf5a9824 100644 --- a/test/jdk/tools/jlink/runtimeImage/KeepPackagedModulesFailTest.java +++ b/test/jdk/tools/jlink/runtimeImage/KeepPackagedModulesFailTest.java @@ -41,7 +41,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g KeepPackagedModulesFailTest + * @run main/othervm -Xmx1400m KeepPackagedModulesFailTest */ public class KeepPackagedModulesFailTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/ModifiedFilesExitTest.java b/test/jdk/tools/jlink/runtimeImage/ModifiedFilesExitTest.java index 709494b6256..90abe14c214 100644 --- a/test/jdk/tools/jlink/runtimeImage/ModifiedFilesExitTest.java +++ b/test/jdk/tools/jlink/runtimeImage/ModifiedFilesExitTest.java @@ -40,7 +40,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g ModifiedFilesExitTest + * @run main/othervm -Xmx1400m ModifiedFilesExitTest */ public class ModifiedFilesExitTest extends ModifiedFilesTest { diff --git a/test/jdk/tools/jlink/runtimeImage/ModifiedFilesWarningTest.java b/test/jdk/tools/jlink/runtimeImage/ModifiedFilesWarningTest.java index f52691dd859..935d80dee4f 100644 --- a/test/jdk/tools/jlink/runtimeImage/ModifiedFilesWarningTest.java +++ b/test/jdk/tools/jlink/runtimeImage/ModifiedFilesWarningTest.java @@ -39,7 +39,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g ModifiedFilesWarningTest + * @run main/othervm -Xmx1400m ModifiedFilesWarningTest */ public class ModifiedFilesWarningTest extends ModifiedFilesTest { diff --git a/test/jdk/tools/jlink/runtimeImage/MultiHopTest.java b/test/jdk/tools/jlink/runtimeImage/MultiHopTest.java index 88f91f238bd..0e2cabe7425 100644 --- a/test/jdk/tools/jlink/runtimeImage/MultiHopTest.java +++ b/test/jdk/tools/jlink/runtimeImage/MultiHopTest.java @@ -40,7 +40,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g MultiHopTest + * @run main/othervm -Xmx1400m MultiHopTest */ public class MultiHopTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/PackagedModulesVsRuntimeImageLinkTest.java b/test/jdk/tools/jlink/runtimeImage/PackagedModulesVsRuntimeImageLinkTest.java index 9910be5f919..d276e80702b 100644 --- a/test/jdk/tools/jlink/runtimeImage/PackagedModulesVsRuntimeImageLinkTest.java +++ b/test/jdk/tools/jlink/runtimeImage/PackagedModulesVsRuntimeImageLinkTest.java @@ -49,7 +49,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g PackagedModulesVsRuntimeImageLinkTest + * @run main/othervm/timeout=1200 -Xmx1400m PackagedModulesVsRuntimeImageLinkTest */ public class PackagedModulesVsRuntimeImageLinkTest extends AbstractLinkableRuntimeTest { @@ -76,6 +76,7 @@ void runTest(Helper helper, boolean isLinkableRuntime) throws Exception { .output(helper.createNewImageDir("java-se-jmodfull")) .addMods("java.se").call().assertSuccess(); + System.out.println("Now comparing jmod-less and jmod-full) images"); compareRecursively(javaSEruntimeLink, javaSEJmodFull); } diff --git a/test/jdk/tools/jlink/runtimeImage/PatchedJDKModuleJlinkTest.java b/test/jdk/tools/jlink/runtimeImage/PatchedJDKModuleJlinkTest.java index 3baa824e049..f83c4c698f1 100644 --- a/test/jdk/tools/jlink/runtimeImage/PatchedJDKModuleJlinkTest.java +++ b/test/jdk/tools/jlink/runtimeImage/PatchedJDKModuleJlinkTest.java @@ -42,7 +42,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g PatchedJDKModuleJlinkTest + * @run main/othervm -Xmx1400m PatchedJDKModuleJlinkTest */ public class PatchedJDKModuleJlinkTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/SystemModulesTest.java b/test/jdk/tools/jlink/runtimeImage/SystemModulesTest.java index fac8cac112d..d0a6234eec0 100644 --- a/test/jdk/tools/jlink/runtimeImage/SystemModulesTest.java +++ b/test/jdk/tools/jlink/runtimeImage/SystemModulesTest.java @@ -41,7 +41,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g SystemModulesTest + * @run main/othervm -Xmx1400m SystemModulesTest */ public class SystemModulesTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/SystemModulesTest2.java b/test/jdk/tools/jlink/runtimeImage/SystemModulesTest2.java index 6be4ad7321c..ee22a55f3a7 100644 --- a/test/jdk/tools/jlink/runtimeImage/SystemModulesTest2.java +++ b/test/jdk/tools/jlink/runtimeImage/SystemModulesTest2.java @@ -42,7 +42,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1g SystemModulesTest2 + * @run main/othervm -Xmx1400m SystemModulesTest2 */ public class SystemModulesTest2 extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jpackage/TEST.properties b/test/jdk/tools/jpackage/TEST.properties index e01036f0ed3..a34532d6695 100644 --- a/test/jdk/tools/jpackage/TEST.properties +++ b/test/jdk/tools/jpackage/TEST.properties @@ -12,4 +12,6 @@ maxOutputSize=2000000 exclusiveAccess.dirs=share windows modules=jdk.jpackage/jdk.jpackage.internal:+open \ + jdk.jpackage/jdk.jpackage.internal.util \ + jdk.jpackage/jdk.jpackage.internal.util.function \ java.base/jdk.internal.util diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java new file mode 100644 index 00000000000..230b14fd1ea --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.test; + +import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; +import java.lang.reflect.Method; +import java.nio.file.Path; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import static java.util.stream.Collectors.toMap; +import java.util.stream.Stream; +import jdk.internal.util.OperatingSystem; +import static jdk.internal.util.OperatingSystem.LINUX; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterSupplier; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.Annotations.Test; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; + +/* + * @test + * @summary Test jpackage test library's annotation processor + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.* + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.AnnotationsTest + */ +public class AnnotationsTest { + + public static void main(String... args) { + runTests(BasicTest.class, ParameterizedInstanceTest.class); + for (var os : OperatingSystem.values()) { + try { + TestBuilderConfig.setOperatingSystem(os); + TKit.log("Current operating system: " + os); + runTests(IfOSTest.class); + } finally { + TestBuilderConfig.setDefaults(); + } + } + } + + public static class BasicTest extends TestExecutionRecorder { + @Test + public void testNoArg() { + recordTestCase(); + } + + @Test + @Parameter("TRUE") + public int testNoArg(boolean v) { + recordTestCase(v); + return 0; + } + + @Test + @Parameter({}) + @Parameter("a") + @Parameter({"b", "c"}) + public void testVarArg(Path ... paths) { + recordTestCase((Object[]) paths); + } + + @Test + @Parameter({"12", "foo"}) + @Parameter({"-89", "bar", "more"}) + @Parameter({"-89", "bar", "more", "moore"}) + public void testVarArg2(int a, String b, String ... other) { + recordTestCase(a, b, other); + } + + @Test + @ParameterSupplier("dateSupplier") + @ParameterSupplier("jdk.jpackage.test.AnnotationsTest.dateSupplier") + public void testDates(LocalDate v) { + recordTestCase(v); + } + + public static Set<String> getExpectedTestDescs() { + return Set.of( + "().testNoArg()", + "().testNoArg(true)", + "().testVarArg()", + "().testVarArg(a)", + "().testVarArg(b, c)", + "().testVarArg2(-89, bar, [more, moore](length=2))", + "().testVarArg2(-89, bar, [more](length=1))", + "().testVarArg2(12, foo, [](length=0))", + "().testDates(2018-05-05)", + "().testDates(2018-07-11)", + "().testDates(2034-05-05)", + "().testDates(2056-07-11)" + ); + } + + public static Collection<Object[]> dateSupplier() { + return List.of(new Object[][] { + { LocalDate.parse("2018-05-05") }, + { LocalDate.parse("2018-07-11") }, + }); + } + } + + public static class ParameterizedInstanceTest extends TestExecutionRecorder { + public ParameterizedInstanceTest(String... args) { + super((Object[]) args); + } + + public ParameterizedInstanceTest(int o) { + super(o); + } + + public ParameterizedInstanceTest(int a, Boolean[] b, String c, String ... other) { + super(a, b, c, other); + } + + @Test + public void testNoArgs() { + recordTestCase(); + } + + @Test + @ParameterSupplier("jdk.jpackage.test.AnnotationsTest.dateSupplier") + public void testDates(LocalDate v) { + recordTestCase(v); + } + + @Test + @Parameter("a") + public static void staticTest(String arg) { + staticRecorder.recordTestCase(arg); + } + + @Parameters + public static Collection<Object[]> input() { + return List.of(new Object[][] { + {}, + {55, new Boolean[]{false, true, false}, "foo", "bar"}, + {78}, + }); + } + + @Parameters + public static Collection<Object[]> input2() { + return List.of(new Object[][] { + {51, new boolean[]{true, true, true}, "foo"}, + {33}, + {55, null, null }, + {55, null, null, "1" }, + }); + } + + public static Set<String> getExpectedTestDescs() { + return Set.of( + "().testNoArgs()", + "(33).testNoArgs()", + "(78).testNoArgs()", + "(55, [false, true, false](length=3), foo, [bar](length=1)).testNoArgs()", + "(51, [true, true, true](length=3), foo, [](length=0)).testNoArgs()", + "().testDates(2034-05-05)", + "().testDates(2056-07-11)", + "(33).testDates(2034-05-05)", + "(33).testDates(2056-07-11)", + "(51, [true, true, true](length=3), foo, [](length=0)).testDates(2034-05-05)", + "(51, [true, true, true](length=3), foo, [](length=0)).testDates(2056-07-11)", + "(55, [false, true, false](length=3), foo, [bar](length=1)).testDates(2034-05-05)", + "(55, [false, true, false](length=3), foo, [bar](length=1)).testDates(2056-07-11)", + "(78).testDates(2034-05-05)", + "(78).testDates(2056-07-11)", + "(55, null, null, [1](length=1)).testDates(2034-05-05)", + "(55, null, null, [1](length=1)).testDates(2056-07-11)", + "(55, null, null, [1](length=1)).testNoArgs()", + "(55, null, null, [](length=0)).testDates(2034-05-05)", + "(55, null, null, [](length=0)).testDates(2056-07-11)", + "(55, null, null, [](length=0)).testNoArgs()", + "().staticTest(a)" + ); + } + + private final static TestExecutionRecorder staticRecorder = new TestExecutionRecorder(ParameterizedInstanceTest.class); + } + + public static class IfOSTest extends TestExecutionRecorder { + public IfOSTest(int a, String b) { + super(a, b); + } + + @Test(ifOS = OperatingSystem.LINUX) + public void testNoArgs() { + recordTestCase(); + } + + @Test(ifNotOS = OperatingSystem.LINUX) + public void testNoArgs2() { + recordTestCase(); + } + + @Test + @Parameter(value = "foo", ifOS = OperatingSystem.LINUX) + @Parameter(value = {"foo", "bar"}, ifOS = { OperatingSystem.LINUX, OperatingSystem.MACOS }) + @Parameter(value = {}, ifNotOS = { OperatingSystem.WINDOWS }) + public void testVarArgs(String ... args) { + recordTestCase((Object[]) args); + } + + @Test + @ParameterSupplier(value = "jdk.jpackage.test.AnnotationsTest.dateSupplier", ifOS = OperatingSystem.WINDOWS) + public void testDates(LocalDate v) { + recordTestCase(v); + } + + @Parameters(ifOS = OperatingSystem.LINUX) + public static Collection<Object[]> input() { + return Set.of(new Object[][] { + {7, null}, + }); + } + + @Parameters(ifNotOS = {OperatingSystem.LINUX, OperatingSystem.MACOS}) + public static Collection<Object[]> input2() { + return Set.of(new Object[][] { + {10, "hello"}, + }); + } + + @Parameters(ifNotOS = OperatingSystem.LINUX) + public static Collection<Object[]> input3() { + return Set.of(new Object[][] { + {15, "bye"}, + }); + } + + public static Set<String> getExpectedTestDescs() { + switch (TestBuilderConfig.getDefault().getOperatingSystem()) { + case LINUX -> { + return Set.of( + "(7, null).testNoArgs()", + "(7, null).testVarArgs()", + "(7, null).testVarArgs(foo)", + "(7, null).testVarArgs(foo, bar)" + ); + } + + case MACOS -> { + return Set.of( + "(15, bye).testNoArgs2()", + "(15, bye).testVarArgs()", + "(15, bye).testVarArgs(foo, bar)" + ); + } + + case WINDOWS -> { + return Set.of( + "(15, bye).testDates(2034-05-05)", + "(15, bye).testDates(2056-07-11)", + "(15, bye).testNoArgs2()", + "(10, hello).testDates(2034-05-05)", + "(10, hello).testDates(2056-07-11)", + "(10, hello).testNoArgs2()" + ); + } + + case AIX -> { + return Set.of( + ); + } + } + + throw new UnsupportedOperationException(); + } + } + + public static Collection<Object[]> dateSupplier() { + return List.of(new Object[][] { + { LocalDate.parse("2034-05-05") }, + { LocalDate.parse("2056-07-11") }, + }); + } + + private static void runTests(Class<? extends TestExecutionRecorder>... tests) { + ACTUAL_TEST_DESCS.get().clear(); + + var expectedTestDescs = Stream.of(tests) + .map(AnnotationsTest::getExpectedTestDescs) + .flatMap(x -> x) + // Collect in the map to check for collisions for free + .collect(toMap(x -> x, x -> "")) + .keySet(); + + var args = Stream.of(tests).map(test -> { + return String.format("--jpt-run=%s", test.getName()); + }).toArray(String[]::new); + + try { + Main.main(args); + assertRecordedTestDescs(expectedTestDescs); + } catch (Throwable t) { + t.printStackTrace(System.err); + System.exit(1); + } + } + + private static Stream<String> getExpectedTestDescs(Class<?> type) { + return toSupplier(() -> { + var method = type.getMethod("getExpectedTestDescs"); + var testDescPefix = type.getName(); + return ((Set<String>)method.invoke(null)).stream().map(desc -> { + return testDescPefix + desc; + }); + }).get(); + } + + private static void assertRecordedTestDescs(Set<String> expectedTestDescs) { + var comm = Comm.compare(expectedTestDescs, ACTUAL_TEST_DESCS.get()); + if (!comm.unique1().isEmpty()) { + System.err.println("Missing test case signatures:"); + comm.unique1().stream().sorted().sequential().forEachOrdered(System.err::println); + System.err.println("<>"); + } + + if (!comm.unique2().isEmpty()) { + System.err.println("Unexpected test case signatures:"); + comm.unique2().stream().sorted().sequential().forEachOrdered(System.err::println); + System.err.println("<>"); + } + + if (!comm.unique2().isEmpty() || !comm.unique1().isEmpty()) { + // Don't use TKit asserts as this call is outside the test execution + throw new AssertionError("Test case signatures mismatched"); + } + } + + private static class TestExecutionRecorder { + protected TestExecutionRecorder(Object ... args) { + this.testClass = getClass(); + this.testDescBuilder = TestInstance.TestDesc.createBuilder().ctorArgs(args); + } + + TestExecutionRecorder(Class<?> testClass) { + this.testClass = testClass; + this.testDescBuilder = TestInstance.TestDesc.createBuilder().ctorArgs(); + } + + protected void recordTestCase(Object ... args) { + testDescBuilder.methodArgs(args).method(getCurrentTestCase()); + var testCaseDescs = ACTUAL_TEST_DESCS.get(); + var testCaseDesc = testDescBuilder.get().testFullName(); + TKit.assertTrue(!testCaseDescs.contains(testCaseDesc), String.format( + "Check this test case is executed for the first time", + testCaseDesc)); + TKit.assertTrue(!executed, "Check this test case instance is not reused"); + executed = true; + testCaseDescs.add(testCaseDesc); + } + + private Method getCurrentTestCase() { + return StackWalker.getInstance(RETAIN_CLASS_REFERENCE).walk(frames -> { + return frames.map(frame -> { + var methodType = frame.getMethodType(); + var methodName = frame.getMethodName(); + var methodReturn = methodType.returnType(); + var methodParameters = methodType.parameterArray(); + return Stream.of(testClass.getDeclaredMethods()).filter(method -> { + return method.getName().equals(methodName) + && method.getReturnType().equals(methodReturn) + && Arrays.equals(method.getParameterTypes(), methodParameters) + && method.isAnnotationPresent(Test.class); + }).findFirst(); + }).dropWhile(Optional::isEmpty).map(Optional::get).findFirst(); + }).get(); + } + + private boolean executed; + private final TestInstance.TestDesc.Builder testDescBuilder; + private final Class<?> testClass; + } + + private static final ThreadLocal<Set<String>> ACTUAL_TEST_DESCS = new ThreadLocal<>() { + @Override + protected Set<String> initialValue() { + return new HashSet<>(); + } + }; +} diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java index 3f55c3c50ae..98a7d873190 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java @@ -37,9 +37,9 @@ import java.util.stream.Stream; import jdk.jpackage.test.Annotations.Parameters; import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Functional.ThrowingRunnable; -import static jdk.jpackage.test.Functional.ThrowingRunnable.toRunnable; -import static jdk.jpackage.test.Functional.ThrowingSupplier.toSupplier; +import jdk.jpackage.internal.util.function.ThrowingRunnable; +import static jdk.jpackage.internal.util.function.ThrowingRunnable.toRunnable; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; public class TKitTest { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java index 6c388ac77ff..70b0e160d24 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,8 +37,9 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.test.Functional.ThrowingBiConsumer; -import static jdk.jpackage.test.Functional.ThrowingFunction.toFunction; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import jdk.jpackage.internal.util.function.ThrowingBiConsumer; +import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; public class AdditionalLauncher { @@ -48,12 +49,12 @@ public AdditionalLauncher(String name) { setPersistenceHandler(null); } - final public AdditionalLauncher setDefaultArguments(String... v) { + public final AdditionalLauncher setDefaultArguments(String... v) { defaultArguments = new ArrayList<>(List.of(v)); return this; } - final public AdditionalLauncher addDefaultArguments(String... v) { + public final AdditionalLauncher addDefaultArguments(String... v) { if (defaultArguments == null) { return setDefaultArguments(v); } @@ -62,12 +63,12 @@ final public AdditionalLauncher addDefaultArguments(String... v) { return this; } - final public AdditionalLauncher setJavaOptions(String... v) { + public final AdditionalLauncher setJavaOptions(String... v) { javaOptions = new ArrayList<>(List.of(v)); return this; } - final public AdditionalLauncher addJavaOptions(String... v) { + public final AdditionalLauncher addJavaOptions(String... v) { if (javaOptions == null) { return setJavaOptions(v); } @@ -76,27 +77,27 @@ final public AdditionalLauncher addJavaOptions(String... v) { return this; } - final public AdditionalLauncher setVerifyUninstalled(boolean value) { + public final AdditionalLauncher setVerifyUninstalled(boolean value) { verifyUninstalled = value; return this; } - final public AdditionalLauncher setLauncherAsService() { + public final AdditionalLauncher setLauncherAsService() { return addRawProperties(LAUNCHER_AS_SERVICE); } - final public AdditionalLauncher addRawProperties( + public final AdditionalLauncher addRawProperties( Map.Entry<String, String>... v) { return addRawProperties(List.of(v)); } - final public AdditionalLauncher addRawProperties( + public final AdditionalLauncher addRawProperties( Collection<Map.Entry<String, String>> v) { rawProperties.addAll(v); return this; } - final public String getRawPropertyValue( + public final String getRawPropertyValue( String key, Supplier<String> getDefault) { return rawProperties.stream() .filter(item -> item.getKey().equals(key)) @@ -108,13 +109,13 @@ private String getDesciption(JPackageCommand cmd) { "--description", unused -> cmd.name())); } - final public AdditionalLauncher setShortcuts(boolean menu, boolean shortcut) { + public final AdditionalLauncher setShortcuts(boolean menu, boolean shortcut) { withMenuShortcut = menu; withShortcut = shortcut; return this; } - final public AdditionalLauncher setIcon(Path iconPath) { + public final AdditionalLauncher setIcon(Path iconPath) { if (iconPath == NO_ICON) { throw new IllegalArgumentException(); } @@ -123,12 +124,12 @@ final public AdditionalLauncher setIcon(Path iconPath) { return this; } - final public AdditionalLauncher setNoIcon() { + public final AdditionalLauncher setNoIcon() { icon = NO_ICON; return this; } - final public AdditionalLauncher setPersistenceHandler( + public final AdditionalLauncher setPersistenceHandler( ThrowingBiConsumer<Path, List<Map.Entry<String, String>>> handler) { if (handler != null) { createFileHandler = ThrowingBiConsumer.toBiConsumer(handler); @@ -138,12 +139,12 @@ final public AdditionalLauncher setPersistenceHandler( return this; } - final public void applyTo(JPackageCommand cmd) { + public final void applyTo(JPackageCommand cmd) { cmd.addPrerequisiteAction(this::initialize); cmd.addVerifyAction(this::verify); } - final public void applyTo(PackageTest test) { + public final void applyTo(PackageTest test) { test.addInitializer(this::initialize); test.addInstallVerifier(this::verify); if (verifyUninstalled) { @@ -151,7 +152,7 @@ final public void applyTo(PackageTest test) { } } - final public void verifyRemovedInUpgrade(PackageTest test) { + public final void verifyRemovedInUpgrade(PackageTest test) { test.addInstallVerifier(this::verifyUninstalled); } @@ -189,7 +190,7 @@ private void initialize(JPackageCommand cmd) { propsFile = TKit.createTempFile(propsFile); TKit.deleteIfExists(propsFile); } catch (IOException ex) { - Functional.rethrowUnchecked(ex); + rethrowUnchecked(ex); } } @@ -446,7 +447,7 @@ private static String resolveVariables(JPackageCommand cmd, String str) { private Boolean withMenuShortcut; private Boolean withShortcut; - private final static Path NO_ICON = Path.of(""); - private final static Map.Entry<String, String> LAUNCHER_AS_SERVICE = Map.entry( + private static final Path NO_ICON = Path.of(""); + private static final Map.Entry<String, String> LAUNCHER_AS_SERVICE = Map.entry( "launcher-as-service", "true"); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Annotations.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Annotations.java index d29133ee3e1..ad1e77b4171 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Annotations.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Annotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -27,6 +27,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jdk.internal.util.OperatingSystem; public class Annotations { @@ -43,6 +44,14 @@ public class Annotations { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test { + + OperatingSystem[] ifOS() default { + OperatingSystem.LINUX, + OperatingSystem.WINDOWS, + OperatingSystem.MACOS + }; + + OperatingSystem[] ifNotOS() default {}; } @Retention(RetentionPolicy.RUNTIME) @@ -51,6 +60,14 @@ public class Annotations { public @interface Parameter { String[] value(); + + OperatingSystem[] ifOS() default { + OperatingSystem.LINUX, + OperatingSystem.WINDOWS, + OperatingSystem.MACOS + }; + + OperatingSystem[] ifNotOS() default {}; } @Retention(RetentionPolicy.RUNTIME) @@ -60,8 +77,39 @@ public class Annotations { Parameter[] value(); } + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + @Repeatable(ParameterSupplierGroup.class) + public @interface ParameterSupplier { + + String value(); + + OperatingSystem[] ifOS() default { + OperatingSystem.LINUX, + OperatingSystem.WINDOWS, + OperatingSystem.MACOS + }; + + OperatingSystem[] ifNotOS() default {}; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface ParameterSupplierGroup { + + ParameterSupplier[] value(); + } + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Parameters { + + OperatingSystem[] ifOS() default { + OperatingSystem.LINUX, + OperatingSystem.WINDOWS, + OperatingSystem.MACOS + }; + + OperatingSystem[] ifNotOS() default {}; } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedFormattedString.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedFormattedString.java new file mode 100644 index 00000000000..8b28049b7b1 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedFormattedString.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.test; + +import java.util.List; +import java.util.function.BiFunction; + +public final class CannedFormattedString { + + CannedFormattedString(BiFunction<String, Object[], String> formatter, + String key, Object[] args) { + this.formatter = formatter; + this.key = key; + this.args = args; + } + + public String getValue() { + return formatter.apply(key, args); + } + + @Override + public String toString() { + if (args.length == 0) { + return String.format("%s", key); + } else { + return String.format("%s+%s", key, List.of(args)); + } + } + + private final BiFunction<String, Object[], String> formatter; + private final String key; + private final Object[] args; +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Comm.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Comm.java new file mode 100644 index 00000000000..23798f326fe --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Comm.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.test; + +import java.util.HashSet; +import java.util.Set; + +record Comm<T>(Set<T> common, Set<T> unique1, Set<T> unique2) { + + static <T> Comm<T> compare(Set<T> a, Set<T> b) { + Set<T> common = new HashSet<>(a); + common.retainAll(b); + Set<T> unique1 = new HashSet<>(a); + unique1.removeAll(common); + Set<T> unique2 = new HashSet<>(b); + unique2.removeAll(common); + return new Comm(common, unique1, unique2); + } +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index 72ebb64a142..00f6ab5263c 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -42,7 +42,7 @@ import java.util.spi.ToolProvider; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.test.Functional.ThrowingSupplier; +import jdk.jpackage.internal.util.function.ThrowingSupplier; public final class Executor extends CommandArguments<Executor> { @@ -53,7 +53,7 @@ public static Executor of(String... cmdline) { public Executor() { saveOutputType = new HashSet<>(Set.of(SaveOutputType.NONE)); - removePath = false; + removePathEnvVar = false; } public Executor setExecutable(String v) { @@ -85,8 +85,8 @@ public Executor setExecutable(JavaTool v) { return setExecutable(v.getPath()); } - public Executor setRemovePath(boolean value) { - removePath = value; + public Executor setRemovePathEnvVar(boolean value) { + removePathEnvVar = value; return this; } @@ -348,7 +348,7 @@ private Result runExecutable() throws IOException, InterruptedException { builder.directory(directory.toFile()); sb.append(String.format("; in directory [%s]", directory)); } - if (removePath) { + if (removePathEnvVar) { // run this with cleared Path in Environment TKit.trace("Clearing PATH in environment"); builder.environment().remove("PATH"); @@ -478,7 +478,7 @@ private static void trace(String msg) { private Path executable; private Set<SaveOutputType> saveOutputType; private Path directory; - private boolean removePath; + private boolean removePathEnvVar; private String winTmpDir = null; private static enum SaveOutputType { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/FileAssociations.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/FileAssociations.java index 49085197828..091a2206b17 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/FileAssociations.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/FileAssociations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,10 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import jdk.jpackage.internal.IOUtils; +import jdk.jpackage.internal.util.PathUtils; -final public class FileAssociations { +public final class FileAssociations { public FileAssociations(String faSuffixName) { suffixName = faSuffixName; setFilename("fa"); @@ -79,7 +79,7 @@ Path getLinuxIconFileName() { if (icon == null) { return null; } - return Path.of(getMime().replace('/', '-') + IOUtils.getSuffix(icon)); + return Path.of(getMime().replace('/', '-') + PathUtils.getSuffix(icon)); } Path getPropertiesFile() { @@ -243,7 +243,7 @@ public static enum InvocationType { } private Path file; - final private String suffixName; + private final String suffixName; private String description; private Path icon; private Collection<TestRun> testRuns; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Functional.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Functional.java index a57caa92cb2..a974670b8e4 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Functional.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Functional.java @@ -31,84 +31,6 @@ public class Functional { - @FunctionalInterface - public interface ThrowingConsumer<T> { - void accept(T t) throws Throwable; - - public static <T> Consumer<T> toConsumer(ThrowingConsumer<T> v) { - return o -> { - try { - v.accept(o); - } catch (Throwable ex) { - rethrowUnchecked(ex); - } - }; - } - } - - @FunctionalInterface - public interface ThrowingBiConsumer<T, U> { - void accept(T t, U u) throws Throwable; - - public static <T, U> BiConsumer<T, U> toBiConsumer(ThrowingBiConsumer<T, U> v) { - return (t, u) -> { - try { - v.accept(t, u); - } catch (Throwable ex) { - rethrowUnchecked(ex); - } - }; - } - } - - @FunctionalInterface - public interface ThrowingSupplier<T> { - T get() throws Throwable; - - public static <T> Supplier<T> toSupplier(ThrowingSupplier<T> v) { - return () -> { - try { - return v.get(); - } catch (Throwable ex) { - rethrowUnchecked(ex); - } - // Unreachable - return null; - }; - } - } - - @FunctionalInterface - public interface ThrowingFunction<T, R> { - R apply(T t) throws Throwable; - - public static <T, R> Function<T, R> toFunction(ThrowingFunction<T, R> v) { - return (t) -> { - try { - return v.apply(t); - } catch (Throwable ex) { - rethrowUnchecked(ex); - } - // Unreachable - return null; - }; - } - } - - @FunctionalInterface - public interface ThrowingRunnable { - void run() throws Throwable; - - public static Runnable toRunnable(ThrowingRunnable v) { - return () -> { - try { - v.run(); - } catch (Throwable ex) { - rethrowUnchecked(ex); - } - }; - } - } public static <T> Supplier<T> identity(Supplier<T> v) { return v; @@ -141,28 +63,4 @@ public static <T> Predicate<T> identity(Predicate<T> v) { public static <T> Predicate<T> identityPredicate(Predicate<T> v) { return v; } - - public static class ExceptionBox extends RuntimeException { - public ExceptionBox(Throwable throwable) { - super(throwable); - } - } - - @SuppressWarnings("unchecked") - public static RuntimeException rethrowUnchecked(Throwable throwable) throws - ExceptionBox { - if (throwable instanceof RuntimeException err) { - throw err; - } - - if (throwable instanceof Error err) { - throw err; - } - - if (throwable instanceof InvocationTargetException err) { - throw rethrowUnchecked(err.getCause()); - } - - throw new ExceptionBox(throwable); - } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java index bc722e7acd9..0c7476e863d 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java @@ -40,9 +40,9 @@ import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import jdk.jpackage.test.Functional.ThrowingFunction; -import jdk.jpackage.test.Functional.ThrowingSupplier; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingFunction; +import jdk.jpackage.internal.util.function.ThrowingSupplier; public final class HelloApp { @@ -354,12 +354,12 @@ public static final class AppOutputVerifier { if (TKit.isWindows()) { // When running app launchers on Windows, clear users environment (JDK-8254920) - removePath(true); + removePathEnvVar(true); } } - public AppOutputVerifier removePath(boolean v) { - removePath = v; + public AppOutputVerifier removePathEnvVar(boolean v) { + removePathEnvVar = v; return this; } @@ -455,7 +455,7 @@ private Executor getExecutor(String...args) { Path outputFile = TKit.workDir().resolve(OUTPUT_FILENAME); ThrowingFunction.toFunction(Files::deleteIfExists).apply(outputFile); - final Path executablePath; + Path executablePath; if (launcherPath.isAbsolute()) { executablePath = launcherPath; } else { @@ -463,18 +463,27 @@ private Executor getExecutor(String...args) { executablePath = Path.of(".").resolve(launcherPath.normalize()); } + if (TKit.isWindows()) { + var absExecutablePath = executablePath.toAbsolutePath().normalize(); + var shortPath = WindowsHelper.toShortPath(absExecutablePath); + if (shortPath.isPresent()) { + TKit.trace(String.format("Will run [%s] as [%s]", executablePath, shortPath.get())); + executablePath = shortPath.get(); + } + } + final List<String> launcherArgs = List.of(args); return new Executor() .setDirectory(outputFile.getParent()) .saveOutput(saveOutput) .dumpOutput() - .setRemovePath(removePath) + .setRemovePathEnvVar(removePathEnvVar) .setExecutable(executablePath) .addArguments(launcherArgs); } private boolean launcherNoExit; - private boolean removePath; + private boolean removePathEnvVar; private boolean saveOutput; private final Path launcherPath; private Path outputFilePath; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index 9b25c9058d1..4239d8a87c8 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -45,15 +45,15 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.internal.IOUtils; import jdk.jpackage.internal.AppImageFile; import jdk.jpackage.internal.ApplicationLayout; import jdk.jpackage.internal.PackageFile; +import jdk.jpackage.internal.util.XmlUtils; import static jdk.jpackage.test.AdditionalLauncher.forEachAdditionalLauncher; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import jdk.jpackage.test.Functional.ThrowingFunction; -import jdk.jpackage.test.Functional.ThrowingRunnable; -import jdk.jpackage.test.Functional.ThrowingSupplier; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingFunction; +import jdk.jpackage.internal.util.function.ThrowingRunnable; +import jdk.jpackage.internal.util.function.ThrowingSupplier; /** * jpackage command line with prerequisite actions. Prerequisite actions can be @@ -78,6 +78,7 @@ public JPackageCommand(JPackageCommand cmd) { prerequisiteActions = new Actions(cmd.prerequisiteActions); verifyActions = new Actions(cmd.verifyActions); appLayoutAsserts = cmd.appLayoutAsserts; + outputValidator = cmd.outputValidator; executeInDirectory = cmd.executeInDirectory; } @@ -314,7 +315,7 @@ public void createJPackageXMLFile(String mainLauncher, String mainClass) "Error: --app-image expected"); })); - IOUtils.createXml(jpackageXMLFile, xml -> { + XmlUtils.createXml(jpackageXMLFile, xml -> { xml.writeStartElement("jpackage-state"); xml.writeAttribute("version", AppImageFile.getVersion()); xml.writeAttribute("platform", AppImageFile.getPlatform()); @@ -739,6 +740,24 @@ public JPackageCommand ignoreDefaultVerbose(boolean v) { return this; } + public JPackageCommand validateOutput(TKit.TextStreamVerifier validator) { + return JPackageCommand.this.validateOutput(validator::apply); + } + + public JPackageCommand validateOutput(Consumer<Stream<String>> validator) { + if (validator != null) { + saveConsoleOutput(true); + outputValidator = validator; + } else { + outputValidator = null; + } + return this; + } + + public JPackageCommand validateOutput(CannedFormattedString str) { + return JPackageCommand.this.validateOutput(TKit.assertTextStream(str.getValue())); + } + public boolean isWithToolProvider() { return Optional.ofNullable(withToolProvider).orElse( defaultWithToolProvider); @@ -817,6 +836,10 @@ public Executor.Result execute(int expectedExitCode) { .createExecutor() .execute(expectedExitCode); + if (outputValidator != null) { + outputValidator.accept(result.getOutput().stream()); + } + if (result.exitCode == 0) { executeVerifyActions(); } @@ -1187,6 +1210,7 @@ public void run() { private final Actions verifyActions; private Path executeInDirectory; private Set<AppLayoutAssert> appLayoutAsserts = Set.of(AppLayoutAssert.values()); + private Consumer<Stream<String>> outputValidator; private static boolean defaultWithToolProvider; private static final Map<String, PackageType> PACKAGE_TYPES = Functional.identity( diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java new file mode 100644 index 00000000000..4757f54fdfd --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.test; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.MessageFormat; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; + +public enum JPackageStringBundle { + + MAIN("jdk.jpackage.internal.I18N"), + ; + + JPackageStringBundle(String i18nClassName) { + try { + i18nClass = Class.forName(i18nClassName); + + i18nClass_getString = i18nClass.getDeclaredMethod("getString", String.class); + i18nClass_getString.setAccessible(true); + } catch (ClassNotFoundException|NoSuchMethodException ex) { + throw rethrowUnchecked(ex); + } + } + + /** + * Return a string value of the given key from jpackage resources. + */ + private String getString(String key) { + try { + return (String)i18nClass_getString.invoke(i18nClass, key); + } catch (IllegalAccessException|InvocationTargetException ex) { + throw rethrowUnchecked(ex); + } + } + + private String getFormattedString(String key, Object[] args) { + return MessageFormat.format(getString(key), args); + } + + public CannedFormattedString cannedFormattedString(String key, String ... args) { + return new CannedFormattedString(this::getFormattedString, key, args); + } + + private final Class<?> i18nClass; + private final Method i18nClass_getString; +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherAsServiceVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherAsServiceVerifier.java index 026da0df0eb..d73029ab153 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherAsServiceVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherAsServiceVerifier.java @@ -35,8 +35,10 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.internal.IOUtils; -import static jdk.jpackage.test.Functional.ThrowingConsumer.toConsumer; +import jdk.jpackage.internal.util.PathUtils; +import jdk.jpackage.internal.util.function.ThrowingBiConsumer; +import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; +import jdk.jpackage.internal.util.function.ThrowingRunnable; import static jdk.jpackage.test.PackageType.LINUX; import static jdk.jpackage.test.PackageType.MAC_PKG; import static jdk.jpackage.test.PackageType.WINDOWS; @@ -187,7 +189,7 @@ static List<String> getLaunchersAsServices(JPackageCommand cmd) { } AdditionalLauncher.forEachAdditionalLauncher(cmd, - Functional.ThrowingBiConsumer.toBiConsumer( + ThrowingBiConsumer.toBiConsumer( (launcherName, propFilePath) -> { if (Files.readAllLines(propFilePath).stream().anyMatch( line -> { @@ -335,14 +337,14 @@ private static void verifyMacDaemonPlistFile(JPackageCommand cmd, TKit.assertEquals(installedLauncherPath.toString(), args.get(0), "Check path to launcher in 'ProgramArguments' property in the property file"); - var expectedLabel = IOUtils.replaceSuffix(servicePlistFile.getFileName(), "").toString(); + var expectedLabel = PathUtils.replaceSuffix(servicePlistFile.getFileName(), "").toString(); TKit.assertEquals(expectedLabel, servicePlist.queryValue("Label"), "Check value of 'Label' property in the property file"); } private static void delayInstallVerify() { // Sleep a bit to let system launch the service - Functional.ThrowingRunnable.toRunnable(() -> Thread.sleep(5 * 1000)).run(); + ThrowingRunnable.toRunnable(() -> Thread.sleep(5 * 1000)).run(); } private Path appOutputFilePathInitialize() { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java index 2de2e002a94..39e483f1fee 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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,6 +31,7 @@ import java.nio.file.Path; import java.util.Optional; import javax.imageio.ImageIO; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; public final class LauncherIconVerifier { public LauncherIconVerifier() { @@ -176,7 +177,7 @@ private WinIconVerifier() { iconSwapWrapper.setAccessible(true); } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { - throw Functional.rethrowUnchecked(ex); + throw rethrowUnchecked(ex); } } @@ -254,14 +255,14 @@ private void setIcon(Path iconPath, Path launcherPath) { } } } catch (IllegalAccessException | InvocationTargetException ex) { - throw Functional.rethrowUnchecked(ex); + throw rethrowUnchecked(ex); } } finally { launcherPath.toFile().setWritable(false, true); } } - final static WinIconVerifier instance = new WinIconVerifier(); + static final WinIconVerifier instance = new WinIconVerifier(); private final Class executableRebranderClass; private final Method lockResource; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index bf5ced09bc7..35baff3d5db 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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,8 +40,9 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.internal.IOUtils; -import jdk.jpackage.test.Functional.ThrowingConsumer; +import jdk.jpackage.internal.ApplicationLayout; +import jdk.jpackage.internal.util.PathUtils; +import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.PackageTest.PackageHandlers; @@ -399,6 +400,15 @@ static void addBundleDesktopIntegrationVerifier(PackageTest test, private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile) throws IOException { TKit.trace(String.format("Check [%s] file BEGIN", desktopFile)); + + var launcherName = Stream.of(List.of(cmd.name()), cmd.addLauncherNames()).flatMap(List::stream).filter(name -> { + return getDesktopFile(cmd, name).equals(desktopFile); + }).findAny(); + if (!cmd.hasArgument("--app-image")) { + TKit.assertTrue(launcherName.isPresent(), + "Check the desktop file corresponds to one of app launchers"); + } + List<String> lines = Files.readAllLines(desktopFile); TKit.assertEquals("[Desktop Entry]", lines.get(0), "Check file header"); @@ -428,7 +438,7 @@ private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile) "Check value of [%s] key", key)); } - // Verify value of `Exec` property in .desktop files are escaped if required + // Verify the value of `Exec` key is escaped if required String launcherPath = data.get("Exec"); if (Pattern.compile("\\s").matcher(launcherPath).find()) { TKit.assertTrue(launcherPath.startsWith("\"") @@ -437,10 +447,25 @@ private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile) launcherPath = launcherPath.substring(1, launcherPath.length() - 1); } - Stream.of(launcherPath, data.get("Icon")) - .map(Path::of) - .map(cmd::pathToUnpackedPackageFile) - .forEach(TKit::assertFileExists); + if (launcherName.isPresent()) { + TKit.assertEquals(launcherPath, cmd.pathToPackageFile( + cmd.appLauncherPath(launcherName.get())).toString(), + String.format( + "Check the value of [Exec] key references [%s] app launcher", + launcherName.get())); + } + + for (var e : List.<Map.Entry<Map.Entry<String, Optional<String>>, Function<ApplicationLayout, Path>>>of( + Map.entry(Map.entry("Exec", Optional.of(launcherPath)), ApplicationLayout::launchersDirectory), + Map.entry(Map.entry("Icon", Optional.empty()), ApplicationLayout::destktopIntegrationDirectory))) { + var path = e.getKey().getValue().or(() -> Optional.of(data.get( + e.getKey().getKey()))).map(Path::of).get(); + TKit.assertFileExists(cmd.pathToUnpackedPackageFile(path)); + Path expectedDir = cmd.pathToPackageFile(e.getValue().apply(cmd.appLayout())); + TKit.assertTrue(path.getParent().equals(expectedDir), String.format( + "Check the value of [%s] key references a file in [%s] folder", + e.getKey().getKey(), expectedDir)); + } TKit.trace(String.format("Check [%s] file END", desktopFile)); } @@ -553,7 +578,7 @@ private static String queryMimeTypeDefaultHandler(String mimeType) { private static void verifyIconInScriptlet(Scriptlet scriptletType, List<String> scriptletBody, Path iconPathInPackage) { - final String dashMime = IOUtils.replaceSuffix( + final String dashMime = PathUtils.replaceSuffix( iconPathInPackage.getFileName(), null).toString(); final String xdgCmdName = "xdg-icon-resource"; @@ -725,10 +750,10 @@ private static Method initGetServiceUnitFileName() { private static Map<PackageType, String> archs; - private final static Pattern XDG_CMD_ICON_SIZE_PATTERN = Pattern.compile("\\s--size\\s+(\\d+)\\b"); + private static final Pattern XDG_CMD_ICON_SIZE_PATTERN = Pattern.compile("\\s--size\\s+(\\d+)\\b"); // Values grabbed from https://linux.die.net/man/1/xdg-icon-resource - private final static Set<Integer> XDG_CMD_VALID_ICON_SIZES = Set.of(16, 22, 32, 48, 64, 128); + private static final Set<Integer> XDG_CMD_VALID_ICON_SIZES = Set.of(16, 22, 32, 48, 64, 128); - private final static Method getServiceUnitFileName = initGetServiceUnitFileName(); + private static final Method getServiceUnitFileName = initGetServiceUnitFileName(); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java index 63afb6cf9f7..9cadd419ca1 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java @@ -43,11 +43,11 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; -import jdk.jpackage.internal.IOUtils; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import jdk.jpackage.test.Functional.ThrowingSupplier; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingSupplier; import jdk.jpackage.test.PackageTest.PackageHandlers; import jdk.jpackage.internal.RetryExecutor; +import jdk.jpackage.internal.util.PathUtils; import org.xml.sax.SAXException; import org.w3c.dom.NodeList; @@ -212,7 +212,7 @@ static PackageHandlers createPkgPackageHandlers() { // Unpack all ".pkg" files from $dataDir folder in $unpackDir folder try (var dataListing = Files.list(dataDir)) { dataListing.filter(file -> { - return ".pkg".equals(IOUtils.getSuffix(file.getFileName())); + return ".pkg".equals(PathUtils.getSuffix(file.getFileName())); }).forEach(ThrowingConsumer.toConsumer(pkgDir -> { // Installation root of the package is stored in // /pkg-info@install-location attribute in $pkgDir/PackageInfo xml file diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java index 37aca48ac17..5919d8361c4 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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,11 +23,17 @@ package jdk.jpackage.test; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Comparator; +import java.util.Deque; import java.util.List; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; +import static java.util.stream.Collectors.toCollection; +import java.util.stream.Stream; import static jdk.jpackage.test.TestBuilder.CMDLINE_ARG_PREFIX; @@ -36,7 +42,9 @@ public static void main(String args[]) throws Throwable { boolean listTests = false; List<TestInstance> tests = new ArrayList<>(); try (TestBuilder testBuilder = new TestBuilder(tests::add)) { - for (var arg : args) { + Deque<String> argsAsList = new ArrayDeque<>(List.of(args)); + while (!argsAsList.isEmpty()) { + var arg = argsAsList.pop(); TestBuilder.trace(String.format("Parsing [%s]...", arg)); if ((CMDLINE_ARG_PREFIX + "list").equals(arg)) { @@ -44,6 +52,29 @@ public static void main(String args[]) throws Throwable { continue; } + if (arg.startsWith("@")) { + // Command file + // @=args will read arguments from the "args" file, one argument per line + // @args will read arguments from the "args" file, splitting lines into arguments at whitespaces + arg = arg.substring(1); + var oneArgPerLine = arg.startsWith("="); + if (oneArgPerLine) { + arg = arg.substring(1); + } + + var newArgsStream = Files.readAllLines(Path.of(arg)).stream(); + if (!oneArgPerLine) { + newArgsStream.map(line -> { + return Stream.of(line.split("\\s+")); + }).flatMap(x -> x); + } + + var newArgs = newArgsStream.collect(toCollection(ArrayDeque::new)); + newArgs.addAll(argsAsList); + argsAsList = newArgs; + continue; + } + boolean success = false; try { testBuilder.processCmdLineArg(arg); @@ -62,12 +93,11 @@ public static void main(String args[]) throws Throwable { // Order tests by their full names to have stable test sequence. List<TestInstance> orderedTests = tests.stream() - .sorted((a, b) -> a.fullName().compareTo(b.fullName())) - .collect(Collectors.toList()); + .sorted(Comparator.comparing(TestInstance::fullName)).toList(); if (listTests) { // Just list the tests - orderedTests.stream().forEach(test -> System.out.println(String.format( + orderedTests.forEach(test -> System.out.println(String.format( "%s; workDir=[%s]", test.fullName(), test.workDir()))); return; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java index 2aaba054a9b..51a8ade8a1d 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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,34 +22,33 @@ */ package jdk.jpackage.test; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; -import java.util.List; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Collectors; +import java.util.function.Predicate; +import java.util.stream.IntStream; import java.util.stream.Stream; -import jdk.jpackage.test.Functional.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.TestInstance.TestDesc; class MethodCall implements ThrowingConsumer { - MethodCall(Object[] instanceCtorArgs, Method method) { - this.ctorArgs = Optional.ofNullable(instanceCtorArgs).orElse( - DEFAULT_CTOR_ARGS); - this.method = method; - this.methodArgs = new Object[0]; - } + MethodCall(Object[] instanceCtorArgs, Method method, Object ... args) { + Objects.requireNonNull(instanceCtorArgs); + Objects.requireNonNull(method); - MethodCall(Object[] instanceCtorArgs, Method method, Object arg) { - this.ctorArgs = Optional.ofNullable(instanceCtorArgs).orElse( - DEFAULT_CTOR_ARGS); + this.ctorArgs = instanceCtorArgs; this.method = method; - this.methodArgs = new Object[]{arg}; + this.methodArgs = args; } TestDesc createDescription() { @@ -76,78 +75,195 @@ Object newInstance() throws NoSuchMethodException, InstantiationException, return null; } - Constructor ctor = findRequiredConstructor(method.getDeclaringClass(), - ctorArgs); - if (ctor.isVarArgs()) { - // Assume constructor doesn't have fixed, only variable parameters. - return ctor.newInstance(new Object[]{ctorArgs}); - } + var ctor = findMatchingConstructor(method.getDeclaringClass(), ctorArgs); - return ctor.newInstance(ctorArgs); + return ctor.newInstance(mapArgs(ctor, ctorArgs)); + } + + static Object[] mapArgs(Executable executable, final Object ... args) { + return mapPrimitiveTypeArgs(executable, mapVarArgs(executable, args)); } void checkRequiredConstructor() throws NoSuchMethodException { if ((method.getModifiers() & Modifier.STATIC) == 0) { - findRequiredConstructor(method.getDeclaringClass(), ctorArgs); + findMatchingConstructor(method.getDeclaringClass(), ctorArgs); } } - private static Constructor findVarArgConstructor(Class type) { - return Stream.of(type.getConstructors()).filter( - Constructor::isVarArgs).findFirst().orElse(null); - } - - private Constructor findRequiredConstructor(Class type, Object... ctorArgs) + private static Constructor findMatchingConstructor(Class type, Object... ctorArgs) throws NoSuchMethodException { - Supplier<NoSuchMethodException> notFoundException = () -> { - return new NoSuchMethodException(String.format( + var ctors = filterMatchingExecutablesForParameterValues(Stream.of( + type.getConstructors()), ctorArgs).toList(); + + if (ctors.size() != 1) { + // No public constructors that can handle the given arguments. + throw new NoSuchMethodException(String.format( "No public contructor in %s for %s arguments", type, Arrays.deepToString(ctorArgs))); - }; - - if (Stream.of(ctorArgs).allMatch(Objects::nonNull)) { - // No `null` in constructor args, take easy path - try { - return type.getConstructor(Stream.of(ctorArgs).map( - Object::getClass).collect(Collectors.toList()).toArray( - Class[]::new)); - } catch (NoSuchMethodException ex) { - // Failed to find ctor that can take the given arguments. - Constructor varArgCtor = findVarArgConstructor(type); - if (varArgCtor != null) { - // There is one with variable number of arguments. Use it. - return varArgCtor; - } - throw notFoundException.get(); + } + + return ctors.get(0); + } + + @Override + public void accept(Object thiz) throws Throwable { + method.invoke(thiz, methodArgs); + } + + private static Object[] mapVarArgs(Executable executable, final Object ... args) { + if (executable.isVarArgs()) { + var paramTypes = executable.getParameterTypes(); + Class varArgParamType = paramTypes[paramTypes.length - 1]; + + Object[] newArgs; + if (paramTypes.length - args.length == 1) { + // Empty var args + + // "args" can be of type String[] if the "executable" is "foo(String ... str)" + newArgs = Arrays.copyOf(args, args.length + 1, Object[].class); + newArgs[newArgs.length - 1] = Array.newInstance(varArgParamType.componentType(), 0); + } else { + var varArgs = Arrays.copyOfRange(args, paramTypes.length - 1, + args.length, varArgParamType); + + // "args" can be of type String[] if the "executable" is "foo(String ... str)" + newArgs = Arrays.copyOfRange(args, 0, paramTypes.length, Object[].class); + newArgs[newArgs.length - 1] = varArgs; } + return newArgs; } - List<Constructor> ctors = Stream.of(type.getConstructors()) - .filter(ctor -> ctor.getParameterCount() == ctorArgs.length) - .collect(Collectors.toList()); + return args; + } - if (ctors.isEmpty()) { - // No public constructors that can handle the given arguments. - throw notFoundException.get(); + private static Object[] mapPrimitiveTypeArgs(Executable executable, final Object ... args) { + var paramTypes = executable.getParameterTypes(); + if (paramTypes.length != args.length) { + throw new IllegalArgumentException( + "The number of arguments must be equal to the number of parameters of the executable"); } - if (ctors.size() == 1) { - return ctors.iterator().next(); + if (IntStream.range(0, args.length).allMatch(idx -> { + return Optional.ofNullable(args[idx]).map(Object::getClass).map(paramTypes[idx]::isAssignableFrom).orElse(true); + })) { + return args; + } else { + final var newArgs = Arrays.copyOf(args, args.length, Object[].class); + for (var idx = 0; idx != args.length; ++idx) { + final var paramType = paramTypes[idx]; + final var argValue = args[idx]; + newArgs[idx] = Optional.ofNullable(argValue).map(Object::getClass).map(argType -> { + if(argType.isArray() && !paramType.isAssignableFrom(argType)) { + var length = Array.getLength(argValue); + var newArray = Array.newInstance(paramType.getComponentType(), length); + for (var arrayIdx = 0; arrayIdx != length; ++arrayIdx) { + Array.set(newArray, arrayIdx, Array.get(argValue, arrayIdx)); + } + return newArray; + } else { + return argValue; + } + }).orElse(argValue); + } + + return newArgs; } + } - // Revisit this tricky case when it will start bothering. - throw notFoundException.get(); + private static <T extends Executable> Stream<T> filterMatchingExecutablesForParameterValues( + Stream<T> executables, Object... args) { + return filterMatchingExecutablesForParameterTypes( + executables, + Stream.of(args) + .map(arg -> arg != null ? arg.getClass() : null) + .toArray(Class[]::new)); } - @Override - public void accept(Object thiz) throws Throwable { - method.invoke(thiz, methodArgs); + private static <T extends Executable> Stream<T> filterMatchingExecutablesForParameterTypes( + Stream<T> executables, Class<?>... argTypes) { + return executables.filter(executable -> { + var parameterTypes = executable.getParameterTypes(); + + final int checkArgTypeCount; + if (parameterTypes.length <= argTypes.length) { + checkArgTypeCount = parameterTypes.length; + } else if (parameterTypes.length - argTypes.length == 1 && executable.isVarArgs()) { + // Empty optional arguments. + checkArgTypeCount = argTypes.length; + } else { + // Not enough mandatory arguments. + return false; + } + + var unmatched = IntStream.range(0, checkArgTypeCount).dropWhile(idx -> { + return new ParameterTypeMatcher(parameterTypes[idx]).test(argTypes[idx]); + }).toArray(); + + if (argTypes.length == parameterTypes.length && unmatched.length == 0) { + // Number of argument types equals to the number of parameters + // of the executable and all types match. + return true; + } + + if (executable.isVarArgs()) { + var varArgType = parameterTypes[parameterTypes.length - 1].componentType(); + return IntStream.of(unmatched).allMatch(idx -> { + return new ParameterTypeMatcher(varArgType).test(argTypes[idx]); + }); + } + + return false; + }); + } + + private static final class ParameterTypeMatcher implements Predicate<Class<?>> { + ParameterTypeMatcher(Class<?> parameterType) { + Objects.requireNonNull(parameterType); + this.parameterType = NORM_TYPES.getOrDefault(parameterType, parameterType); + } + + @Override + public boolean test(Class<?> paramaterValueType) { + if (paramaterValueType == null) { + return true; + } + + paramaterValueType = NORM_TYPES.getOrDefault(paramaterValueType, paramaterValueType); + return parameterType.isAssignableFrom(paramaterValueType); + } + + private final Class<?> parameterType; } private final Object[] methodArgs; private final Method method; private final Object[] ctorArgs; - final static Object[] DEFAULT_CTOR_ARGS = new Object[0]; + private static final Map<Class<?>, Class<?>> NORM_TYPES; + + static { + Map<Class<?>, Class<?>> primitives = Map.of( + boolean.class, Boolean.class, + byte.class, Byte.class, + short.class, Short.class, + int.class, Integer.class, + long.class, Long.class, + float.class, Float.class, + double.class, Double.class); + + Map<Class<?>, Class<?>> primitiveArrays = Map.of( + boolean[].class, Boolean[].class, + byte[].class, Byte[].class, + short[].class, Short[].class, + int[].class, Integer[].class, + long[].class, Long[].class, + float[].class, Float[].class, + double[].class, Double[].class); + + Map<Class<?>, Class<?>> combined = new HashMap<>(primitives); + combined.putAll(primitiveArrays); + + NORM_TYPES = Collections.unmodifiableMap(combined); + } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java index 6f486425e73..7c6aab29fee 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -46,13 +46,13 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; import jdk.jpackage.internal.ApplicationLayout; -import jdk.jpackage.test.Functional.ThrowingBiConsumer; -import static jdk.jpackage.test.Functional.ThrowingBiConsumer.toBiConsumer; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import static jdk.jpackage.test.Functional.ThrowingConsumer.toConsumer; -import jdk.jpackage.test.Functional.ThrowingRunnable; -import static jdk.jpackage.test.Functional.ThrowingSupplier.toSupplier; -import static jdk.jpackage.test.Functional.rethrowUnchecked; +import jdk.jpackage.internal.util.function.ThrowingBiConsumer; +import static jdk.jpackage.internal.util.function.ThrowingBiConsumer.toBiConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; +import jdk.jpackage.internal.util.function.ThrowingRunnable; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; import static jdk.jpackage.test.PackageType.LINUX; import static jdk.jpackage.test.PackageType.LINUX_DEB; import static jdk.jpackage.test.PackageType.LINUX_RPM; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java index 71637ef7134..8aa7d005adb 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java @@ -32,6 +32,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.Log; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; /** * jpackage type traits. @@ -103,7 +104,7 @@ private static boolean isBundlerSupportedImpl(String bundlerClass) { } catch (ClassNotFoundException | IllegalAccessException ex) { } catch (InstantiationException | NoSuchMethodException | InvocationTargetException ex) { - Functional.rethrowUnchecked(ex); + rethrowUnchecked(ex); } return false; } @@ -127,7 +128,7 @@ private static boolean isBundlerSupported(String bundlerClass) { thread.run(); thread.join(); } catch (InterruptedException ex) { - Functional.rethrowUnchecked(ex); + rethrowUnchecked(ex); } return reply.get(); } @@ -136,15 +137,15 @@ private static boolean isBundlerSupported(String bundlerClass) { private final String suffix; private final boolean supported; - public final static Set<PackageType> LINUX = Set.of(LINUX_DEB, LINUX_RPM); - public final static Set<PackageType> WINDOWS = Set.of(WIN_EXE, WIN_MSI); - public final static Set<PackageType> MAC = Set.of(MAC_PKG, MAC_DMG); - public final static Set<PackageType> NATIVE = Stream.concat( + public static final Set<PackageType> LINUX = Set.of(LINUX_DEB, LINUX_RPM); + public static final Set<PackageType> WINDOWS = Set.of(WIN_EXE, WIN_MSI); + public static final Set<PackageType> MAC = Set.of(MAC_PKG, MAC_DMG); + public static final Set<PackageType> NATIVE = Stream.concat( Stream.concat(LINUX.stream(), WINDOWS.stream()), MAC.stream()).collect(Collectors.toUnmodifiableSet()); - private final static class Inner { - private final static Set<String> DISABLED_PACKAGERS = Optional.ofNullable( + private static final class Inner { + private static final Set<String> DISABLED_PACKAGERS = Optional.ofNullable( TKit.tokenizeConfigProperty("disabledPackagers")).orElse( TKit.isLinuxAPT() ? Set.of("rpm") : Collections.emptySet()); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index 28c58a4db3d..b5859564568 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -61,10 +61,10 @@ import static java.util.stream.Collectors.toSet; import java.util.stream.Stream; import jdk.internal.util.OperatingSystem; -import jdk.jpackage.test.Functional.ExceptionBox; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import jdk.jpackage.test.Functional.ThrowingRunnable; -import jdk.jpackage.test.Functional.ThrowingSupplier; +import jdk.jpackage.internal.util.function.ExceptionBox; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingRunnable; +import jdk.jpackage.internal.util.function.ThrowingSupplier; public final class TKit { @@ -781,18 +781,18 @@ public void match(Set<Path> expected) { currentTest.notifyAssert(); var comm = Comm.compare(content, expected); - if (!comm.unique1.isEmpty() && !comm.unique2.isEmpty()) { + if (!comm.unique1().isEmpty() && !comm.unique2().isEmpty()) { error(String.format( "assertDirectoryContentEquals(%s): Some expected %s. Unexpected %s. Missing %s", - baseDir, format(comm.common), format(comm.unique1), format(comm.unique2))); - } else if (!comm.unique1.isEmpty()) { + baseDir, format(comm.common()), format(comm.unique1()), format(comm.unique2()))); + } else if (!comm.unique1().isEmpty()) { error(String.format( "assertDirectoryContentEquals(%s): Expected %s. Unexpected %s", - baseDir, format(comm.common), format(comm.unique1))); - } else if (!comm.unique2.isEmpty()) { + baseDir, format(comm.common()), format(comm.unique1()))); + } else if (!comm.unique2().isEmpty()) { error(String.format( "assertDirectoryContentEquals(%s): Some expected %s. Missing %s", - baseDir, format(comm.common), format(comm.unique2))); + baseDir, format(comm.common()), format(comm.unique2()))); } else { traceAssert(String.format( "assertDirectoryContentEquals(%s): Expected %s", @@ -808,10 +808,10 @@ public void contains(Set<Path> expected) { currentTest.notifyAssert(); var comm = Comm.compare(content, expected); - if (!comm.unique2.isEmpty()) { + if (!comm.unique2().isEmpty()) { error(String.format( "assertDirectoryContentContains(%s): Some expected %s. Missing %s", - baseDir, format(comm.common), format(comm.unique2))); + baseDir, format(comm.common()), format(comm.unique2()))); } else { traceAssert(String.format( "assertDirectoryContentContains(%s): Expected %s", @@ -838,21 +838,6 @@ private DirectoryContentVerifier(Path baseDir, Set<Path> contents) { this.content = contents; } - private static record Comm(Set<Path> common, Set<Path> unique1, Set<Path> unique2) { - static Comm compare(Set<Path> a, Set<Path> b) { - Set<Path> common = new HashSet<>(a); - common.retainAll(b); - - Set<Path> unique1 = new HashSet<>(a); - unique1.removeAll(common); - - Set<Path> unique2 = new HashSet<>(b); - unique2.removeAll(common); - - return new Comm(common, unique1, unique2); - } - } - private static String format(Set<Path> paths) { return Arrays.toString( paths.stream().sorted().map(Path::toString).toArray( @@ -961,6 +946,16 @@ public TextStreamVerifier negate() { return this; } + public TextStreamVerifier andThen(Consumer<? super Stream<String>> anotherVerifier) { + this.anotherVerifier = anotherVerifier; + return this; + } + + public TextStreamVerifier andThen(TextStreamVerifier anotherVerifier) { + this.anotherVerifier = anotherVerifier::apply; + return this; + } + public TextStreamVerifier orElseThrow(RuntimeException v) { return orElseThrow(() -> v); } @@ -971,9 +966,22 @@ public TextStreamVerifier orElseThrow(Supplier<RuntimeException> v) { } public void apply(Stream<String> lines) { - String matchedStr = lines.filter(line -> predicate.test(line, value)).findFirst().orElse( - null); - String labelStr = Optional.ofNullable(label).orElse("output"); + final String matchedStr; + + lines = lines.dropWhile(line -> !predicate.test(line, value)); + if (anotherVerifier == null) { + matchedStr = lines.findFirst().orElse(null); + } else { + var tail = lines.toList(); + if (tail.isEmpty()) { + matchedStr = null; + } else { + matchedStr = tail.get(0); + } + lines = tail.stream().skip(1); + } + + final String labelStr = Optional.ofNullable(label).orElse("output"); if (negate) { String msg = String.format( "Check %s doesn't contain [%s] string", labelStr, value); @@ -997,12 +1005,17 @@ public void apply(Stream<String> lines) { } } } + + if (anotherVerifier != null) { + anotherVerifier.accept(lines); + } } private BiPredicate<String, String> predicate; private String label; private boolean negate; private Supplier<RuntimeException> createException; + private Consumer<? super Stream<String>> anotherVerifier; private final String value; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java index bb699ba3b9c..23fd5dd52a5 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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,32 +23,28 @@ package jdk.jpackage.test; -import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Collection; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import java.util.function.Function; import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.test.Annotations.AfterEach; import jdk.jpackage.test.Annotations.BeforeEach; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.ParameterGroup; -import jdk.jpackage.test.Annotations.Parameters; import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import jdk.jpackage.test.Functional.ThrowingFunction; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; +import jdk.jpackage.internal.util.function.ThrowingFunction; +import jdk.jpackage.test.TestMethodSupplier.InvalidAnnotationException; +import static jdk.jpackage.test.TestMethodSupplier.MethodQuery.fromQualifiedMethodName; final class TestBuilder implements AutoCloseable { @@ -58,6 +54,7 @@ public void close() throws Exception { } TestBuilder(Consumer<TestInstance> testConsumer) { + this.testMethodSupplier = TestBuilderConfig.getDefault().createTestMethodSupplier(); argProcessors = Map.of( CMDLINE_ARG_PREFIX + "after-run", arg -> getJavaMethodsFromArg(arg).map( @@ -70,7 +67,7 @@ public void close() throws Exception { CMDLINE_ARG_PREFIX + "run", arg -> addTestGroup(getJavaMethodsFromArg(arg).map( ThrowingFunction.toFunction( - TestBuilder::toMethodCalls)).flatMap(s -> s).collect( + this::toMethodCalls)).flatMap(s -> s).collect( Collectors.toList())), CMDLINE_ARG_PREFIX + "exclude", @@ -219,23 +216,29 @@ private static Stream<Method> selectFrameMethods(Class type, Class annotationTyp .filter(m -> m.getParameterCount() == 0) .filter(m -> !m.isAnnotationPresent(Test.class)) .filter(m -> m.isAnnotationPresent(annotationType)) - .sorted((a, b) -> a.getName().compareTo(b.getName())); + .sorted(Comparator.comparing(Method::getName)); } - private static Stream<String> cmdLineArgValueToMethodNames(String v) { + private Stream<String> cmdLineArgValueToMethodNames(String v) { List<String> result = new ArrayList<>(); String defaultClassName = null; for (String token : v.split(",")) { Class testSet = probeClass(token); if (testSet != null) { + if (testMethodSupplier.isTestClass(testSet)) { + toConsumer(testMethodSupplier::verifyTestClass).accept(testSet); + } + // Test set class specified. Pull in all public methods // from the class with @Test annotation removing name duplicates. // Overloads will be handled at the next phase of processing. defaultClassName = token; - Stream.of(testSet.getMethods()).filter( - m -> m.isAnnotationPresent(Test.class)).map( - Method::getName).distinct().forEach( - name -> result.add(String.join(".", token, name))); + result.addAll(Stream.of(testSet.getMethods()) + .filter(m -> m.isAnnotationPresent(Test.class)) + .filter(testMethodSupplier::isEnabled) + .map(Method::getName).distinct() + .map(name -> String.join(".", token, name)) + .toList()); continue; } @@ -246,7 +249,7 @@ private static Stream<String> cmdLineArgValueToMethodNames(String v) { qualifiedMethodName = token; defaultClassName = token.substring(0, lastDotIdx); } else if (defaultClassName == null) { - throw new ParseException("Default class name not found in"); + throw new ParseException("Missing default class name in"); } else { qualifiedMethodName = String.join(".", defaultClassName, token); } @@ -255,155 +258,43 @@ private static Stream<String> cmdLineArgValueToMethodNames(String v) { return result.stream(); } - private static boolean filterMethod(String expectedMethodName, Method method) { - if (!method.getName().equals(expectedMethodName)) { - return false; - } - switch (method.getParameterCount()) { - case 0: - return !isParametrized(method); - case 1: - return isParametrized(method); - } - return false; - } - - private static boolean isParametrized(Method method) { - return method.isAnnotationPresent(ParameterGroup.class) || method.isAnnotationPresent( - Parameter.class); - } - - private static List<Method> getJavaMethodFromString( - String qualifiedMethodName) { + private List<Method> getJavaMethodFromString(String qualifiedMethodName) { int lastDotIdx = qualifiedMethodName.lastIndexOf('.'); if (lastDotIdx == -1) { - throw new ParseException("Class name not found in"); - } - String className = qualifiedMethodName.substring(0, lastDotIdx); - String methodName = qualifiedMethodName.substring(lastDotIdx + 1); - Class methodClass; - try { - methodClass = Class.forName(className); - } catch (ClassNotFoundException ex) { - throw new ParseException(String.format("Class [%s] not found;", - className)); - } - // Get the list of all public methods as need to deal with overloads. - List<Method> methods = Stream.of(methodClass.getMethods()).filter( - (m) -> filterMethod(methodName, m)).collect(Collectors.toList()); - if (methods.isEmpty()) { - throw new ParseException(String.format( - "Method [%s] not found in [%s] class;", - methodName, className)); + throw new ParseException("Missing class name in"); } - trace(String.format("%s -> %s", qualifiedMethodName, methods)); - return methods; - } - - private static Stream<Method> getJavaMethodsFromArg(String argValue) { - return cmdLineArgValueToMethodNames(argValue).map( - ThrowingFunction.toFunction( - TestBuilder::getJavaMethodFromString)).flatMap( - List::stream).sequential(); - } - - private static Parameter[] getMethodParameters(Method method) { - if (method.isAnnotationPresent(ParameterGroup.class)) { - return ((ParameterGroup) method.getAnnotation(ParameterGroup.class)).value(); - } - - if (method.isAnnotationPresent(Parameter.class)) { - return new Parameter[]{(Parameter) method.getAnnotation( - Parameter.class)}; - } - - // Unexpected - return null; - } - - private static Stream<Object[]> toCtorArgs(Method method) throws - IllegalAccessException, InvocationTargetException { - Class type = method.getDeclaringClass(); - List<Method> paremetersProviders = Stream.of(type.getMethods()) - .filter(m -> m.getParameterCount() == 0) - .filter(m -> (m.getModifiers() & Modifier.STATIC) != 0) - .filter(m -> m.isAnnotationPresent(Parameters.class)) - .sorted() - .collect(Collectors.toList()); - if (paremetersProviders.isEmpty()) { - // Single instance using the default constructor. - return Stream.ofNullable(MethodCall.DEFAULT_CTOR_ARGS); - } - - // Pick the first method from the list. - Method paremetersProvider = paremetersProviders.iterator().next(); - if (paremetersProviders.size() > 1) { - trace(String.format( - "Found %d public static methods without arguments with %s annotation. Will use %s", - paremetersProviders.size(), Parameters.class, - paremetersProvider)); - paremetersProviders.stream().map(Method::toString).forEach( - TestBuilder::trace); + try { + return testMethodSupplier.findNullaryLikeMethods( + fromQualifiedMethodName(qualifiedMethodName)); + } catch (NoSuchMethodException ex) { + throw new ParseException(ex.getMessage() + ";", ex); } - - // Construct collection of arguments for test class instances. - return ((Collection) paremetersProvider.invoke(null)).stream(); } - private static Stream<MethodCall> toMethodCalls(Method method) throws - IllegalAccessException, InvocationTargetException { - return toCtorArgs(method).map(v -> toMethodCalls(v, method)).flatMap( - s -> s).peek(methodCall -> { - // Make sure required constructor is accessible if the one is needed. - // Need to probe all methods as some of them might be static - // and some class members. - // Only class members require ctors. - try { - methodCall.checkRequiredConstructor(); - } catch (NoSuchMethodException ex) { - throw new ParseException(ex.getMessage() + "."); - } - }); + private Stream<Method> getJavaMethodsFromArg(String argValue) { + var methods = cmdLineArgValueToMethodNames(argValue) + .map(this::getJavaMethodFromString) + .flatMap(List::stream).toList(); + trace(String.format("%s -> %s", argValue, methods)); + return methods.stream(); } - private static Stream<MethodCall> toMethodCalls(Object[] ctorArgs, Method method) { - if (!isParametrized(method)) { - return Stream.of(new MethodCall(ctorArgs, method)); - } - Parameter[] annotations = getMethodParameters(method); - if (annotations.length == 0) { - return Stream.of(new MethodCall(ctorArgs, method)); - } - return Stream.of(annotations).map((a) -> { - Class paramType = method.getParameterTypes()[0]; - final Object annotationValue; - if (!paramType.isArray()) { - annotationValue = fromString(a.value()[0], paramType); - } else { - Class paramComponentType = paramType.getComponentType(); - annotationValue = Array.newInstance(paramComponentType, a.value().length); - var idx = new AtomicInteger(-1); - Stream.of(a.value()).map(v -> fromString(v, paramComponentType)).sequential().forEach( - v -> Array.set(annotationValue, idx.incrementAndGet(), v)); + private Stream<MethodCall> toMethodCalls(Method method) throws + IllegalAccessException, InvocationTargetException, InvalidAnnotationException { + return testMethodSupplier.mapToMethodCalls(method).peek(methodCall -> { + // Make sure required constructor is accessible if the one is needed. + // Need to probe all methods as some of them might be static + // and some class members. + // Only class members require ctors. + try { + methodCall.checkRequiredConstructor(); + } catch (NoSuchMethodException ex) { + throw new ParseException(ex.getMessage() + ".", ex); } - return new MethodCall(ctorArgs, method, annotationValue); }); } - private static Object fromString(String value, Class toType) { - if (toType.isEnum()) { - return Enum.valueOf(toType, value); - } - Function<String, Object> converter = conv.get(toType); - if (converter == null) { - throw new RuntimeException(String.format( - "Failed to find a conversion of [%s] string to %s type", - value, toType)); - } - return converter.apply(value); - } - // Wraps Method.invike() into ThrowingRunnable.run() private ThrowingConsumer wrap(Method method) { return (test) -> { @@ -427,6 +318,10 @@ private static class ParseException extends IllegalArgumentException { super(msg); } + ParseException(String msg, Exception ex) { + super(msg, ex); + } + void setContext(String badCmdLineArg) { this.badCmdLineArg = badCmdLineArg; } @@ -448,8 +343,9 @@ static void trace(String msg) { } } + private final TestMethodSupplier testMethodSupplier; private final Map<String, ThrowingConsumer<String>> argProcessors; - private Consumer<TestInstance> testConsumer; + private final Consumer<TestInstance> testConsumer; private List<MethodCall> testGroup; private List<ThrowingConsumer> beforeActions; private List<ThrowingConsumer> afterActions; @@ -458,14 +354,5 @@ static void trace(String msg) { private String spaceSubstitute; private boolean dryRun; - private final static Map<Class, Function<String, Object>> conv = Map.of( - boolean.class, Boolean::valueOf, - Boolean.class, Boolean::valueOf, - int.class, Integer::valueOf, - Integer.class, Integer::valueOf, - long.class, Long::valueOf, - Long.class, Long::valueOf, - String.class, String::valueOf); - - final static String CMDLINE_ARG_PREFIX = "--jpt-"; + static final String CMDLINE_ARG_PREFIX = "--jpt-"; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilderConfig.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilderConfig.java new file mode 100644 index 00000000000..baeaec32546 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilderConfig.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.test; + +import java.util.Objects; +import jdk.internal.util.OperatingSystem; + +final class TestBuilderConfig { + TestBuilderConfig() { + } + + TestMethodSupplier createTestMethodSupplier() { + return new TestMethodSupplier(os); + } + + OperatingSystem getOperatingSystem() { + return os; + } + + static TestBuilderConfig getDefault() { + return DEFAULT.get(); + } + + static void setOperatingSystem(OperatingSystem os) { + Objects.requireNonNull(os); + DEFAULT.get().os = os; + } + + static void setDefaults() { + DEFAULT.set(new TestBuilderConfig()); + } + + private OperatingSystem os = OperatingSystem.current(); + + private static final ThreadLocal<TestBuilderConfig> DEFAULT = new ThreadLocal<>() { + @Override + protected TestBuilderConfig initialValue() { + return new TestBuilderConfig(); + } + }; +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java index 105c8f707cd..871ddc24277 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,15 +32,18 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import jdk.jpackage.test.Functional.ThrowingFunction; -import jdk.jpackage.test.Functional.ThrowingRunnable; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingFunction; +import jdk.jpackage.internal.util.function.ThrowingRunnable; +import jdk.jpackage.internal.util.function.ThrowingSupplier; final class TestInstance implements ThrowingRunnable { @@ -50,7 +53,7 @@ private TestDesc() { String testFullName() { StringBuilder sb = new StringBuilder(); - sb.append(clazz.getSimpleName()); + sb.append(clazz.getName()); if (instanceArgs != null) { sb.append('(').append(instanceArgs).append(')'); } @@ -78,12 +81,12 @@ Builder method(Method v) { } Builder ctorArgs(Object... v) { - ctorArgs = ofNullable(v); + ctorArgs = Arrays.asList(v); return this; } Builder methodArgs(Object... v) { - methodArgs = ofNullable(v); + methodArgs = Arrays.asList(v); return this; } @@ -107,22 +110,18 @@ private static String formatArgs(List<Object> values) { } return values.stream().map(v -> { if (v != null && v.getClass().isArray()) { - return String.format("%s(length=%d)", - Arrays.deepToString((Object[]) v), - Array.getLength(v)); + String asString; + if (v.getClass().getComponentType().isPrimitive()) { + asString = PRIMITIVE_ARRAY_FORMATTERS.get(v.getClass()).apply(v); + } else { + asString = Arrays.deepToString((Object[]) v); + } + return String.format("%s(length=%d)", asString, Array.getLength(v)); } return String.format("%s", v); }).collect(Collectors.joining(", ")); } - private static List<Object> ofNullable(Object... values) { - List<Object> result = new ArrayList(); - for (var v: values) { - result.add(v); - } - return result; - } - private List<Object> ctorArgs; private List<Object> methodArgs; private Method method; @@ -260,7 +259,7 @@ private static Class enclosingMainMethodClass() { StackTraceElement st[] = Thread.currentThread().getStackTrace(); for (StackTraceElement ste : st) { if ("main".equals(ste.getMethodName())) { - return Functional.ThrowingSupplier.toSupplier(() -> Class.forName( + return ThrowingSupplier.toSupplier(() -> Class.forName( ste.getClassName())).get(); } } @@ -331,7 +330,7 @@ public String toString() { private final boolean dryRun; private final Path workDir; - private final static Set<Status> KEEP_WORK_DIR = Functional.identity( + private static final Set<Status> KEEP_WORK_DIR = Functional.identity( () -> { final String propertyName = "keep-work-dir"; Set<String> keepWorkDir = TKit.tokenizeConfigProperty( @@ -355,4 +354,15 @@ public String toString() { return Collections.unmodifiableSet(result); }).get(); + private static final Map<Class<?>, Function<Object, String>> PRIMITIVE_ARRAY_FORMATTERS = Map.of( + boolean[].class, v -> Arrays.toString((boolean[])v), + byte[].class, v -> Arrays.toString((byte[])v), + char[].class, v -> Arrays.toString((char[])v), + short[].class, v -> Arrays.toString((short[])v), + int[].class, v -> Arrays.toString((int[])v), + long[].class, v -> Arrays.toString((long[])v), + float[].class, v -> Arrays.toString((float[])v), + double[].class, v -> Arrays.toString((double[])v) + ); + } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java new file mode 100644 index 00000000000..0d701d0ec6f --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2024, 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 jdk.jpackage.test; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import jdk.internal.util.OperatingSystem; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterGroup; +import jdk.jpackage.test.Annotations.ParameterSupplier; +import jdk.jpackage.test.Annotations.ParameterSupplierGroup; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.Annotations.Test; +import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; +import static jdk.jpackage.test.MethodCall.mapArgs; + +final class TestMethodSupplier { + + TestMethodSupplier(OperatingSystem os) { + Objects.requireNonNull(os); + this.os = os; + } + + record MethodQuery(String className, String methodName) { + + List<Method> lookup() throws ClassNotFoundException { + final Class methodClass = Class.forName(className); + + // Get the list of all public methods as need to deal with overloads. + return Stream.of(methodClass.getMethods()).filter(method -> { + return method.getName().equals(methodName); + }).toList(); + } + + static MethodQuery fromQualifiedMethodName(String qualifiedMethodName) { + int lastDotIdx = qualifiedMethodName.lastIndexOf('.'); + if (lastDotIdx == -1) { + throw new IllegalArgumentException("Class name not specified"); + } + + var className = qualifiedMethodName.substring(0, lastDotIdx); + var methodName = qualifiedMethodName.substring(lastDotIdx + 1); + + return new MethodQuery(className, methodName); + } + } + + List<Method> findNullaryLikeMethods(MethodQuery query) throws NoSuchMethodException { + List<Method> methods; + + try { + methods = query.lookup(); + } catch (ClassNotFoundException ex) { + throw new NoSuchMethodException( + String.format("Class [%s] not found", query.className())); + } + + if (methods.isEmpty()) { + throw new NoSuchMethodException(String.format( + "Public method [%s] not found in [%s] class", + query.methodName(), query.className())); + } + + methods = methods.stream().filter(method -> { + if (isParameterized(method) && isTest(method)) { + // Always accept test method with annotations producing arguments for its invocation. + return true; + } else { + return method.getParameterCount() == 0; + } + }).filter(this::isEnabled).toList(); + + if (methods.isEmpty()) { + throw new NoSuchMethodException(String.format( + "Suitable public method [%s] not found in [%s] class", + query.methodName(), query.className())); + } + + return methods; + } + + boolean isTestClass(Class<?> type) { + var typeStatus = processedTypes.get(type); + if (typeStatus == null) { + typeStatus = Verifier.isTestClass(type) ? TypeStatus.TEST_CLASS : TypeStatus.NOT_TEST_CLASS; + processedTypes.put(type, typeStatus); + } + + return !TypeStatus.NOT_TEST_CLASS.equals(typeStatus); + } + + void verifyTestClass(Class<?> type) throws InvalidAnnotationException { + var typeStatus = processedTypes.get(type); + if (typeStatus == null) { + // The "type" has not been verified yet. + try { + Verifier.verifyTestClass(type); + processedTypes.put(type, TypeStatus.VALID_TEST_CLASS); + return; + } catch (InvalidAnnotationException ex) { + processedTypes.put(type, TypeStatus.TEST_CLASS); + throw ex; + } + } + + switch (typeStatus) { + case NOT_TEST_CLASS -> Verifier.throwNotTestClassException(type); + case TEST_CLASS -> Verifier.verifyTestClass(type); + case VALID_TEST_CLASS -> {} + } + } + + boolean isEnabled(Method method) { + return Stream.of(Test.class, Parameters.class) + .filter(method::isAnnotationPresent) + .findFirst() + .map(method::getAnnotation) + .map(this::canRunOnTheOperatingSystem) + .orElse(true); + } + + Stream<MethodCall> mapToMethodCalls(Method method) throws + IllegalAccessException, InvocationTargetException { + return toCtorArgs(method).map(v -> toMethodCalls(v, method)).flatMap(x -> x); + } + + private Stream<Object[]> toCtorArgs(Method method) throws + IllegalAccessException, InvocationTargetException { + + if ((method.getModifiers() & Modifier.STATIC) != 0) { + // Static method, no instance + return Stream.ofNullable(DEFAULT_CTOR_ARGS); + } + + final var type = method.getDeclaringClass(); + + final var paremeterSuppliers = filterParameterSuppliers(type) + .filter(m -> m.isAnnotationPresent(Parameters.class)) + .filter(this::isEnabled) + .sorted(Comparator.comparing(Method::getName)).toList(); + if (paremeterSuppliers.isEmpty()) { + // Single instance using the default constructor. + return Stream.ofNullable(DEFAULT_CTOR_ARGS); + } + + // Construct collection of arguments for test class instances. + return createArgs(paremeterSuppliers.toArray(Method[]::new)); + } + + private Stream<MethodCall> toMethodCalls(Object[] ctorArgs, Method method) { + if (!isParameterized(method)) { + return Stream.of(new MethodCall(ctorArgs, method)); + } + + var fromParameter = Stream.of(getMethodParameters(method)).map(a -> { + return createArgsForAnnotation(method, a); + }).flatMap(List::stream); + + var fromParameterSupplier = Stream.of(getMethodParameterSuppliers(method)).map(a -> { + return toSupplier(() -> createArgsForAnnotation(method, a)).get(); + }).flatMap(List::stream); + + return Stream.concat(fromParameter, fromParameterSupplier).map(args -> { + return new MethodCall(ctorArgs, method, args); + }); + } + + private List<Object[]> createArgsForAnnotation(Executable exec, Parameter a) { + if (!canRunOnTheOperatingSystem(a)) { + return List.of(); + } + + final var annotationArgs = a.value(); + final var execParameterTypes = exec.getParameterTypes(); + + if (execParameterTypes.length > annotationArgs.length) { + if (execParameterTypes.length - annotationArgs.length == 1 && exec.isVarArgs()) { + } else { + throw new RuntimeException(String.format( + "Not enough annotation values %s for [%s]", + List.of(annotationArgs), exec)); + } + } + + final Class<?>[] argTypes; + if (exec.isVarArgs()) { + List<Class<?>> argTypesBuilder = new ArrayList<>(); + var lastExecParameterTypeIdx = execParameterTypes.length - 1; + argTypesBuilder.addAll(List.of(execParameterTypes).subList(0, + lastExecParameterTypeIdx)); + argTypesBuilder.addAll(Collections.nCopies( + Integer.max(0, annotationArgs.length - lastExecParameterTypeIdx), + execParameterTypes[lastExecParameterTypeIdx].componentType())); + argTypes = argTypesBuilder.toArray(Class[]::new); + } else { + argTypes = execParameterTypes; + } + + if (argTypes.length < annotationArgs.length) { + throw new RuntimeException(String.format( + "Too many annotation values %s for [%s]", + List.of(annotationArgs), exec)); + } + + var args = mapArgs(exec, IntStream.range(0, argTypes.length).mapToObj(idx -> { + return fromString(annotationArgs[idx], argTypes[idx]); + }).toArray(Object[]::new)); + + return List.<Object[]>of(args); + } + + private List<Object[]> createArgsForAnnotation(Executable exec, + ParameterSupplier a) throws IllegalAccessException, + InvocationTargetException { + if (!canRunOnTheOperatingSystem(a)) { + return List.of(); + } + + final Class<?> execClass = exec.getDeclaringClass(); + final var supplierFuncName = a.value(); + + final MethodQuery methodQuery; + if (!a.value().contains(".")) { + // No class name specified + methodQuery = new MethodQuery(execClass.getName(), a.value()); + } else { + methodQuery = MethodQuery.fromQualifiedMethodName(supplierFuncName); + } + + final Method supplierMethod; + try { + final var parameterSupplierCandidates = findNullaryLikeMethods(methodQuery); + final Function<String, Class> classForName = toFunction(Class::forName); + final var supplierMethodClass = classForName.apply(methodQuery.className()); + if (parameterSupplierCandidates.isEmpty()) { + throw new RuntimeException(String.format( + "No parameter suppliers in [%s] class", + supplierMethodClass.getName())); + } + + var allParameterSuppliers = filterParameterSuppliers(supplierMethodClass).toList(); + + supplierMethod = findNullaryLikeMethods(methodQuery) + .stream() + .filter(allParameterSuppliers::contains) + .findFirst().orElseThrow(() -> { + var msg = String.format( + "No suitable parameter supplier found for %s(%s) annotation", + a, supplierFuncName); + trace(String.format( + "%s. Parameter suppliers of %s class:", msg, + execClass.getName())); + IntStream.range(0, allParameterSuppliers.size()).mapToObj(idx -> { + return String.format(" [%d/%d] %s()", idx + 1, + allParameterSuppliers.size(), + allParameterSuppliers.get(idx).getName()); + }).forEachOrdered(TestMethodSupplier::trace); + + return new RuntimeException(msg); + }); + } catch (NoSuchMethodException ex) { + throw new RuntimeException(String.format( + "Method not found for %s(%s) annotation", a, supplierFuncName)); + } + + return createArgs(supplierMethod).map(args -> { + return mapArgs(exec, args); + }).toList(); + } + + private boolean canRunOnTheOperatingSystem(Annotation a) { + switch (a) { + case Test t -> { + return canRunOnTheOperatingSystem(os, t.ifOS(), t.ifNotOS()); + } + case Parameters t -> { + return canRunOnTheOperatingSystem(os, t.ifOS(), t.ifNotOS()); + } + case Parameter t -> { + return canRunOnTheOperatingSystem(os, t.ifOS(), t.ifNotOS()); + } + case ParameterSupplier t -> { + return canRunOnTheOperatingSystem(os, t.ifOS(), t.ifNotOS()); + } + default -> { + return true; + } + } + } + + private static boolean isParameterized(Method method) { + return Stream.of( + Parameter.class, ParameterGroup.class, + ParameterSupplier.class, ParameterSupplierGroup.class + ).anyMatch(method::isAnnotationPresent); + } + + private static boolean isTest(Method method) { + return method.isAnnotationPresent(Test.class); + } + + private static boolean canRunOnTheOperatingSystem(OperatingSystem value, + OperatingSystem[] include, OperatingSystem[] exclude) { + Set<OperatingSystem> suppordOperatingSystems = new HashSet<>(); + suppordOperatingSystems.addAll(List.of(include)); + suppordOperatingSystems.removeAll(List.of(exclude)); + return suppordOperatingSystems.contains(value); + } + + private static Parameter[] getMethodParameters(Method method) { + if (method.isAnnotationPresent(ParameterGroup.class)) { + return ((ParameterGroup) method.getAnnotation(ParameterGroup.class)).value(); + } + + if (method.isAnnotationPresent(Parameter.class)) { + return new Parameter[]{(Parameter) method.getAnnotation(Parameter.class)}; + } + + return new Parameter[0]; + } + + private static ParameterSupplier[] getMethodParameterSuppliers(Method method) { + if (method.isAnnotationPresent(ParameterSupplierGroup.class)) { + return ((ParameterSupplierGroup) method.getAnnotation(ParameterSupplierGroup.class)).value(); + } + + if (method.isAnnotationPresent(ParameterSupplier.class)) { + return new ParameterSupplier[]{(ParameterSupplier) method.getAnnotation( + ParameterSupplier.class)}; + } + + return new ParameterSupplier[0]; + } + + private static Stream<Method> filterParameterSuppliers(Class<?> type) { + return Stream.of(type.getMethods()) + .filter(m -> m.getParameterCount() == 0) + .filter(m -> (m.getModifiers() & Modifier.STATIC) != 0) + .sorted(Comparator.comparing(Method::getName)); + } + + private static Stream<Object[]> createArgs(Method ... parameterSuppliers) throws + IllegalAccessException, InvocationTargetException { + List<Object[]> args = new ArrayList<>(); + for (var parameterSupplier : parameterSuppliers) { + args.addAll((Collection) parameterSupplier.invoke(null)); + } + return args.stream(); + } + + private static Object fromString(String value, Class toType) { + if (toType.isEnum()) { + return Enum.valueOf(toType, value); + } + Function<String, Object> converter = FROM_STRING.get(toType); + if (converter == null) { + throw new RuntimeException(String.format( + "Failed to find a conversion of [%s] string to %s type", + value, toType.getName())); + } + return converter.apply(value); + } + + private static void trace(String msg) { + if (TKit.VERBOSE_TEST_SETUP) { + TKit.log(msg); + } + } + + static class InvalidAnnotationException extends Exception { + InvalidAnnotationException(String msg) { + super(msg); + } + } + + private static class Verifier { + static boolean isTestClass(Class<?> type) { + for (var method : type.getDeclaredMethods()) { + if (isParameterized(method) || isTest(method)) { + return true; + } + } + return false; + } + + static void verifyTestClass(Class<?> type) throws InvalidAnnotationException { + boolean withTestAnnotations = false; + for (var method : type.getDeclaredMethods()) { + if (!withTestAnnotations && (isParameterized(method) || isTest(method))) { + withTestAnnotations = true; + } + verifyAnnotationsCorrect(method); + } + + if (!withTestAnnotations) { + throwNotTestClassException(type); + } + } + + static void throwNotTestClassException(Class<?> type) throws InvalidAnnotationException { + throw new InvalidAnnotationException(String.format( + "Type [%s] is not a test class", type.getName())); + } + + private static void verifyAnnotationsCorrect(Method method) throws + InvalidAnnotationException { + var parameterized = isParameterized(method); + if (parameterized && !isTest(method)) { + throw new InvalidAnnotationException(String.format( + "Missing %s annotation on [%s] method", Test.class.getName(), method)); + } + + var isPublic = Modifier.isPublic(method.getModifiers()); + + if (isTest(method) && !isPublic) { + throw new InvalidAnnotationException(String.format( + "Non-public method [%s] with %s annotation", + method, Test.class.getName())); + } + + if (method.isAnnotationPresent(Parameters.class) && !isPublic) { + throw new InvalidAnnotationException(String.format( + "Non-public method [%s] with %s annotation", + method, Test.class.getName())); + } + } + } + + private enum TypeStatus { + NOT_TEST_CLASS, + TEST_CLASS, + VALID_TEST_CLASS, + } + + private final OperatingSystem os; + private final Map<Class<?>, TypeStatus> processedTypes = new HashMap<>(); + + private static final Object[] DEFAULT_CTOR_ARGS = new Object[0]; + + private static final Map<Class, Function<String, Object>> FROM_STRING; + + static { + Map<Class, Function<String, Object>> primitives = Map.of( + boolean.class, Boolean::valueOf, + byte.class, Byte::valueOf, + short.class, Short::valueOf, + int.class, Integer::valueOf, + long.class, Long::valueOf, + float.class, Float::valueOf, + double.class, Double::valueOf); + + Map<Class, Function<String, Object>> boxed = Map.of( + Boolean.class, Boolean::valueOf, + Byte.class, Byte::valueOf, + Short.class, Short::valueOf, + Integer.class, Integer::valueOf, + Long.class, Long::valueOf, + Float.class, Float::valueOf, + Double.class, Double::valueOf); + + Map<Class, Function<String, Object>> other = Map.of( + String.class, String::valueOf, + Path.class, Path::of); + + Map<Class, Function<String, Object>> combined = new HashMap<>(primitives); + combined.putAll(other); + combined.putAll(boxed); + + FROM_STRING = Collections.unmodifiableMap(combined); + } +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 338ff7a767b..4fb937864aa 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -23,6 +23,7 @@ package jdk.jpackage.test; import java.io.IOException; +import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; @@ -36,7 +37,9 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.jpackage.test.Functional.ThrowingRunnable; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import jdk.jpackage.internal.util.function.ThrowingRunnable; +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import jdk.jpackage.test.PackageTest.PackageHandlers; public class WindowsHelper { @@ -64,22 +67,6 @@ private static Path getInstallationSubDirectory(JPackageCommand cmd) { return Path.of(cmd.getArgumentValue("--install-dir", cmd::name)); } - // Tests have problems on windows where path in the temp dir are too long - // for the wix tools. We can't use a tempDir outside the TKit's WorkDir, so - // we minimize both the tempRoot directory name (above) and the tempDir name - // (below) to the extension part (which is necessary to differenciate between - // the multiple PackageTypes that will be run for one JPackageCommand). - // It might be beter if the whole work dir name was shortened from: - // jtreg_open_test_jdk_tools_jpackage_share_jdk_jpackage_tests_BasicTest_java. - public static Path getTempDirectory(JPackageCommand cmd, Path tempRoot) { - String ext = cmd.outputBundle().getFileName().toString(); - int i = ext.lastIndexOf("."); - if (i > 0 && i < (ext.length() - 1)) { - ext = ext.substring(i+1); - } - return tempRoot.resolve(ext); - } - private static void runMsiexecWithRetries(Executor misexec) { Executor.Result result = null; for (int attempt = 0; attempt < 8; ++attempt) { @@ -110,8 +97,9 @@ private static void runMsiexecWithRetries(Executor misexec) { static PackageHandlers createMsiPackageHandlers() { BiConsumer<JPackageCommand, Boolean> installMsi = (cmd, install) -> { cmd.verifyIsOfType(PackageType.WIN_MSI); + var msiPath = TransientMsi.create(cmd).path(); runMsiexecWithRetries(Executor.of("msiexec", "/qn", "/norestart", - install ? "/i" : "/x").addArgument(cmd.outputBundle().normalize())); + install ? "/i" : "/x").addArgument(msiPath)); }; PackageHandlers msi = new PackageHandlers(); @@ -128,6 +116,8 @@ static PackageHandlers createMsiPackageHandlers() { TKit.removeRootFromAbsolutePath( getInstallationRootDirectory(cmd))); + final Path msiPath = TransientMsi.create(cmd).path(); + // Put msiexec in .bat file because can't pass value of TARGETDIR // property containing spaces through ProcessBuilder properly. // Set folder permissions to allow msiexec unpack msi bundle. @@ -137,7 +127,7 @@ static PackageHandlers createMsiPackageHandlers() { String.join(" ", List.of( "msiexec", "/a", - String.format("\"%s\"", cmd.outputBundle().normalize()), + String.format("\"%s\"", msiPath), "/qn", String.format("TARGETDIR=\"%s\"", unpackDir.toAbsolutePath().normalize()))))); @@ -171,6 +161,49 @@ static PackageHandlers createMsiPackageHandlers() { return msi; } + record TransientMsi(Path path) { + static TransientMsi create(JPackageCommand cmd) { + var outputMsiPath = cmd.outputBundle().normalize(); + if (isPathTooLong(outputMsiPath)) { + return toSupplier(() -> { + var transientMsiPath = TKit.createTempDirectory("msi-copy").resolve("a.msi").normalize(); + TKit.trace(String.format("Copy [%s] to [%s]", outputMsiPath, transientMsiPath)); + Files.copy(outputMsiPath, transientMsiPath); + return new TransientMsi(transientMsiPath); + }).get(); + } else { + return new TransientMsi(outputMsiPath); + } + } + } + + public enum WixType { + WIX3, + WIX4 + } + + public static WixType getWixTypeFromVerboseJPackageOutput(Executor.Result result) { + return result.getOutput().stream().map(str -> { + if (str.contains("[light.exe]")) { + return WixType.WIX3; + } else if (str.contains("[wix.exe]")) { + return WixType.WIX4; + } else { + return null; + } + }).filter(Objects::nonNull).reduce((a, b) -> { + throw new IllegalArgumentException("Invalid input: multiple invocations of WiX tools"); + }).orElseThrow(() -> new IllegalArgumentException("Invalid input: no invocations of WiX tools")); + } + + static Optional<Path> toShortPath(Path path) { + if (isPathTooLong(path)) { + return Optional.of(ShortPathUtils.toShortPath(path)); + } else { + return Optional.empty(); + } + } + static PackageHandlers createExePackageHandlers() { BiConsumer<JPackageCommand, Boolean> installExe = (cmd, install) -> { cmd.verifyIsOfType(PackageType.WIN_EXE); @@ -319,6 +352,10 @@ private static boolean isUserLocalInstall(JPackageCommand cmd) { return cmd.hasArgument("--win-per-user-install"); } + private static boolean isPathTooLong(Path path) { + return path.toString().length() > WIN_MAX_PATH; + } + private static class DesktopIntegrationVerifier { DesktopIntegrationVerifier(JPackageCommand cmd, String launcherName) { @@ -541,6 +578,32 @@ private static String queryRegistryValueCache(String keyPath, return value; } + private static final class ShortPathUtils { + private ShortPathUtils() { + try { + var shortPathUtilsClass = Class.forName("jdk.jpackage.internal.ShortPathUtils"); + + getShortPathWrapper = shortPathUtilsClass.getDeclaredMethod( + "getShortPathWrapper", String.class); + // Note: this reflection call requires + // --add-opens jdk.jpackage/jdk.jpackage.internal=ALL-UNNAMED + getShortPathWrapper.setAccessible(true); + } catch (ClassNotFoundException | NoSuchMethodException + | SecurityException ex) { + throw rethrowUnchecked(ex); + } + } + + static Path toShortPath(Path path) { + return Path.of(toSupplier(() -> (String) INSTANCE.getShortPathWrapper.invoke( + null, path.toString())).get()); + } + + private final Method getShortPathWrapper; + + private static final ShortPathUtils INSTANCE = new ShortPathUtils(); + } + static final Set<Path> CRITICAL_RUNTIME_FILES = Set.of(Path.of( "bin\\server\\jvm.dll")); @@ -556,4 +619,6 @@ private static String queryRegistryValueCache(String keyPath, private static final String USER_SHELL_FOLDERS_REGKEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; private static final Map<String, String> REGISTRY_VALUES = new HashMap<>(); + + private static final int WIN_MAX_PATH = 260; } diff --git a/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java b/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java index 0d8f0ec4805..aef46e29725 100644 --- a/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java +++ b/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java @@ -22,7 +22,7 @@ */ import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Functional.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; diff --git a/test/jdk/tools/jpackage/linux/jdk/jpackage/tests/UsrTreeTest.java b/test/jdk/tools/jpackage/linux/UsrTreeTest.java similarity index 100% rename from test/jdk/tools/jpackage/linux/jdk/jpackage/tests/UsrTreeTest.java rename to test/jdk/tools/jpackage/linux/UsrTreeTest.java diff --git a/test/jdk/tools/jpackage/share/AppContentTest.java b/test/jdk/tools/jpackage/share/AppContentTest.java index e056070a5fc..d33960092ee 100644 --- a/test/jdk/tools/jpackage/share/AppContentTest.java +++ b/test/jdk/tools/jpackage/share/AppContentTest.java @@ -33,8 +33,8 @@ import java.util.List; import static java.util.stream.Collectors.joining; import java.util.stream.Stream; -import jdk.jpackage.internal.IOUtils; -import jdk.jpackage.test.Functional.ThrowingFunction; +import jdk.jpackage.internal.util.FileUtils; +import jdk.jpackage.internal.util.function.ThrowingFunction; import jdk.jpackage.test.JPackageCommand; @@ -65,7 +65,7 @@ public class AppContentTest { // In particular, random files should be placed in "Contents/Resources" folder // otherwise "codesign" will fail to sign. // Need to prepare arguments for `--app-content` accordingly. - private final static boolean copyInResources = TKit.isOSX(); + private static final boolean copyInResources = TKit.isOSX(); private final List<String> testPathArgs; @@ -148,7 +148,7 @@ private static Path copyAppContentPath(Path appContentPath) throws IOException { var srcPath = TKit.TEST_SRC_ROOT.resolve(appContentPath); var dstPath = appContentArg.resolve(srcPath.getFileName()); Files.createDirectories(dstPath.getParent()); - IOUtils.copyRecursive(srcPath, dstPath); + FileUtils.copyRecursive(srcPath, dstPath); return appContentArg; } diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java b/test/jdk/tools/jpackage/share/AppVersionTest.java similarity index 98% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java rename to test/jdk/tools/jpackage/share/AppVersionTest.java index d4f28ec17be..efd025590d2 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java +++ b/test/jdk/tools/jpackage/share/AppVersionTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.IOException; import java.util.Collection; @@ -46,7 +45,7 @@ * @build jdk.jpackage.test.* * @compile AppVersionTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.AppVersionTest + * --jpt-run=AppVersionTest */ public final class AppVersionTest { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java b/test/jdk/tools/jpackage/share/BasicTest.java similarity index 95% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java rename to test/jdk/tools/jpackage/share/BasicTest.java index 1222fa95949..c6e4e930155 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java +++ b/test/jdk/tools/jpackage/share/BasicTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.IOException; import java.nio.file.Files; @@ -42,11 +41,9 @@ import jdk.jpackage.test.JavaTool; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Functional.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; import static jdk.jpackage.test.RunnablePackageTest.Action.CREATE_AND_UNPACK; -import static jdk.jpackage.test.WindowsHelper.getTempDirectory; - /* * @test * @summary jpackage basic testing @@ -54,7 +51,7 @@ * @build jdk.jpackage.test.* * @compile BasicTest.java * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.BasicTest + * --jpt-run=BasicTest */ public final class BasicTest { @@ -345,7 +342,7 @@ public void testTemp(TestTempType type) throws IOException { // Force save of package bundle in test work directory. .addInitializer(JPackageCommand::setDefaultInputOutput) .addInitializer(cmd -> { - Path tempDir = getTempDirectory(cmd, tempRoot); + Path tempDir = tempRoot.resolve(cmd.packageType().name()); switch (type) { case TEMPDIR_EMPTY -> Files.createDirectories(tempDir); case TEMPDIR_NOT_EXIST -> Files.createDirectories(tempDir.getParent()); @@ -362,20 +359,16 @@ public void testTemp(TestTempType type) throws IOException { if (TestTempType.TEMPDIR_NOT_EMPTY.equals(type)) { pkgTest.setExpectedExitCode(1).addBundleVerifier(cmd -> { // Check jpackage didn't use the supplied directory. - Path tempDir = getTempDirectory(cmd, tempRoot); - String[] tempDirContents = tempDir.toFile().list(); - TKit.assertStringListEquals(List.of("foo.txt"), List.of( - tempDirContents), String.format( - "Check the contents of the supplied temporary directory [%s]", - tempDir)); + Path tempDir = Path.of(cmd.getArgumentValue("--temp")); + TKit.assertDirectoryContent(tempDir).match(Path.of("foo.txt")); TKit.assertStringListEquals(List.of("Hello Duke!"), - Files.readAllLines(tempDir.resolve(tempDirContents[0])), + Files.readAllLines(tempDir.resolve("foo.txt")), "Check the contents of the file in the supplied temporary directory"); }); } else { pkgTest.addBundleVerifier(cmd -> { // Check jpackage used the supplied directory. - Path tempDir = getTempDirectory(cmd, tempRoot); + Path tempDir = Path.of(cmd.getArgumentValue("--temp")); TKit.assertDirectoryNotEmpty(tempDir); }); } diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/CookedRuntimeTest.java b/test/jdk/tools/jpackage/share/CookedRuntimeTest.java similarity index 98% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/CookedRuntimeTest.java rename to test/jdk/tools/jpackage/share/CookedRuntimeTest.java index cfb6ec13ccf..e8bd034bfb4 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/CookedRuntimeTest.java +++ b/test/jdk/tools/jpackage/share/CookedRuntimeTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.IOException; import java.nio.file.Files; @@ -46,7 +45,7 @@ * @build jdk.jpackage.test.* * @compile CookedRuntimeTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.CookedRuntimeTest + * --jpt-run=CookedRuntimeTest */ public final class CookedRuntimeTest { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/DotInNameTest.java b/test/jdk/tools/jpackage/share/DotInNameTest.java similarity index 96% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/DotInNameTest.java rename to test/jdk/tools/jpackage/share/DotInNameTest.java index 73be2c2e47a..2617db26183 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/DotInNameTest.java +++ b/test/jdk/tools/jpackage/share/DotInNameTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.HelloApp; @@ -37,7 +36,7 @@ * @build jdk.jpackage.test.* * @compile DotInNameTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.DotInNameTest + * --jpt-run=DotInNameTest * --jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault */ diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java similarity index 53% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/ErrorTest.java rename to test/jdk/tools/jpackage/share/ErrorTest.java index 57603809607..ed7338a76dd 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -21,13 +21,16 @@ * questions. */ -package jdk.jpackage.tests; import java.util.Collection; import java.util.List; -import jdk.jpackage.test.Annotations.Parameters; +import java.util.Optional; +import java.util.stream.Stream; +import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.CannedFormattedString; import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JPackageStringBundle; import jdk.jpackage.test.TKit; /* @@ -37,7 +40,7 @@ * @build jdk.jpackage.test.* * @compile ErrorTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.ErrorTest + * --jpt-run=ErrorTest * --jpt-before-run=jdk.jpackage.test.JPackageCommand.useExecutableByDefault */ @@ -48,87 +51,91 @@ * @build jdk.jpackage.test.* * @compile ErrorTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.ErrorTest + * --jpt-run=ErrorTest * --jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault */ public final class ErrorTest { - private final String expectedError; - private final JPackageCommand cmd; - - @Parameters public static Collection input() { return List.of(new Object[][]{ // non-existent arg {"Hello", new String[]{"--no-such-argument"}, null, - "Invalid Option: [--no-such-argument]"}, + JPackageStringBundle.MAIN.cannedFormattedString("ERR_InvalidOption", "--no-such-argument")}, // no main jar {"Hello", null, new String[]{"--main-jar"}, - "--main-jar or --module"}, + JPackageStringBundle.MAIN.cannedFormattedString("ERR_NoEntryPoint")}, // no main-class {"Hello", null, new String[]{"--main-class"}, - "main class was not specified"}, + JPackageStringBundle.MAIN.cannedFormattedString("error.no-main-class-with-main-jar", "hello.jar"), + JPackageStringBundle.MAIN.cannedFormattedString("error.no-main-class-with-main-jar.advice", "hello.jar")}, // non-existent main jar {"Hello", new String[]{"--main-jar", "non-existent.jar"}, null, - "main jar does not exist"}, + JPackageStringBundle.MAIN.cannedFormattedString("error.main-jar-does-not-exist", "non-existent.jar")}, // non-existent runtime {"Hello", new String[]{"--runtime-image", "non-existent.runtime"}, null, - "does not exist"}, + JPackageStringBundle.MAIN.cannedFormattedString("message.runtime-image-dir-does-not-exist", "runtime-image", "non-existent.runtime")}, // non-existent resource-dir {"Hello", new String[]{"--resource-dir", "non-existent.dir"}, null, - "does not exist"}, + JPackageStringBundle.MAIN.cannedFormattedString("message.resource-dir-does-not-exist", "resource-dir", "non-existent.dir")}, // invalid type {"Hello", new String[]{"--type", "invalid-type"}, null, - "Invalid or unsupported type: [invalid-type]"}, + JPackageStringBundle.MAIN.cannedFormattedString("ERR_InvalidInstallerType", "invalid-type")}, // no --input {"Hello", null, new String[]{"--input"}, - "Missing argument: --input"}, + JPackageStringBundle.MAIN.cannedFormattedString("ERR_MissingArgument", "--input")}, // no --module-path {"com.other/com.other.Hello", null, new String[]{"--module-path"}, - "Missing argument: --runtime-image or --module-path"}, + JPackageStringBundle.MAIN.cannedFormattedString("ERR_MissingArgument", "--runtime-image or --module-path")}, }); } - public ErrorTest(String javaAppDesc, String[] jpackageArgs, - String[] removeArgs, - String expectedError) { - this.expectedError = expectedError; + @Test + @ParameterSupplier("input") + public static void test(String javaAppDesc, String[] jpackageArgs, + String[] removeArgs, CannedFormattedString... expectedErrors) { + // Init default jpackage test command line. + var cmd = JPackageCommand.helloAppImage(javaAppDesc) + // Disable default logic adding `--verbose` option + // to jpackage command line. + // It will affect jpackage error messages if the command line is malformed. + .ignoreDefaultVerbose(true) + // Ignore external runtime as it will interfer + // with jpackage arguments in this test. + .ignoreDefaultRuntime(true); - cmd = JPackageCommand.helloAppImage(javaAppDesc) - .saveConsoleOutput(true).dumpOutput(true); - if (jpackageArgs != null) { - cmd.addArguments(jpackageArgs); - } if (removeArgs != null) { - for (String arg : removeArgs) { - cmd.removeArgumentWithValue(arg); - } - } - } + // Add arguments if requested. + Optional.ofNullable(jpackageArgs).ifPresent(cmd::addArguments); - @Test - public void test() { - List<String> output = cmd.execute(1).getOutput(); - TKit.assertNotNull(output, "output is null"); - TKit.assertTextStream(expectedError).apply(output.stream()); - } + // Remove arguments if requested. + Optional.ofNullable(removeArgs).map(List::of).ifPresent( + args -> args.forEach(cmd::removeArgumentWithValue)); + + // Configure jpackage output verifier to look up the list of provided + // errors in the order they specified. + cmd.validateOutput(Stream.of(expectedErrors) + .map(CannedFormattedString::getValue) + .map(TKit::assertTextStream) + .reduce(TKit.TextStreamVerifier::andThen).get()); + cmd.execute(1); + } } diff --git a/test/jdk/tools/jpackage/share/IconTest.java b/test/jdk/tools/jpackage/share/IconTest.java index 2d6469f5f2e..d5edbc93245 100644 --- a/test/jdk/tools/jpackage/share/IconTest.java +++ b/test/jdk/tools/jpackage/share/IconTest.java @@ -41,8 +41,8 @@ import jdk.jpackage.test.Executor; import jdk.jpackage.test.LinuxHelper; import jdk.jpackage.test.AdditionalLauncher; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import jdk.jpackage.test.Functional.ThrowingBiConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingBiConsumer; import jdk.jpackage.test.Annotations.Parameters; import jdk.jpackage.test.Annotations.Test; @@ -428,7 +428,7 @@ private enum Launcher { private final Path cmdlineIcon; private final Path resourceDirIcon; - private final static Set<Launcher> PRIMARY = Set.of(Main, Additional); + private static final Set<Launcher> PRIMARY = Set.of(Main, Additional); } private final boolean appImage; @@ -440,7 +440,7 @@ private static Path iconPath(String name) { + TKit.ICON_SUFFIX)); } - private final static Path[] ICONS = Stream.of("icon", "icon2", "icon3", + private static final Path[] ICONS = Stream.of("icon", "icon2", "icon3", "icon4") .map(IconTest::iconPath) .collect(Collectors.toList()).toArray(Path[]::new); diff --git a/test/jdk/tools/jpackage/share/InOutPathTest.java b/test/jdk/tools/jpackage/share/InOutPathTest.java index f8cb983bd16..b2579133148 100644 --- a/test/jdk/tools/jpackage/share/InOutPathTest.java +++ b/test/jdk/tools/jpackage/share/InOutPathTest.java @@ -29,14 +29,14 @@ import java.util.List; import java.util.Set; import java.util.function.Predicate; -import static java.util.stream.Collectors.toSet; import java.util.stream.Stream; +import jdk.internal.util.OperatingSystem; import jdk.jpackage.internal.AppImageFile; import jdk.jpackage.internal.ApplicationLayout; import jdk.jpackage.internal.PackageFile; -import jdk.jpackage.test.Annotations; +import jdk.jpackage.test.Annotations.Parameters; import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Functional.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JPackageCommand.AppLayoutAssert; import jdk.jpackage.test.PackageTest; @@ -55,47 +55,51 @@ */ public final class InOutPathTest { - @Annotations.Parameters + @Parameters public static Collection input() { List<Object[]> data = new ArrayList<>(); - for (var packageTypes : List.of(PackageType.IMAGE.toString(), ALL_NATIVE_PACKAGE_TYPES)) { + for (var packageTypeAlias : PackageTypeAlias.values()) { data.addAll(List.of(new Object[][]{ - {packageTypes, wrap(InOutPathTest::outputDirInInputDir, "--dest in --input")}, - {packageTypes, wrap(InOutPathTest::outputDirSameAsInputDir, "--dest same as --input")}, - {packageTypes, wrap(InOutPathTest::tempDirInInputDir, "--temp in --input")}, - {packageTypes, wrap(cmd -> { + {packageTypeAlias, wrap(InOutPathTest::outputDirInInputDir, "--dest in --input")}, + {packageTypeAlias, wrap(InOutPathTest::outputDirSameAsInputDir, "--dest same as --input")}, + {packageTypeAlias, wrap(InOutPathTest::tempDirInInputDir, "--temp in --input")}, + {packageTypeAlias, wrap(cmd -> { outputDirInInputDir(cmd); tempDirInInputDir(cmd); }, "--dest and --temp in --input")}, })); - data.addAll(additionalContentInput(packageTypes, "--app-content")); + data.addAll(additionalContentInput(packageTypeAlias, "--app-content")); } - if (!TKit.isOSX()) { - data.addAll(List.of(new Object[][]{ - {PackageType.IMAGE.toString(), wrap(cmd -> { - additionalContent(cmd, "--app-content", cmd.outputBundle()); - }, "--app-content same as output bundle")}, - })); - } else { - var contentsFolder = "Contents/MacOS"; - data.addAll(List.of(new Object[][]{ - {PackageType.IMAGE.toString(), wrap(cmd -> { - additionalContent(cmd, "--app-content", cmd.outputBundle().resolve(contentsFolder)); - }, String.format("--app-content same as the \"%s\" folder in the output bundle", contentsFolder))}, - })); - } + return data; + } - if (TKit.isOSX()) { - data.addAll(additionalContentInput(PackageType.MAC_DMG.toString(), - "--mac-dmg-content")); - } + @Parameters(ifNotOS = OperatingSystem.MACOS) + public static Collection<Object[]> appContentInputOther() { + return List.of(new Object[][]{ + {PackageTypeAlias.IMAGE, wrap(cmd -> { + additionalContent(cmd, "--app-content", cmd.outputBundle()); + }, "--app-content same as output bundle")}, + }); + } - return data; + @Parameters(ifOS = OperatingSystem.MACOS) + public static Collection<Object[]> appContentInputOSX() { + var contentsFolder = "Contents/MacOS"; + return List.of(new Object[][]{ + {PackageTypeAlias.IMAGE, wrap(cmd -> { + additionalContent(cmd, "--app-content", cmd.outputBundle().resolve(contentsFolder)); + }, String.format("--app-content same as the \"%s\" folder in the output bundle", contentsFolder))}, + }); } - private static List<Object[]> additionalContentInput(String packageTypes, String argName) { + @Parameters(ifOS = OperatingSystem.MACOS) + public static Collection<Object[]> inputOSX() { + return List.of(additionalContentInput(PackageType.MAC_DMG, "--mac-dmg-content").toArray(Object[][]::new)); + } + + private static List<Object[]> additionalContentInput(Object packageTypes, String argName) { List<Object[]> data = new ArrayList<>(); data.addAll(List.of(new Object[][]{ @@ -127,13 +131,16 @@ private static List<Object[]> additionalContentInput(String packageTypes, String return data; } - public InOutPathTest(String packageTypes, Envelope configure) { - if (ALL_NATIVE_PACKAGE_TYPES.equals(packageTypes)) { - this.packageTypes = PackageType.NATIVE; - } else { - this.packageTypes = Stream.of(packageTypes.split(",")).map( - PackageType::valueOf).collect(toSet()); - } + public InOutPathTest(PackageTypeAlias packageTypeAlias, Envelope configure) { + this(packageTypeAlias.packageTypes, configure); + } + + public InOutPathTest(PackageType packageType, Envelope configure) { + this(Set.of(packageType), configure); + } + + public InOutPathTest(Set<PackageType> packageTypes, Envelope configure) { + this.packageTypes = packageTypes; this.configure = configure.value; } @@ -271,6 +278,18 @@ public String toString() { } } + private enum PackageTypeAlias { + IMAGE(Set.of(PackageType.IMAGE)), + NATIVE(PackageType.NATIVE), + ; + + PackageTypeAlias(Set<PackageType> packageTypes) { + this.packageTypes = packageTypes; + } + + private final Set<PackageType> packageTypes; + } + private final Set<PackageType> packageTypes; private final ThrowingConsumer<JPackageCommand> configure; @@ -279,6 +298,4 @@ public String toString() { // For other platforms it doesn't matter. Keep it the same across // all platforms for simplicity. private static final Path JAR_PATH = Path.of("Resources/duke.jar"); - - private static final String ALL_NATIVE_PACKAGE_TYPES = "NATIVE"; } diff --git a/test/jdk/tools/jpackage/share/InstallDirTest.java b/test/jdk/tools/jpackage/share/InstallDirTest.java index 7047f35e87b..23539589bcc 100644 --- a/test/jdk/tools/jpackage/share/InstallDirTest.java +++ b/test/jdk/tools/jpackage/share/InstallDirTest.java @@ -22,13 +22,12 @@ */ import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; +import jdk.internal.util.OperatingSystem; import jdk.jpackage.test.TKit; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.Functional; import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.Test; /** * Test --install-dir parameter. Output of the test should be @@ -76,28 +75,18 @@ */ public class InstallDirTest { - public static void testCommon() { - final Map<PackageType, Path> INSTALL_DIRS = Functional.identity(() -> { - Map<PackageType, Path> reply = new HashMap<>(); - reply.put(PackageType.WIN_MSI, Path.of("TestVendor\\InstallDirTest1234")); - reply.put(PackageType.WIN_EXE, reply.get(PackageType.WIN_MSI)); - - reply.put(PackageType.LINUX_DEB, Path.of("/opt/jpackage")); - reply.put(PackageType.LINUX_RPM, reply.get(PackageType.LINUX_DEB)); - - reply.put(PackageType.MAC_PKG, Path.of("/Applications/jpackage")); - reply.put(PackageType.MAC_DMG, reply.get(PackageType.MAC_PKG)); - - return reply; - }).get(); - + @Test + @Parameter(value = "TestVendor\\InstallDirTest1234", ifOS = OperatingSystem.WINDOWS) + @Parameter(value = "/opt/jpackage", ifOS = OperatingSystem.LINUX) + @Parameter(value = "/Applications/jpackage", ifOS = OperatingSystem.MACOS) + public static void testCommon(Path installDir) { new PackageTest().configureHelloApp() .addInitializer(cmd -> { - cmd.addArguments("--install-dir", INSTALL_DIRS.get( - cmd.packageType())); + cmd.addArguments("--install-dir", installDir); }).run(); } + @Test(ifOS = OperatingSystem.LINUX) @Parameter("/") @Parameter(".") @Parameter("foo") diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java b/test/jdk/tools/jpackage/share/JLinkOptionsTest.java similarity index 98% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java rename to test/jdk/tools/jpackage/share/JLinkOptionsTest.java index dce60890aba..d4f7bca2ae4 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JLinkOptionsTest.java +++ b/test/jdk/tools/jpackage/share/JLinkOptionsTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.util.Collection; import java.util.List; @@ -37,7 +36,7 @@ * @build jdk.jpackage.test.* * @compile JLinkOptionsTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.JLinkOptionsTest + * --jpt-run=JLinkOptionsTest */ public final class JLinkOptionsTest { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsEqualsTest.java b/test/jdk/tools/jpackage/share/JavaOptionsEqualsTest.java similarity index 96% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsEqualsTest.java rename to test/jdk/tools/jpackage/share/JavaOptionsEqualsTest.java index e1c809dadd3..b1f69c6395f 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsEqualsTest.java +++ b/test/jdk/tools/jpackage/share/JavaOptionsEqualsTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.util.Collection; import java.util.List; @@ -39,7 +38,7 @@ * @build jdk.jpackage.test.* * @compile JavaOptionsEqualsTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.JavaOptionsEqualsTest + * --jpt-run=JavaOptionsEqualsTest * --jpt-before-run=jdk.jpackage.test.JPackageCommand.useExecutableByDefault */ @@ -50,7 +49,7 @@ * @build jdk.jpackage.test.* * @compile JavaOptionsEqualsTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.JavaOptionsEqualsTest + * --jpt-run=JavaOptionsEqualsTest * --jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault */ diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsTest.java b/test/jdk/tools/jpackage/share/JavaOptionsTest.java similarity index 98% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsTest.java rename to test/jdk/tools/jpackage/share/JavaOptionsTest.java index cee455271aa..befc90accea 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/JavaOptionsTest.java +++ b/test/jdk/tools/jpackage/share/JavaOptionsTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.util.Collection; import java.util.List; @@ -39,7 +38,7 @@ * @build jdk.jpackage.test.* * @compile JavaOptionsTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.JavaOptionsTest + * --jpt-run=JavaOptionsTest * --jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault */ diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java b/test/jdk/tools/jpackage/share/MainClassTest.java similarity index 95% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java rename to test/jdk/tools/jpackage/share/MainClassTest.java index 641d0fd00bb..a031bbc2788 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java +++ b/test/jdk/tools/jpackage/share/MainClassTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.IOException; import java.nio.file.Files; @@ -45,8 +44,8 @@ import jdk.jpackage.test.Annotations.Parameters; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.CfgFile; -import jdk.jpackage.test.Functional.ThrowingConsumer; -import static jdk.jpackage.tests.MainClassTest.Script.MainClassType.*; +import jdk.jpackage.internal.util.function.ThrowingConsumer; + /* @@ -56,7 +55,7 @@ * @build jdk.jpackage.test.* * @compile MainClassTest.java * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.MainClassTest + * --jpt-run=MainClassTest */ public final class MainClassTest { @@ -82,7 +81,7 @@ Script withMainClass(MainClassType v) { } Script withJarMainClass(MainClassType v) { - appDesc.setWithMainClass(v != NotSet); + appDesc.setWithMainClass(v != MainClassType.NotSet); jarMainClass = v; return this; } @@ -172,7 +171,8 @@ public MainClassTest(Script script) { @Parameters public static Collection scripts() { - final var withMainClass = Set.of(SetWrong, SetRight); + final var withMainClass = Set.of(Script.MainClassType.SetWrong, + Script.MainClassType.SetRight); List<Script[]> scripts = new ArrayList<>(); for (var withJLink : List.of(true, false)) { @@ -205,7 +205,7 @@ public static Collection scripts() { @Test public void test() throws IOException { - if (script.jarMainClass == SetWrong) { + if (script.jarMainClass == Script.MainClassType.SetWrong) { initJarWithWrongMainClass(); } @@ -224,11 +224,11 @@ public void test() throws IOException { boolean appShouldSucceed = false; // Should succeed if valid main class is set on the command line. - appShouldSucceed |= (script.mainClass == SetRight); + appShouldSucceed |= (script.mainClass == Script.MainClassType.SetRight); // Should succeed if main class is not set on the command line but set // to valid value in the jar. - appShouldSucceed |= (script.mainClass == NotSet && script.jarMainClass == SetRight); + appShouldSucceed |= (script.mainClass == Script.MainClassType.NotSet && script.jarMainClass == Script.MainClassType.SetRight); if (appShouldSucceed) { cmd.executeAndAssertHelloAppImageCreated(); diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java b/test/jdk/tools/jpackage/share/ModulePathTest.java similarity index 98% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java rename to test/jdk/tools/jpackage/share/ModulePathTest.java index c42a24ec310..7d1e86f8ae2 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java +++ b/test/jdk/tools/jpackage/share/ModulePathTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.File; import java.io.IOException; @@ -48,7 +47,7 @@ * @build jdk.jpackage.test.* * @compile ModulePathTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.ModulePathTest + * --jpt-run=ModulePathTest */ public final class ModulePathTest { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest2.java b/test/jdk/tools/jpackage/share/ModulePathTest2.java similarity index 97% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest2.java rename to test/jdk/tools/jpackage/share/ModulePathTest2.java index 7b1ec2f5b63..34144907bdb 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest2.java +++ b/test/jdk/tools/jpackage/share/ModulePathTest2.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.IOException; import java.nio.file.Path; @@ -40,7 +39,7 @@ * @build jdk.jpackage.test.* * @compile ModulePathTest2.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.ModulePathTest2 + * --jpt-run=ModulePathTest2 */ public final class ModulePathTest2 { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java b/test/jdk/tools/jpackage/share/ModulePathTest3.java similarity index 98% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java rename to test/jdk/tools/jpackage/share/ModulePathTest3.java index d6fca043920..b4b51e1adfc 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java +++ b/test/jdk/tools/jpackage/share/ModulePathTest3.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.IOException; import java.nio.file.Files; @@ -53,7 +52,7 @@ * @build jdk.jpackage.test.* * @compile ModulePathTest3.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.ModulePathTest3 + * --jpt-run=ModulePathTest3 */ public final class ModulePathTest3 { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MultipleJarAppTest.java b/test/jdk/tools/jpackage/share/MultipleJarAppTest.java similarity index 96% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/MultipleJarAppTest.java rename to test/jdk/tools/jpackage/share/MultipleJarAppTest.java index 38878929006..0726b131d69 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MultipleJarAppTest.java +++ b/test/jdk/tools/jpackage/share/MultipleJarAppTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.nio.file.Path; import jdk.jpackage.test.Annotations.Test; @@ -37,7 +36,7 @@ * @build jdk.jpackage.test.* * @compile MultipleJarAppTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.MultipleJarAppTest + * --jpt-run=MultipleJarAppTest */ public final class MultipleJarAppTest { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NoMPathRuntimeTest.java b/test/jdk/tools/jpackage/share/NoMPathRuntimeTest.java similarity index 98% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/NoMPathRuntimeTest.java rename to test/jdk/tools/jpackage/share/NoMPathRuntimeTest.java index 4a9aef7860d..37319971183 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NoMPathRuntimeTest.java +++ b/test/jdk/tools/jpackage/share/NoMPathRuntimeTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.IOException; import java.nio.file.Files; @@ -47,7 +46,7 @@ * @build jdk.jpackage.test.* * @compile NoMPathRuntimeTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.NoMPathRuntimeTest + * --jpt-run=NoMPathRuntimeTest */ public final class NoMPathRuntimeTest { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NonExistentTest.java b/test/jdk/tools/jpackage/share/NonExistentTest.java similarity index 97% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/NonExistentTest.java rename to test/jdk/tools/jpackage/share/NonExistentTest.java index 8ca18af356c..4d50f2a5850 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/NonExistentTest.java +++ b/test/jdk/tools/jpackage/share/NonExistentTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.util.Collection; import java.util.List; @@ -37,7 +36,7 @@ * @build jdk.jpackage.test.* * @compile NonExistentTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.NonExistentTest + * --jpt-run=NonExistentTest */ public final class NonExistentTest { diff --git a/test/jdk/tools/jpackage/share/PerUserCfgTest.java b/test/jdk/tools/jpackage/share/PerUserCfgTest.java index 0fff7eb3a2d..2e62aa5c5d6 100644 --- a/test/jdk/tools/jpackage/share/PerUserCfgTest.java +++ b/test/jdk/tools/jpackage/share/PerUserCfgTest.java @@ -29,7 +29,7 @@ import jdk.jpackage.test.AdditionalLauncher; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Functional.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.HelloApp; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.LinuxHelper; diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/PredefinedAppImageErrorTest.java b/test/jdk/tools/jpackage/share/PredefinedAppImageErrorTest.java similarity index 96% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/PredefinedAppImageErrorTest.java rename to test/jdk/tools/jpackage/share/PredefinedAppImageErrorTest.java index b01a78120db..bdb4f6bfbd7 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/PredefinedAppImageErrorTest.java +++ b/test/jdk/tools/jpackage/share/PredefinedAppImageErrorTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.io.IOException; import java.nio.file.Path; @@ -42,11 +41,11 @@ * @compile PredefinedAppImageErrorTest.java * * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.PredefinedAppImageErrorTest + * --jpt-run=PredefinedAppImageErrorTest * --jpt-before-run=jdk.jpackage.test.JPackageCommand.useExecutableByDefault * * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.PredefinedAppImageErrorTest + * --jpt-run=PredefinedAppImageErrorTest * --jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault */ diff --git a/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java b/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java index 0e48df630af..649ac0a3695 100644 --- a/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java +++ b/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java @@ -21,20 +21,11 @@ * questions. */ -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import jdk.jpackage.internal.ApplicationLayout; import jdk.jpackage.test.TKit; -import jdk.jpackage.test.PackageTest; -import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.Functional; import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JavaTool; import jdk.jpackage.test.Executor; diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/UnicodeArgsTest.java b/test/jdk/tools/jpackage/share/UnicodeArgsTest.java similarity index 97% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/UnicodeArgsTest.java rename to test/jdk/tools/jpackage/share/UnicodeArgsTest.java index 29722086eec..6fa2717d15e 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/UnicodeArgsTest.java +++ b/test/jdk/tools/jpackage/share/UnicodeArgsTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import java.util.stream.Collectors; import jdk.jpackage.test.TKit; @@ -38,7 +37,7 @@ * @compile UnicodeArgsTest.java * @requires (os.family == "windows") * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.UnicodeArgsTest + * --jpt-run=UnicodeArgsTest */ public final class UnicodeArgsTest { diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java b/test/jdk/tools/jpackage/share/VendorTest.java similarity index 96% rename from test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java rename to test/jdk/tools/jpackage/share/VendorTest.java index b6e8f44dbf8..4c3a0ffcee2 100644 --- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java +++ b/test/jdk/tools/jpackage/share/VendorTest.java @@ -21,7 +21,6 @@ * questions. */ -package jdk.jpackage.tests; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; @@ -61,7 +60,7 @@ * @build jdk.jpackage.test.* * @compile VendorTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.VendorTest + * --jpt-run=VendorTest */ /* @@ -74,7 +73,7 @@ * @build jdk.jpackage.test.* * @compile VendorTest.java * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=jdk.jpackage.tests.VendorTest + * --jpt-run=VendorTest */ public class VendorTest { diff --git a/test/jdk/tools/jpackage/windows/WinL10nTest.java b/test/jdk/tools/jpackage/windows/WinL10nTest.java index d951b6f8832..dee1e42267d 100644 --- a/test/jdk/tools/jpackage/windows/WinL10nTest.java +++ b/test/jdk/tools/jpackage/windows/WinL10nTest.java @@ -22,7 +22,6 @@ */ import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import jdk.jpackage.test.TKit; import jdk.jpackage.test.PackageTest; @@ -36,8 +35,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.test.Executor; - -import static jdk.jpackage.test.WindowsHelper.getTempDirectory; +import static jdk.jpackage.test.WindowsHelper.WixType.WIX3; +import static jdk.jpackage.test.WindowsHelper.getWixTypeFromVerboseJPackageOutput; /* * @test @@ -112,13 +111,13 @@ public static List<Object[]> data() { }); } - private static Stream<String> getBuildCommandLine(Executor.Result result) { + private static Stream<String> getWixCommandLine(Executor.Result result) { return result.getOutput().stream().filter(createToolCommandLinePredicate("light").or( createToolCommandLinePredicate("wix"))); } private static boolean isWix3(Executor.Result result) { - return result.getOutput().stream().anyMatch(createToolCommandLinePredicate("light")); + return getWixTypeFromVerboseJPackageOutput(result) == WIX3; } private final static Predicate<String> createToolCommandLinePredicate(String wixToolName) { @@ -130,10 +129,10 @@ private final static Predicate<String> createToolCommandLinePredicate(String wix }; } - private static List<TKit.TextStreamVerifier> createDefaultL10nFilesLocVerifiers(Path tempDir) { + private static List<TKit.TextStreamVerifier> createDefaultL10nFilesLocVerifiers(Path wixSrcDir) { return Arrays.stream(DEFAULT_L10N_FILES).map(loc -> - TKit.assertTextStream("-loc " + tempDir.resolve( - String.format("config/MsiInstallerStrings_%s.wxl", loc)).normalize())) + TKit.assertTextStream("-loc " + wixSrcDir.resolve( + String.format("MsiInstallerStrings_%s.wxl", loc)))) .toList(); } @@ -182,21 +181,24 @@ public void test() throws IOException { } // Preserve config dir to check the set of copied l10n files. - Path tempDir = getTempDirectory(cmd, tempRoot); - Files.createDirectories(tempDir.getParent()); - cmd.addArguments("--temp", tempDir.toString()); + Path tempDir = tempRoot.resolve(cmd.packageType().name()); + cmd.addArguments("--temp", tempDir); }) .addBundleVerifier((cmd, result) -> { + final List<String> wixCmdline = getWixCommandLine(result).toList(); + + final var isWix3 = isWix3(result); + if (expectedCultures != null) { String expected; - if (isWix3(result)) { + if (isWix3) { expected = "-cultures:" + String.join(";", expectedCultures); } else { expected = Stream.of(expectedCultures).map(culture -> { return String.join(" ", "-culture", culture); }).collect(Collectors.joining(" ")); } - TKit.assertTextStream(expected).apply(getBuildCommandLine(result)); + TKit.assertTextStream(expected).apply(wixCmdline.stream()); } if (expectedErrorMessage != null) { @@ -205,25 +207,27 @@ public void test() throws IOException { } if (wxlFileInitializers != null) { - var wixSrcDir = Path.of(cmd.getArgumentValue("--temp")).resolve("config"); + var wixSrcDir = Path.of(cmd.getArgumentValue("--temp")).resolve( + "config").normalize().toAbsolutePath(); if (allWxlFilesValid) { for (var v : wxlFileInitializers) { if (!v.name.startsWith("MsiInstallerStrings_")) { - v.createCmdOutputVerifier(wixSrcDir).apply(getBuildCommandLine(result)); + v.createCmdOutputVerifier(wixSrcDir).apply(wixCmdline.stream()); } } - Path tempDir = getTempDirectory(cmd, tempRoot).toAbsolutePath(); - for (var v : createDefaultL10nFilesLocVerifiers(tempDir)) { - v.apply(getBuildCommandLine(result)); + + for (var v : createDefaultL10nFilesLocVerifiers(wixSrcDir)) { + v.apply(wixCmdline.stream()); } } else { Stream.of(wxlFileInitializers) .filter(Predicate.not(WixFileInitializer::isValid)) .forEach(v -> v.createCmdOutputVerifier( wixSrcDir).apply(result.getOutput().stream())); - TKit.assertFalse(getBuildCommandLine(result).findAny().isPresent(), - "Check light.exe was not invoked"); + TKit.assertTrue(wixCmdline.stream().findAny().isEmpty(), + String.format("Check %s.exe was not invoked", + isWix3 ? "light" : "wix")); } } }); @@ -280,10 +284,9 @@ boolean isValid() { } @Override - TKit.TextStreamVerifier createCmdOutputVerifier(Path root) { + TKit.TextStreamVerifier createCmdOutputVerifier(Path wixSrcDir) { return TKit.assertTextStream(String.format( - "Failed to parse %s file", - root.resolve("b.wxl").toAbsolutePath())); + "Failed to parse %s file", wixSrcDir.resolve("b.wxl"))); } }; } @@ -301,9 +304,8 @@ void apply(Path root) throws IOException { + "\" xmlns=\"http://schemas.microsoft.com/wix/2006/localization\" Codepage=\"1252\"/>")); } - TKit.TextStreamVerifier createCmdOutputVerifier(Path root) { - return TKit.assertTextStream( - "-loc " + root.resolve(name).toAbsolutePath().normalize()); + TKit.TextStreamVerifier createCmdOutputVerifier(Path wixSrcDir) { + return TKit.assertTextStream("-loc " + wixSrcDir.resolve(name)); } boolean isValid() { diff --git a/test/jdk/tools/jpackage/windows/WinLongPathTest.java b/test/jdk/tools/jpackage/windows/WinLongPathTest.java new file mode 100644 index 00000000000..e9e5ef8ce03 --- /dev/null +++ b/test/jdk/tools/jpackage/windows/WinLongPathTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.PackageTest; +import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.RunnablePackageTest.Action; +import jdk.jpackage.test.TKit; + +/* +/* @test + * @bug 8289771 + * @summary jpackage with long paths on windows + * @library /test/jdk/tools/jpackage/helpers + * @key jpackagePlatformPackage + * @build jdk.jpackage.test.* + * @requires (os.family == "windows") + * @compile WinLongPathTest.java + * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main + * --jpt-space-subst=* + * --jpt-exclude=WinLongPathTest(false,*--temp) + * --jpt-run=WinLongPathTest + */ + +public record WinLongPathTest(Boolean appImage, String optionName) { + + @Parameters + public static List<Object[]> input() { + List<Object[]> data = new ArrayList<>(); + for (var appImage : List.of(Boolean.TRUE, Boolean.FALSE)) { + for (var option : List.of("--dest", "--temp")) { + data.add(new Object[]{appImage, option}); + } + } + return data; + } + + @Test + public void test() throws IOException { + if (appImage) { + var cmd = JPackageCommand.helloAppImage(); + setOptionLongPath(cmd, optionName); + cmd.executeAndAssertHelloAppImageCreated(); + } else { + new PackageTest() + .forTypes(PackageType.WINDOWS) + .configureHelloApp() + .addInitializer(cmd -> setOptionLongPath(cmd, optionName)) + .run(Action.CREATE_AND_UNPACK); + } + } + + private static void setOptionLongPath(JPackageCommand cmd, String option) throws IOException { + var root = TKit.createTempDirectory("long-path"); + // 261 characters in total, which alone is above the 260 threshold + var longPath = root.resolve(Path.of("a".repeat(80), "b".repeat(90), "c".repeat(91))); + Files.createDirectories(longPath); + cmd.setArgumentValue(option, longPath); + } +} diff --git a/test/jdk/tools/jpackage/windows/WinLongVersionTest.java b/test/jdk/tools/jpackage/windows/WinLongVersionTest.java index 0d52da65630..7a915b5c123 100644 --- a/test/jdk/tools/jpackage/windows/WinLongVersionTest.java +++ b/test/jdk/tools/jpackage/windows/WinLongVersionTest.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Set; import java.util.UUID; import java.util.function.Supplier; import javax.xml.transform.Result; @@ -36,7 +35,7 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; -import jdk.jpackage.internal.IOUtils; +import jdk.jpackage.internal.util.XmlUtils; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.Executor; import jdk.jpackage.test.PackageTest; @@ -148,7 +147,7 @@ public static void test() throws IOException { Path scriptPath = resourceDir.resolve(String.format( "%s-post-msi.wsf", cmd.name())); - IOUtils.createXml(scriptPath, xml -> { + XmlUtils.createXml(scriptPath, xml -> { xml.writeStartElement("job"); xml.writeAttribute("id", "main"); xml.writeStartElement("script"); @@ -194,7 +193,7 @@ public static void testNoUpgradeTable() throws IOException { cmd.setFakeRuntime(); // Create package without Upgrade table - Document doc = IOUtils.initDocumentBuilder().parse( + Document doc = XmlUtils.initDocumentBuilder().parse( Files.newInputStream(TKit.SRC_ROOT.resolve( "windows/classes/jdk/jpackage/internal/resources/main.wxs"))); XPath xPath = XPathFactory.newInstance().newXPath(); diff --git a/test/jdk/tools/jpackage/windows/WinScriptTest.java b/test/jdk/tools/jpackage/windows/WinScriptTest.java index 296da482bb0..98b4922826d 100644 --- a/test/jdk/tools/jpackage/windows/WinScriptTest.java +++ b/test/jdk/tools/jpackage/windows/WinScriptTest.java @@ -24,8 +24,7 @@ import java.io.IOException; import java.nio.file.Path; import java.util.List; -import java.util.ArrayList; -import jdk.jpackage.internal.IOUtils; +import jdk.jpackage.internal.util.XmlUtils; import jdk.jpackage.test.TKit; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; @@ -147,7 +146,7 @@ void assertJPackageOutput(List<String> output) { } void createScript(JPackageCommand cmd) throws IOException { - IOUtils.createXml(Path.of(cmd.getArgumentValue("--resource-dir"), + XmlUtils.createXml(Path.of(cmd.getArgumentValue("--resource-dir"), String.format("%s-%s.wsf", cmd.name(), scriptSuffixName)), xml -> { xml.writeStartElement("job"); xml.writeAttribute("id", "main"); diff --git a/test/jdk/tools/sincechecker/modules/java.instrument/JavaInstrumentCheckSince.java b/test/jdk/tools/sincechecker/modules/java.instrument/JavaInstrumentCheckSince.java new file mode 100644 index 00000000000..1fe03b5bddd --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/java.instrument/JavaInstrumentCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in java.instrument module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker java.instrument + */ diff --git a/test/jdk/tools/sincechecker/modules/java.management.rmi/JavaManagementRmiCheckSince.java b/test/jdk/tools/sincechecker/modules/java.management.rmi/JavaManagementRmiCheckSince.java new file mode 100644 index 00000000000..8c6b18bb6c0 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/java.management.rmi/JavaManagementRmiCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in java.management.rmi module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker java.management.rmi + */ diff --git a/test/jdk/tools/sincechecker/modules/java.management/JavaManagementCheckSince.java b/test/jdk/tools/sincechecker/modules/java.management/JavaManagementCheckSince.java new file mode 100644 index 00000000000..65158639e2d --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/java.management/JavaManagementCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in java.management module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker java.management + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.attach/JdkAttachCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.attach/JdkAttachCheckSince.java new file mode 100644 index 00000000000..e4806c584b7 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.attach/JdkAttachCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.attach module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.attach + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.charsets/JdkCharsetsCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.charsets/JdkCharsetsCheckSince.java new file mode 100644 index 00000000000..b9b47998ace --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.charsets/JdkCharsetsCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343777 + * @summary Test for `@since` declaration in the module-info.java file of jdk.charsets + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.charsets + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.hotspot.agent/JdkHotspotAgentCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.hotspot.agent/JdkHotspotAgentCheckSince.java new file mode 100644 index 00000000000..974550cc7b7 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.hotspot.agent/JdkHotspotAgentCheckSince.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.hotspot.agent module + * @requires vm.hasSA + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.hotspot.agent + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jcmd/JdkJcmdCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jcmd/JdkJcmdCheckSince.java new file mode 100644 index 00000000000..03a872cf184 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jcmd/JdkJcmdCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.jcmd module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jcmd + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jconsole/JdkJconsoleCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jconsole/JdkJconsoleCheckSince.java new file mode 100644 index 00000000000..b73f9e67e4e --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jconsole/JdkJconsoleCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.jconsole module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jconsole + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jdi/JdkJdiCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jdi/JdkJdiCheckSince.java new file mode 100644 index 00000000000..67da45a26e2 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jdi/JdkJdiCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.jdi module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jdi + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jdwp.agent/JdkJdwpAgentCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jdwp.agent/JdkJdwpAgentCheckSince.java new file mode 100644 index 00000000000..b00ac2d30c6 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jdwp.agent/JdkJdwpAgentCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.jdwp.agent module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jdwp.agent + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jstatd/JdkJstatdCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jstatd/JdkJstatdCheckSince.java new file mode 100644 index 00000000000..b7fbfde37dd --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jstatd/JdkJstatdCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.jstatd module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jstatd + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.localedata/JdkLocaledataCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.localedata/JdkLocaledataCheckSince.java new file mode 100644 index 00000000000..209333b2541 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.localedata/JdkLocaledataCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343777 + * @summary Test for `@since` declaration in the module-info.java file of jdk.localedata + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.localedata + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.management.agent/JdkManagementAgentCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.management.agent/JdkManagementAgentCheckSince.java new file mode 100644 index 00000000000..a7046f66ac4 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.management.agent/JdkManagementAgentCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.management.agent module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.management.agent + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.management/JdkManagementCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.management/JdkManagementCheckSince.java new file mode 100644 index 00000000000..94523f59e75 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.management/JdkManagementCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8343781 + * @summary Test for `@since` in jdk.management module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.management + */ diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 775b95959c6..5544ad1bebd 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -122,6 +122,7 @@ public Map<String, String> call() { // vm.cds is true if the VM is compiled with cds support. map.put("vm.cds", this::vmCDS); map.put("vm.cds.custom.loaders", this::vmCDSForCustomLoaders); + map.put("vm.cds.supports.aot.class.linking", this::vmCDSSupportsAOTClassLinking); map.put("vm.cds.write.archived.java.heap", this::vmCDSCanWriteArchivedJavaHeap); map.put("vm.continuations", this::vmContinuations); // vm.graal.enabled is true if Graal is used as JIT @@ -457,6 +458,14 @@ protected String vmCDSCanWriteArchivedJavaHeap() { && isCDSRuntimeOptionsCompatible()); } + /** + * @return true if this VM can support the -XX:AOTClassLinking option + */ + protected String vmCDSSupportsAOTClassLinking() { + // Currently, the VM supports AOTClassLinking as long as it's able to write archived java heap. + return vmCDSCanWriteArchivedJavaHeap(); + } + /** * @return true if the VM options specified via the "test.cds.runtime.options" * property is compatible with writing Java heap objects into the CDS archive diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java index 369312d690a..79658e4c606 100644 --- a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java +++ b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java @@ -33,6 +33,7 @@ * @run main TestPreview */ +import java.nio.file.Path; import java.nio.file.Paths; import javadoc.tester.JavadocTester; @@ -209,4 +210,18 @@ public void test8282452() { checkOutput("java.base/preview/NoPreview.html", false, "refers to one or more preview"); } + + @Test + public void testRequiresTransitiveJavaBase() { + Path src = Paths.get(testSrc, "requiresTransitiveJavaBase"); + javadoc("-d", "out-requires-transitive-java-base", + "-XDforcePreview", "--enable-preview", "-source", System.getProperty("java.specification.version"), + "--module-source-path", src.toString(), + "--module", "m", + "--expand-requires", "transitive"); + checkExit(Exit.OK); + + checkOutput("m/module-summary.html", true, + "Indirect exports from the <code>java.base</code> module are"); + } } diff --git a/test/langtools/tools/javac/diags/examples/CantAccessInnerClsConstr.java b/test/langtools/jdk/javadoc/doclet/testPreview/requiresTransitiveJavaBase/m/module-info.java similarity index 74% rename from test/langtools/tools/javac/diags/examples/CantAccessInnerClsConstr.java rename to test/langtools/jdk/javadoc/doclet/testPreview/requiresTransitiveJavaBase/m/module-info.java index 112862cd2ef..d1576ff8c3e 100644 --- a/test/langtools/tools/javac/diags/examples/CantAccessInnerClsConstr.java +++ b/test/langtools/jdk/javadoc/doclet/testPreview/requiresTransitiveJavaBase/m/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -20,19 +20,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - -// key: compiler.misc.cant.access.inner.cls.constr -// key: compiler.err.invalid.mref - -class CantAccessInnerClsConstructor { - - interface SAM { - Outer m(); - } - - class Outer { } - - static void test() { - SAM s = Outer::new; - } +module m { + requires transitive java.base; } diff --git a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java index 2e2d0d0f84d..41bff3906d4 100644 --- a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java +++ b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -138,7 +138,7 @@ String toSimpleList(Collection<String> items) { } Path findDefaultFile() { - return findRootDir().resolve("src/jdk.javadoc/share/man/javadoc.1"); + return findRootDir().resolve("src/jdk.javadoc/share/man/javadoc.md"); } Path findRootDir() { @@ -264,29 +264,32 @@ List<String> parseMarkdown(String page) { var list = new ArrayList<String>(); // In the Markdown man page, options are defined in one of two forms: // 1. options delegated to javac appear in lines of the form - // - `-... + // * <span id="...">`-...</span> // 2. options implemented by the tool or doclet appear in lines of the form - // `-...` + // <span id="...">`-...</span> - Pattern p1 = Pattern.compile("\\R- `-.*"); - Pattern p2 = Pattern.compile("\\R`-.*"); + Pattern p1 = Pattern.compile("\\R* <span id=\"[^\"]+\">`-.*</span>"); + Pattern p2 = Pattern.compile("\\R<span id=\"[^\"]+\">`-.*</span>"); Pattern outer = Pattern.compile("(" + p1.pattern() + "|" + p2.pattern() + ")"); Matcher outerMatcher = outer.matcher(page); // In the defining areas, option names are represented as follows: - // `OPTION` - // where OPTION is the shortest string not containing whitespace or colon - Pattern inner = Pattern.compile("\\s`([^:`]+)"); + // `OPTION` or `OPTION` + // where OPTION is the shortest string not containing whitespace or colon, + // and in which all '-' characters are escaped with a single backslash. + Pattern inner = Pattern.compile("[>\\s]`(-[^ :]+?)(:|`)"); while (outerMatcher.find()) { String lines = outerMatcher.group(); - out.println("found:" + lines + "\n"); + out.println("found:" + lines); Matcher innerMatcher = inner.matcher(lines); while (innerMatcher.find()) { String option = innerMatcher.group(1); + out.println(" found option:" + option); list.add(option); } + out.println(); } return list; diff --git a/test/langtools/jdk/jshell/ConsoleTest.java b/test/langtools/jdk/jshell/ConsoleTest.java index 29961a180ba..4aedc061939 100644 --- a/test/langtools/jdk/jshell/ConsoleTest.java +++ b/test/langtools/jdk/jshell/ConsoleTest.java @@ -25,6 +25,7 @@ * @test * @bug 8298425 * @summary Verify behavior of System.console() + * @enablePreview * @build KullaTesting TestingInputStream * @run testng ConsoleTest */ @@ -67,6 +68,13 @@ public String readLine(String prompt) throws IOError { } }; assertEval("System.console().readLine(\"expected\")", "\"AB\""); + console = new ThrowingJShellConsole() { + @Override + public String readLine() throws IOError { + return "AB"; + } + }; + assertEval("System.console().readLine()", "\"AB\""); console = new ThrowingJShellConsole() { @Override public char[] readPassword(String prompt) throws IOError { @@ -210,6 +218,10 @@ public String readLine(String prompt) throws IOError { return console.readLine(prompt); } @Override + public String readLine() throws IOError { + return console.readLine(); + } + @Override public char[] readPassword(String prompt) throws IOError { return console.readPassword(prompt); } @@ -240,6 +252,10 @@ public String readLine(String prompt) throws IOError { throw new IllegalStateException("Not expected!"); } @Override + public String readLine() throws IOError { + throw new IllegalStateException("Not expected!"); + } + @Override public char[] readPassword(String prompt) throws IOError { throw new IllegalStateException("Not expected!"); } diff --git a/test/langtools/jdk/jshell/ConsoleToolTest.java b/test/langtools/jdk/jshell/ConsoleToolTest.java index 8fa85a3ec27..0af85a61862 100644 --- a/test/langtools/jdk/jshell/ConsoleToolTest.java +++ b/test/langtools/jdk/jshell/ConsoleToolTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8331535 + * @bug 8331535 8341631 * @summary Test the JShell tool Console handling * @modules jdk.internal.le/jdk.internal.org.jline.reader * jdk.jshell/jdk.internal.jshell.tool:+open @@ -56,6 +56,40 @@ public void testOutput() { ); } + @Test //JDK-8341631 + public void testIO() { + test(new String[] {"--enable-preview"}, + a -> {assertCommandWithOutputAndTerminal(a, + "java.io.IO.readln(\"%%s\");\ninput", //newline automatically appended + "$1 ==> \"input\"", + """ + \u0005java.io.IO.readln(\"%%s\"); + %%sinput + """);}, + a -> {assertCommandWithOutputAndTerminal(a, + "java.io.IO.readln();\ninput!", //newline automatically appended + "$2 ==> \"input!\"", + """ + \u0005java.io.IO.readln(); + input! + """);}, + a -> {assertCommandWithOutputAndTerminal(a, + "java.io.IO.println(\"Hello, World!\");", + "", + """ + \u0005java.io.IO.println(\"Hello, World!\"); + Hello, World! + """);}, + a -> {assertCommandWithOutputAndTerminal(a, + "java.io.IO.println();", + "", + """ + \u0005java.io.IO.println(); + + """);} + ); + } + void assertCommandWithOutputAndTerminal(boolean a, String command, String out, String terminalOut) { assertCommand(a, command, out, null, null, null, null, terminalOut); } diff --git a/test/langtools/jdk/jshell/StartOptionTest.java b/test/langtools/jdk/jshell/StartOptionTest.java index 60926e69843..b84b454480e 100644 --- a/test/langtools/jdk/jshell/StartOptionTest.java +++ b/test/langtools/jdk/jshell/StartOptionTest.java @@ -22,7 +22,7 @@ */ /* - * @test 8151754 8080883 8160089 8170162 8166581 8172102 8171343 8178023 8186708 8179856 8185840 8190383 + * @test 8151754 8080883 8160089 8170162 8166581 8172102 8171343 8178023 8186708 8179856 8185840 8190383 8341631 * @summary Testing startExCe-up options. * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -366,14 +366,49 @@ public void testShowVersion() { } public void testPreviewEnabled() { - String fn = writeToFile("System.out.println(\"prefix\");\n" + - "System.out.println(MethodHandle.class.getName());\n" + - "System.out.println(\"suffix\");\n" + - "/exit\n"); + String fn = writeToFile( + """ + System.out.println(\"prefix\"); + System.out.println(MethodHandle.class.getName()); + System.out.println(\"suffix\"); + /exit + """); startCheckUserOutput(s -> assertEquals(s, "prefix\nsuffix\n"), fn); startCheckUserOutput(s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"), "--enable-preview", fn); + //JDK-8341631: + String fn2 = writeToFile( + """ + System.out.println(\"prefix\"); + IO.println(\"test\"); + System.out.println(\"suffix\"); + /exit + """); + startCheckUserOutput(s -> assertEquals(s, "prefix\nsuffix\n"), + fn2); + startCheckUserOutput(s -> assertEquals(s, "prefix\ntest\nsuffix\n"), + "--enable-preview", fn2); + } + public void testInput() { + //readLine(String): + String readLinePrompt = writeToFile( + """ + var v = System.console().readLine("prompt: "); + System.out.println(v); + /exit + """); + startCheckUserOutput(s -> assertEquals(s, "prompt: null\n"), + readLinePrompt); + //readPassword(String): + String readPasswordPrompt = writeToFile( + """ + var v = System.console().readPassword("prompt: "); + System.out.println(java.util.Arrays.toString(v)); + /exit + """); + startCheckUserOutput(s -> assertEquals(s, "prompt: null\n"), + readPasswordPrompt); } @AfterMethod diff --git a/test/langtools/tools/javac/6402516/TestClass.java b/test/langtools/tools/javac/6402516/TestClass.java index f080fbc22b4..57131cddaf9 100644 --- a/test/langtools/tools/javac/6402516/TestClass.java +++ b/test/langtools/tools/javac/6402516/TestClass.java @@ -26,32 +26,32 @@ class Test { void m1(int m1_arg) { - String x = "Test; 0; 0"; - String y = "Test; 0; 0"; - String z = "Test; 0; 0"; + String x = "Test; 0; 0; 0"; + String y = "Test; 0; 0; 0"; + String z = "Test; 0; 0; 0"; Object o = new Object() { public boolean equals(Object other) { - String p = "-; Test; 0; 0"; - String q = "-; Test; 0; 0"; - String r = "-; Test; 0; 0"; + String p = "-; Test; 0; 0; 0"; + String q = "-; Test; 0; 0; 0"; + String r = "-; Test; 0; 0; 0"; return (this == other); } }; } - String s = "Test; 0; 0"; + String s = "Test; 0; 0; 0"; boolean b = new Object() { public boolean equals(Object other) { - String p = "-; Test; 0; 0"; - String q = "-; Test; 0; 0"; - String r = "-; Test; 0; 0"; + String p = "-; Test; 0; 0; 0"; + String q = "-; Test; 0; 0; 0"; + String r = "-; Test; 0; 0; 0"; return (this == other); } }.equals(null); class Test2 { - String s = "Test.Test2; Test; 0; 0"; + String s = "Test.Test2; Test; 0; 0; 0"; } } diff --git a/test/langtools/tools/javac/6402516/TestLocalElements.java b/test/langtools/tools/javac/6402516/TestLocalElements.java index 589d2e993cb..7b835bfdcc3 100644 --- a/test/langtools/tools/javac/6402516/TestLocalElements.java +++ b/test/langtools/tools/javac/6402516/TestLocalElements.java @@ -23,29 +23,29 @@ import java.util.List; import java.io.*; -//TOPLEVEL_SCOPE:List, Test2, Test; java.io.*, java.lang.* +//TOPLEVEL_SCOPE:List, Test2, Test; java.io.*, java.lang.*; class Test { void m1(int m1_arg) { - String x = "x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*"; - String y = "y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*"; - String z = "z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*"; + String x = "x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;"; + String y = "y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;"; + String z = "z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;"; Object o = new Object() { public boolean equals(Object other) { - String p = "p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*"; - String q = "q, p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*"; - String r = "r, q, p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*"; + String p = "p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;"; + String q = "q, p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;"; + String r = "r, q, p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;"; return (this == other); } }; } - String s = "super, this; List, Test2, Test; java.io.*, java.lang.*"; + String s = "super, this; List, Test2, Test; java.io.*, java.lang.*;"; boolean b = new Object() { public boolean equals(Object other) { - String p = "p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*"; - String q = "q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*"; - String r = "r, q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*"; + String p = "p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*;"; + String q = "q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*;"; + String r = "r, q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*;"; return (this == other); } diff --git a/test/langtools/tools/javac/6402516/TestMethod.java b/test/langtools/tools/javac/6402516/TestMethod.java index 9aec1d5d881..304b0abd9cb 100644 --- a/test/langtools/tools/javac/6402516/TestMethod.java +++ b/test/langtools/tools/javac/6402516/TestMethod.java @@ -25,32 +25,32 @@ class Test { void m1(int m1_arg) { - String x = "m1; 0; 0"; - String y = "m1; 0; 0"; - String z = "m1; 0; 0"; + String x = "m1; 0; 0; 0"; + String y = "m1; 0; 0; 0"; + String z = "m1; 0; 0; 0"; Object o = new Object() { public boolean equals(Object other) { - String p = "equals; m1; 0; 0"; - String q = "equals; m1; 0; 0"; - String r = "equals; m1; 0; 0"; + String p = "equals; m1; 0; 0; 0"; + String q = "equals; m1; 0; 0; 0"; + String r = "equals; m1; 0; 0; 0"; return (this == other); } }; } - String s = "0; 0; 0"; + String s = "0; 0; 0; 0"; boolean b = new Object() { public boolean equals(Object other) { - String p = "equals; 0; 0; 0"; - String q = "equals; 0; 0; 0"; - String r = "equals; 0; 0; 0"; + String p = "equals; 0; 0; 0; 0"; + String q = "equals; 0; 0; 0; 0"; + String r = "equals; 0; 0; 0; 0"; return (this == other); } }.equals(null); class Test2 { - String s = "0; 0; 0; 0"; + String s = "0; 0; 0; 0; 0"; } } diff --git a/test/langtools/tools/javac/ImportModule.java b/test/langtools/tools/javac/ImportModule.java index dc1ed9bd0c1..1224a9d7470 100644 --- a/test/langtools/tools/javac/ImportModule.java +++ b/test/langtools/tools/javac/ImportModule.java @@ -218,28 +218,14 @@ public class Test { List<String> actualErrors; List<String> expectedErrors; - actualErrors = - new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION, - "-XDrawDiagnostics") - .outdir(classes) - .files(tb.findJavaFiles(src)) - .run(Task.Expect.FAIL) - .writeAll() - .getOutputLines(Task.OutputKind.DIRECT); - - expectedErrors = List.of( - "Test.java:5:5: compiler.err.ref.ambiguous: Logger, kindname.interface, java.lang.System.Logger, java.lang.System, kindname.class, java.util.logging.Logger, java.util.logging", - "- compiler.note.preview.filename: Test.java, DEFAULT", - "- compiler.note.preview.recompile", - "1 error" - ); - - if (!Objects.equals(expectedErrors, actualErrors)) { - throw new AssertionError("Incorrect Output, expected: " + expectedErrors + - ", actual: " + out); - - } + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION, + "-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); tb.writeJavaFiles(src, """ @@ -793,7 +779,7 @@ public class C {} if (!Objects.equals(expectedErrors, actualErrors)) { throw new AssertionError("Incorrect Output, expected: " + expectedErrors + - ", actual: " + out); + ", actual: " + actualErrors); } } @@ -843,4 +829,94 @@ public class Test { } } + public void testPackageImportDisambiguates(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + Path ma = src.resolve("ma"); + tb.writeJavaFiles(ma, + """ + module ma { + exports ma.p1; + } + """, + """ + package ma.p1; + public class A {} + """); + Path mb = src.resolve("mb"); + tb.writeJavaFiles(mb, + """ + module mb { + exports mb.p1; + } + """, + """ + package mb.p1; + public class A {} + """); + Path test = src.resolve("test"); + tb.writeJavaFiles(test, + """ + module test { + requires ma; + requires mb; + } + """, + """ + package test; + import module ma; + import module mb; + public class Test { + A a; + } + """); + + Files.createDirectories(classes); + + List<String> actualErrors = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--enable-preview", "--release", SOURCE_VERSION, + "--module-source-path", src.toString()) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List<String> expectedErrors = List.of( + "Test.java:5:5: compiler.err.ref.ambiguous: A, kindname.class, mb.p1.A, mb.p1, kindname.class, ma.p1.A, ma.p1", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + actualErrors); + + } + + tb.writeJavaFiles(test, + """ + package test; + import module ma; + import module mb; + import mb.p1.*; + public class Test { + A a; + } + """); + + Files.createDirectories(classes); + + new JavacTask(tb) + .options("-XDrawDiagnostics", + "--enable-preview", "--release", SOURCE_VERSION, + "--module-source-path", src.toString()) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + } } diff --git a/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.java b/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.java new file mode 100644 index 00000000000..39b419c694a --- /dev/null +++ b/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.java @@ -0,0 +1,44 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8322882 + * @summary Disallow attempts to access a free variable proxy field from a static method + * @compile/fail/ref=LocalFreeVarStaticInstantiate.out -XDrawDiagnostics LocalFreeVarStaticInstantiate.java + */ + +class LocalFreeVarStaticInstantiate { + + // local class in method + static void foo(Object there) { + class Local { + { + there.hashCode(); + } + + static { + new Local(); // can't get there from here + } + + static Runnable r = () -> { + new Local(); // can't get there from here + }; + } + } + + // local class in lambda + static Runnable foo = () -> { + Object there = ""; + class Local { + { + there.hashCode(); + } + + static { + new Local(); // can't get there from here + } + + static Runnable r = () -> { + new Local(); // can't get there from here + }; + } + }; +} diff --git a/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.out b/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.out new file mode 100644 index 00000000000..50e913083b0 --- /dev/null +++ b/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.out @@ -0,0 +1,5 @@ +LocalFreeVarStaticInstantiate.java:18:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticInstantiate.java:22:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticInstantiate.java:36:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticInstantiate.java:40:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +4 errors diff --git a/test/langtools/tools/javac/QualifiedAccess/QualifiedAccess_2.java b/test/langtools/tools/javac/QualifiedAccess/QualifiedAccess_2.java index de36f070766..d16c8194a53 100644 --- a/test/langtools/tools/javac/QualifiedAccess/QualifiedAccess_2.java +++ b/test/langtools/tools/javac/QualifiedAccess/QualifiedAccess_2.java @@ -7,7 +7,7 @@ * * @compile pack1/P1.java * @compile pack1/P2.java - * @compile/fail/ref=QualifiedAccess_2.out -XDrawDiagnostics QualifiedAccess_2.java + * @compile/fail/ref=QualifiedAccess_2.out -XDdev -XDrawDiagnostics QualifiedAccess_2.java */ import pack1.P1; diff --git a/test/langtools/tools/javac/SuperInit/EarlyIndirectOuterCapture.java b/test/langtools/tools/javac/SuperInit/EarlyIndirectOuterCapture.java new file mode 100644 index 00000000000..9336c4dc183 --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyIndirectOuterCapture.java @@ -0,0 +1,29 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8334248 + * @summary Invalid error for early construction local class constructor method reference + * @compile/fail/ref=EarlyIndirectOuterCapture.out -XDrawDiagnostics EarlyIndirectOuterCapture.java + */ + +public class EarlyIndirectOuterCapture { + + EarlyIndirectOuterCapture() { + this(null); + } + + EarlyIndirectOuterCapture(InnerSuperclass inner) { } + + class InnerSuperclass { } + + static class InnerOuter extends EarlyIndirectOuterCapture { // accessible + class InnerInnerOuter extends EarlyIndirectOuterCapture { // not accessible + InnerInnerOuter() { + super(/* which enclosing instance here ? */new InnerSuperclass() { }); + } + + InnerInnerOuter(boolean b) { + super(InnerOuter.this.new InnerSuperclass() { }); // ok, explicit + } + } + } +} diff --git a/test/langtools/tools/javac/SuperInit/EarlyIndirectOuterCapture.out b/test/langtools/tools/javac/SuperInit/EarlyIndirectOuterCapture.out new file mode 100644 index 00000000000..7b96671a2bd --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyIndirectOuterCapture.out @@ -0,0 +1,2 @@ +EarlyIndirectOuterCapture.java:21:60: compiler.err.cant.ref.before.ctor.called: this +1 error diff --git a/test/langtools/tools/javac/SuperInit/EarlyLocalCtorRef.java b/test/langtools/tools/javac/SuperInit/EarlyLocalCtorRef.java new file mode 100644 index 00000000000..3346d6ff4f7 --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyLocalCtorRef.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, 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 8334248 + * @summary Allow early construction local class constructor method references + * @enablePreview + */ + +import java.util.function.Supplier; + +public class EarlyLocalCtorRef { + + public EarlyLocalCtorRef() { + class InnerLocal { } + this(InnerLocal::new); + } + + public EarlyLocalCtorRef(Supplier<Object> s) { + } + + public static void main(String[] args) { + new EarlyLocalCtorRef(); + } +} diff --git a/test/langtools/tools/javac/SuperInit/EarlyLocalTest2.java b/test/langtools/tools/javac/SuperInit/EarlyLocalTest2.java new file mode 100644 index 00000000000..ba90f06dc5e --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyLocalTest2.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, 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 8333313 + * @summary Verify references to local classes declared in early construction contexts + * @enablePreview + */ +public class EarlyLocalTest2 { + + class Test { + Test() { + class InnerLocal { } + Runnable r = () -> new InnerLocal() { }; + r.run(); + super(); + } + } + + public static void main(String[] args) { + new EarlyLocalTest2().new Test(); + } +} diff --git a/test/langtools/tools/javac/SuperInit/EarlyLocalTest3.java b/test/langtools/tools/javac/SuperInit/EarlyLocalTest3.java new file mode 100644 index 00000000000..bf8d6faa099 --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyLocalTest3.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, 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 8333313 + * @summary Verify references to local classes declared in early construction contexts + * @enablePreview + */ +public class EarlyLocalTest3 { + + class Test { + Test() { + class InnerLocal { } + Runnable r = InnerLocal::new; + r.run(); + super(); + } + } + + public static void main(String[] args) { + new EarlyLocalTest3().new Test(); + } +} diff --git a/test/langtools/tools/javac/SuperInit/EarlyLocalTest8.java b/test/langtools/tools/javac/SuperInit/EarlyLocalTest8.java new file mode 100644 index 00000000000..806903e9017 --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyLocalTest8.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024, 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 8333313 + * @summary Verify references to local classes declared in early construction contexts + * @enablePreview + */ +import java.util.concurrent.atomic.AtomicReference; + +public class EarlyLocalTest8 { + + class Test extends AtomicReference<Runnable> { + Test(int x) { + super( + switch (x) { + case 0 -> null; + default -> { + class InnerLocal { } + yield () -> new InnerLocal() { { System.out.println(EarlyLocalTest8.this); } }; + } + }); + } + } + + public static void main(String[] args) { + new EarlyLocalTest8().new Test(42); + } +} diff --git a/test/langtools/tools/javac/api/TestGetScopeResult.java b/test/langtools/tools/javac/api/TestGetScopeResult.java index 8b53ba0a752..daa3e761b2a 100644 --- a/test/langtools/tools/javac/api/TestGetScopeResult.java +++ b/test/langtools/tools/javac/api/TestGetScopeResult.java @@ -73,6 +73,9 @@ import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Context.Factory; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; +import javax.tools.JavaFileObject; import static javax.tools.JavaFileObject.Kind.SOURCE; @@ -89,6 +92,7 @@ public static void main(String... args) throws IOException { new TestGetScopeResult().testLocalRecordAnnotation(); new TestGetScopeResult().testRuleCases(); new TestGetScopeResult().testNestedSwitchExpression(); + new TestGetScopeResult().testModuleImportScope(); } public void run() throws IOException { @@ -823,6 +827,64 @@ JCTree getCaseBody(Scope scope) { } } + void testModuleImportScope() throws IOException { + JavacTool c = JavacTool.create(); + try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) { + String code = """ + import module java.compiler; + import java.util.*; + import java.lang.System; + class Test { + } + """; + Context ctx = new Context(); + TestAnalyzer.preRegister(ctx); + JavaFileObject input = + SimpleJavaFileObject.forSource(URI.create("myfo:///Test.java"), code); + JavacTask t = (JavacTask) c.getTask(null, fm, null, null, null, + List.of(input), + ctx); + CompilationUnitTree cut = t.parse().iterator().next(); + t.analyze(); + + TreePath topLevelClass = new TreePath(new TreePath(cut), cut.getTypeDecls().get(0)); + Scope scope = Trees.instance(t).getScope(topLevelClass); + + if (scope.getEnclosingClass() == null) { + throw new AssertionError("Expected an enclosing class."); + } + + scope = scope.getEnclosingScope(); + + if (scope.getEnclosingClass() != null) { + throw new AssertionError("Did not expect an enclosing class."); + } + + asssertScopeContainsTypeWithFQN(scope, "java.lang.System"); + asssertScopeContainsTypeWithFQN(scope, "Test"); + + scope = scope.getEnclosingScope(); + + if (scope.getEnclosingClass() != null) { + throw new AssertionError("Did not expect an enclosing class."); + } + + asssertScopeContainsTypeWithFQN(scope, "java.util.List"); + + scope = scope.getEnclosingScope(); + + if (scope.getEnclosingClass() != null) { + throw new AssertionError("Did not expect an enclosing class."); + } + + asssertScopeContainsTypeWithFQN(scope, "javax.tools.ToolProvider"); + + if (scope.getEnclosingScope() != null) { + throw new AssertionError("Did not expect an enclosing scope."); + } + } + } + private List<String> dumpScope(Scope scope) { List<String> content = new ArrayList<>(); while (scope.getEnclosingClass() != null) { @@ -833,4 +895,17 @@ private List<String> dumpScope(Scope scope) { } return content; } + + private void asssertScopeContainsTypeWithFQN(Scope scope, String fqn) { + for (TypeElement type : ElementFilter.typesIn(scope.getLocalElements())) { + if (type.getQualifiedName().contentEquals(fqn)) { + return ; + } + } + + throw new AssertionError("Expected to find: " + fqn + + " in: " + scope.getLocalElements() + + ", but it is missing."); + } + } diff --git a/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultTest.java b/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultTest.java index d9a3320ecc2..2911e58820f 100644 --- a/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultTest.java +++ b/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultTest.java @@ -88,7 +88,7 @@ private void test(String template, Map<String, String> replacements, boolean has checkEquals(countNumberOfAttributes(method.attributes()), 1L, "Number of AnnotationDefault attribute"); - checkEquals(attr.attributeName(), + checkEquals(attr.attributeName().stringValue(), "AnnotationDefault", "attribute_name_index"); ExpectedValues expectedValue = expectedValues.get(methodName); diff --git a/test/langtools/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java b/test/langtools/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java index f15771840f5..924916f5cbd 100644 --- a/test/langtools/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java +++ b/test/langtools/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java @@ -169,7 +169,7 @@ private void testEnclosingMethodAttribute() { // stop checking, attr is null. test case failed return; } - checkEquals(attr.attributeName(), + checkEquals(attr.attributeName().stringValue(), "EnclosingMethod", "attribute_name_index of EnclosingMethod attribute in the class : " + className); checkEquals(((BoundAttribute<?>)attr).payloadLen(), 4, diff --git a/test/langtools/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java b/test/langtools/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java index be4a5aaea91..531d5e617d0 100644 --- a/test/langtools/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java +++ b/test/langtools/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java @@ -138,7 +138,7 @@ private void verifyCoveredLines(Set<Integer> actualCoveredLines, TestCase.Method private <T extends Attribute<T>> int countAttributes(AttributeMapper<T> attr, AttributedElement attributedElement) { int i = 0; for (Attribute<?> attribute : attributedElement.attributes()) { - if (attribute.attributeName().equals(attr.name())) { + if (attribute.attributeName().equalsString(attr.name())) { i++; } } diff --git a/test/langtools/tools/javac/classfiles/attributes/Signature/Driver.java b/test/langtools/tools/javac/classfiles/attributes/Signature/Driver.java index 72f7d2a6b9b..7b75ffa5f9c 100644 --- a/test/langtools/tools/javac/classfiles/attributes/Signature/Driver.java +++ b/test/langtools/tools/javac/classfiles/attributes/Signature/Driver.java @@ -219,7 +219,7 @@ private void testAttribute( SignatureAttribute attribute = sup.get(); if (expectedSignature != null && checkNotNull(attribute, memberName + " must have attribute")) { - checkEquals(attribute.attributeName(), + checkEquals(attribute.attributeName().stringValue(), "Signature", "Attribute's name : " + memberName); checkEquals(((BoundAttribute<?>)attribute).payloadLen(), 2, "Attribute's length : " + memberName); checkEquals(attribute.signature().stringValue(), diff --git a/test/langtools/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java b/test/langtools/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java index 52d53f9dce4..0d81fc2c282 100644 --- a/test/langtools/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java +++ b/test/langtools/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java @@ -108,7 +108,7 @@ private void assertAttributePresent(ClassModel classFile, String fileName) throw SourceFileAttribute attribute = sourceFileAttributes.get(0); - assertEquals(attribute.attributeName(), Attributes.sourceFile().name(), "Incorrect attribute name"); + assertEquals(attribute.attributeName().stringValue(), Attributes.sourceFile().name(), "Incorrect attribute name"); assertEquals(attribute.sourceFile().stringValue(), fileName, "Incorrect source file name"); assertEquals(((BoundAttribute<?>)attribute).payloadLen(), 2, "Incorrect attribute length"); diff --git a/test/langtools/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java b/test/langtools/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java index 425760ea137..6467f3d8027 100644 --- a/test/langtools/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java +++ b/test/langtools/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java @@ -302,7 +302,7 @@ private void testDeprecatedAttribute(String name, DeprecatedAttribute attr, Clas if (checkNotNull(attr, name + " must have deprecated attribute")) { checkEquals(0, ((BoundAttribute<?>)attr).payloadLen(), "attribute_length should equal to 0"); - checkEquals("Deprecated", attr.attributeName(), + checkEquals("Deprecated", attr.attributeName().stringValue(), name + " attribute_name_index"); } } diff --git a/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java b/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java index 26972de3544..aa46d8a9b9d 100644 --- a/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java +++ b/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java @@ -206,7 +206,7 @@ private void test(String classToTest, TestCase test, String...skipClasses) { if (!checkNotNull(innerClasses, "InnerClasses attribute should not be null")) { return; } - checkEquals(innerClasses.attributeName(), "InnerClasses", + checkEquals(innerClasses.attributeName().stringValue(), "InnerClasses", "innerClasses.attribute_name_index"); // Inner Classes attribute consists of length (2 bytes) // and 8 bytes for each inner class's entry. diff --git a/test/langtools/tools/javac/danglingDocComments/JBangException1.java b/test/langtools/tools/javac/danglingDocComments/JBangException1.java new file mode 100644 index 00000000000..123451aff7c --- /dev/null +++ b/test/langtools/tools/javac/danglingDocComments/JBangException1.java @@ -0,0 +1,19 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +// /nodynamiccopyright/ + +/** A class comment */ +public class JBangException1 { + + /** + * A method comment + * + * @param args a parameter comment + */ + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("Hello World!"); + } else { + System.out.println("Hello " + args[0]); + } + } +} \ No newline at end of file diff --git a/test/langtools/tools/javac/danglingDocComments/JBangException2.enabled.out b/test/langtools/tools/javac/danglingDocComments/JBangException2.enabled.out new file mode 100644 index 00000000000..8934c449e3b --- /dev/null +++ b/test/langtools/tools/javac/danglingDocComments/JBangException2.enabled.out @@ -0,0 +1,2 @@ +JBangException2.java:1:1: compiler.warn.dangling.doc.comment +1 warning diff --git a/test/langtools/tools/javac/danglingDocComments/JBangException2.java b/test/langtools/tools/javac/danglingDocComments/JBangException2.java new file mode 100644 index 00000000000..1514542f3fc --- /dev/null +++ b/test/langtools/tools/javac/danglingDocComments/JBangException2.java @@ -0,0 +1,19 @@ +/** /usr/bin/env jbang "$0" "$@" ; exit $? */ +// /nodynamiccopyright/ + +/** A class comment */ +public class JBangException2 { + + /** + * A method comment + * + * @param args a parameter comment + */ + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("Hello World!"); + } else { + System.out.println("Hello " + args[0]); + } + } +} \ No newline at end of file diff --git a/test/langtools/tools/javac/danglingDocComments/JBangException3.enabled.out b/test/langtools/tools/javac/danglingDocComments/JBangException3.enabled.out new file mode 100644 index 00000000000..9b08300a7c0 --- /dev/null +++ b/test/langtools/tools/javac/danglingDocComments/JBangException3.enabled.out @@ -0,0 +1,2 @@ +JBangException3.java:1:1: compiler.warn.dangling.doc.comment +1 warning diff --git a/test/langtools/tools/javac/danglingDocComments/JBangException3.java b/test/langtools/tools/javac/danglingDocComments/JBangException3.java new file mode 100644 index 00000000000..9e14dfc0b55 --- /dev/null +++ b/test/langtools/tools/javac/danglingDocComments/JBangException3.java @@ -0,0 +1,22 @@ +/// A +/// multiline +/// dangling +/// comment +// /nodynamiccopyright/ + +/** A class comment */ +public class JBangException3 { + + /** + * A method comment + * + * @param args a parameter comment + */ + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("Hello World!"); + } else { + System.out.println("Hello " + args[0]); + } + } +} \ No newline at end of file diff --git a/test/langtools/tools/javac/danglingDocComments/JBangExceptionTest.java b/test/langtools/tools/javac/danglingDocComments/JBangExceptionTest.java new file mode 100644 index 00000000000..4308335f4c5 --- /dev/null +++ b/test/langtools/tools/javac/danglingDocComments/JBangExceptionTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, 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 + * + * @compile/ref=empty.out -XDrawDiagnostics JBangException1.java + * @compile/ref=empty.out -XDrawDiagnostics -Xlint:dangling-doc-comments JBangException1.java + * + * @compile/ref=empty.out -XDrawDiagnostics JBangException2.java + * @compile/ref=JBangException2.enabled.out -XDrawDiagnostics -Xlint:dangling-doc-comments JBangException2.java + * + * @compile/ref=empty.out -XDrawDiagnostics JBangException3.java + * @compile/ref=JBangException3.enabled.out -XDrawDiagnostics -Xlint:dangling-doc-comments JBangException3.java + */ + +// The classes being tested reside in files separate from this one because +// the classes need to provide the initial dangling comment, which would +// otherwise interfere with the JTReg test comment. For similar reasons, +// the files with test classes do __NOT__ have a copyright header. diff --git a/test/langtools/tools/javac/diags/examples/LocalClassCantBeInstStatic.java b/test/langtools/tools/javac/diags/examples/LocalClassCantBeInstStatic.java new file mode 100644 index 00000000000..80301cbbb77 --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/LocalClassCantBeInstStatic.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024, 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. + */ + +// key: compiler.err.local.cant.be.inst.static + +class LocalClassCantBeInstStatic { + static void foo(Object there) { + class Local { + { + there.hashCode(); + } + + static { + new Local(); // can't get there from here + } + } + } +} diff --git a/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java b/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java index 44bcfae8d44..f2e5899a915 100644 --- a/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java +++ b/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.modifier.not.allowed.here +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.java.base.transitive module m { requires transitive java.base; diff --git a/test/langtools/tools/javac/lambda/MethodReference23.out b/test/langtools/tools/javac/lambda/MethodReference23.out index 456a002bd99..6f7e1c5c909 100644 --- a/test/langtools/tools/javac/lambda/MethodReference23.out +++ b/test/langtools/tools/javac/lambda/MethodReference23.out @@ -1,6 +1,6 @@ -MethodReference23.java:52:19: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23) -MethodReference23.java:53:16: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23) -MethodReference23.java:57:19: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23) -MethodReference23.java:58:16: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23) +MethodReference23.java:52:19: compiler.err.non-static.cant.be.ref: kindname.variable, this +MethodReference23.java:53:16: compiler.err.non-static.cant.be.ref: kindname.variable, this +MethodReference23.java:57:19: compiler.err.non-static.cant.be.ref: kindname.variable, this +MethodReference23.java:58:16: compiler.err.non-static.cant.be.ref: kindname.variable, this MethodReference23.java:72:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference23.SAM21), MethodReference23, kindname.method, call3(MethodReference23.SAM22), MethodReference23 5 errors diff --git a/test/langtools/tools/javac/lambda/MethodReference37.out b/test/langtools/tools/javac/lambda/MethodReference37.out index 8db8e456daf..09dc966bd4a 100644 --- a/test/langtools/tools/javac/lambda/MethodReference37.out +++ b/test/langtools/tools/javac/lambda/MethodReference37.out @@ -1,5 +1,5 @@ MethodReference37.java:24:38: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Inner, compiler.misc.no.args, MethodReference37.Outer, kindname.class, MethodReference37.Outer.Inner, (compiler.misc.arg.length.mismatch))) MethodReference37.java:29:39: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Inner, compiler.misc.no.args, MethodReference37.Outer, kindname.class, MethodReference37.Outer.Inner, (compiler.misc.arg.length.mismatch))) -MethodReference37.java:34:40: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner, MethodReference37.Outer, MethodReference37.Outer) -MethodReference37.java:38:41: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner, MethodReference37.Outer, MethodReference37.Outer) +MethodReference37.java:34:40: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Inner, compiler.misc.no.args, MethodReference37.Outer, kindname.class, MethodReference37.Outer.Inner, (compiler.misc.arg.length.mismatch))) +MethodReference37.java:38:41: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Inner, compiler.misc.no.args, MethodReference37.Outer, kindname.class, MethodReference37.Outer.Inner, (compiler.misc.arg.length.mismatch))) 4 errors diff --git a/test/langtools/tools/javac/lambda/MethodReferenceNoThisTest.out b/test/langtools/tools/javac/lambda/MethodReferenceNoThisTest.out index 2dff751f68d..a411c340484 100644 --- a/test/langtools/tools/javac/lambda/MethodReferenceNoThisTest.out +++ b/test/langtools/tools/javac/lambda/MethodReferenceNoThisTest.out @@ -1,2 +1,2 @@ MethodReferenceNoThisTest.java:22:15: compiler.err.cant.ref.before.ctor.called: this -1 error \ No newline at end of file +1 error diff --git a/test/langtools/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.out b/test/langtools/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.out index 03b3d338369..66c50ed315b 100644 --- a/test/langtools/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.out +++ b/test/langtools/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.out @@ -1,2 +1,2 @@ -MethodRefToInnerWithoutOuter.java:22:31: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: TestString, java.lang.String, MethodRefToInnerBase) +MethodRefToInnerWithoutOuter.java:22:31: compiler.err.non-static.cant.be.ref: kindname.variable, this 1 error diff --git a/test/langtools/tools/javac/modules/ConvenientAccessErrorsTest.java b/test/langtools/tools/javac/modules/ConvenientAccessErrorsTest.java index 24c2b045800..f558ddb20ac 100644 --- a/test/langtools/tools/javac/modules/ConvenientAccessErrorsTest.java +++ b/test/langtools/tools/javac/modules/ConvenientAccessErrorsTest.java @@ -432,6 +432,40 @@ public void testInImportOnDemand(Path base) throws Exception { throw new Exception("expected output not found; actual: " + log); } + @Test + public void testInModuleImport(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1x"); + tb.writeJavaFiles(src_m1, + "module m1x { }", + "package api; public class Api { public String test() { return null; } }"); + Path src_m2 = src.resolve("m2x"); + tb.writeJavaFiles(src_m2, + "module m2x { requires m1x; }", + "package test; import module m1x; public class Test { Api api; { api.test().length(); } }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + List<String> log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--enable-preview", "--source", System.getProperty("java.specification.version"), + "--module-source-path", src.toString()) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List<String> expected = Arrays.asList( + "Test.java:1:54: compiler.err.cant.resolve.location: kindname.class, Api, , , (compiler.misc.location: kindname.class, test.Test, null)", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error"); + + if (!expected.equals(log)) + throw new Exception("expected output not found; actual: " + log); + } + @Test public void testUnusedImportOnDemand2(Path base) throws Exception { Path src = base.resolve("src"); diff --git a/test/langtools/tools/javac/modules/EdgeCases.java b/test/langtools/tools/javac/modules/EdgeCases.java index 0dc5d02ce4a..dd68a5142b2 100644 --- a/test/langtools/tools/javac/modules/EdgeCases.java +++ b/test/langtools/tools/javac/modules/EdgeCases.java @@ -73,6 +73,9 @@ import com.sun.tools.javac.code.Symbol.ModuleSymbol; import com.sun.tools.javac.code.Symtab; import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; +import javax.lang.model.element.ModuleElement.DirectiveKind; import toolbox.JarTask; import toolbox.JavacTask; @@ -1153,4 +1156,90 @@ private void record(TaskEvent e, String phase) { } } + @Test + public void testJavaSEHasRequiresTransitiveJavaBase(Path base) throws Exception { + Path src = base.resolve("src"); + Path a = src.resolve("a"); + tb.writeJavaFiles(a, + "module a { requires java.se; }", + """ + package test; + import module java.se; + public class Test { + ArrayList<String> l; + } + """); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + AtomicBoolean seenJavaSEDependency = new AtomicBoolean(); + + List<String> log; + + log = new JavacTask(tb) + .outdir(classes) + .options("-XDrawDiagnostics", "-XDshould-stop.at=FLOW") + .callback(verifyJavaSEDependency(true, seenJavaSEDependency)) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List<String> expected = List.of( + "Test.java:2:8: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.module.imports)", + "1 error"); + + if (!expected.equals(log)) + throw new Exception("expected output not found: " + log); + + if (!seenJavaSEDependency.get()) { + throw new AssertionError("Didn't find the java.se dependency!"); + } + + seenJavaSEDependency.set(false); + + new JavacTask(tb) + .outdir(classes) + .options("--enable-preview", + "--source", System.getProperty("java.specification.version")) + .callback(verifyJavaSEDependency(true, seenJavaSEDependency)) + .files(findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + if (!seenJavaSEDependency.get()) { + throw new AssertionError("Didn't find the java.se dependency!"); + } + } + private Consumer<com.sun.source.util.JavacTask> verifyJavaSEDependency( + boolean expectedTransitive, + AtomicBoolean seenJavaSEDependency) { + return t -> { + t.addTaskListener(new TaskListener() { + @Override + public void finished(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.ANALYZE) { + ModuleElement javaBase = + t.getElements().getModuleElement("java.base"); + ModuleElement javaSE = + t.getElements().getModuleElement("java.se"); + RequiresDirective requiresJavaBase = + javaSE.getDirectives() + .stream() + .filter(d -> d.getKind() == DirectiveKind.REQUIRES) + .map(d -> (RequiresDirective) d) + .filter(d -> d.getDependency() == javaBase) + .findAny() + .orElseThrow(); + if (requiresJavaBase.isTransitive() != expectedTransitive) { + throw new AssertionError("Expected: " + expectedTransitive + ", " + + "but got: " + requiresJavaBase.isTransitive()); + } + seenJavaSEDependency.set(true); + } + } + }); + }; + } } diff --git a/test/langtools/tools/javac/modules/JavaBaseTest.java b/test/langtools/tools/javac/modules/JavaBaseTest.java index 6d9f574705d..484225fcd0c 100644 --- a/test/langtools/tools/javac/modules/JavaBaseTest.java +++ b/test/langtools/tools/javac/modules/JavaBaseTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8193125 8196623 + * @bug 8193125 8196623 8335989 * @summary test modifiers with java.base * @library /tools/lib * @enablePreview @@ -49,6 +49,7 @@ import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.platform.JDKPlatformProvider; +import java.util.function.Supplier; import toolbox.JavacTask; import toolbox.Task; @@ -56,6 +57,8 @@ public class JavaBaseTest { + private static final String CURRENT_VERSION = System.getProperty("java.specification.version"); + public static void main(String... args) throws Exception { JavaBaseTest t = new JavaBaseTest(); t.run(); @@ -75,13 +78,11 @@ enum Mode { SOURCE, CLASS }; void run() throws Exception { Set<String> targets = new LinkedHashSet<>(); - StreamSupport.stream(new JDKPlatformProvider().getSupportedPlatformNames() - .spliterator(), - false) - .filter(p -> Integer.parseInt(p) >= 9) - .forEach(targets::add); - //run without --release: + targets.add("9"); + targets.add("10"); + targets.add("21"); targets.add("current"); + targets.add("current-preview"); for (List<String> mods : modifiers) { for (String target : targets) { for (Mode mode : Mode.values()) { @@ -119,15 +120,43 @@ void testSource(Path base, List<String> mods, String target) throws Exception { tb.writeJavaFiles(src, "module m { requires " + String.join(" ", mods) + " java.base; }"); Path modules = Files.createDirectories(base.resolve("modules")); - boolean expectOK = target.equals("9"); + boolean expectOK; JavacTask jct = new JavacTask(tb) .outdir(modules); - if (target.equals("current")) - jct.options("-XDrawDiagnostics"); - else - jct.options("-XDrawDiagnostics", "--release", target); + List<String> options = new ArrayList<>(); + + switch (target) { + case "current": + options.add("--release"); + options.add(CURRENT_VERSION); + expectOK = false; + break; + case "current-preview": + options.add("--enable-preview"); + options.add("--release"); + options.add(CURRENT_VERSION); + expectOK = true; + break; + case "9": + options.add("--release"); + options.add(target); + expectOK = true; + break; + default: + options.add("--release"); + options.add(target); + expectOK = false; + break; + } + + if (mods.contains("static") && !"9".equals(target)) { + expectOK = false; + } + + options.add("-XDrawDiagnostics"); + jct.options(options); String log = jct.files(tb.findJavaFiles(src)) .run(expectOK ? Task.Expect.SUCCESS : Task.Expect.FAIL) @@ -138,9 +167,9 @@ void testSource(Path base, List<String> mods, String target) throws Exception { boolean foundErrorMessage = false; for (String mod : mods) { String key = mod.equals("static") - ? "compiler.err.mod.not.allowed.here" - : "compiler.err.modifier.not.allowed.here"; - String message = "module-info.java:1:12: " + key + ": " + mod; + ? "compiler.err.mod.not.allowed.here: " + mod + : "compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.java.base.transitive)"; + String message = "module-info.java:1:12: " + key; if (log.contains(message)) { foundErrorMessage = true; } @@ -152,18 +181,57 @@ void testSource(Path base, List<String> mods, String target) throws Exception { } void testClass(Path base, List<String> mods, String target) throws Exception { - createClass(base, mods, target); + boolean expectOK; + List<String> options = new ArrayList<>(); + + switch (target) { + case "current": + options.add("--release"); + options.add(CURRENT_VERSION); + expectOK = false; + break; + case "current-preview": + options.add("--enable-preview"); + options.add("--release"); + options.add(CURRENT_VERSION); + expectOK = true; + break; + case "9": + options.add("--release"); + options.add(target); + expectOK = true; + break; + default: + options.add("--release"); + options.add(target); + expectOK = false; + break; + } + + if (mods.contains("static") && !"9".equals(target)) { + expectOK = false; + } + + createClass(base, mods, options); + + List<String> testOptions = new ArrayList<>(); + + testOptions.add("-XDrawDiagnostics"); + testOptions.add("--module-path"); testOptions.add(base.resolve("test-modules").toString()); + + if (options.contains("--enable-preview")) { + testOptions.add("--enable-preview"); + testOptions.add("--source"); testOptions.add(CURRENT_VERSION); + } Path src = base.resolve("src"); tb.writeJavaFiles(src, "module mx { requires m; }"); Path modules = Files.createDirectories(base.resolve("modules")); - boolean expectOK = target.equals("9"); String log = new JavacTask(tb) .outdir(modules) - .options("-XDrawDiagnostics", - "--module-path", base.resolve("test-modules").toString()) + .options(testOptions) .files(tb.findJavaFiles(src)) .run(expectOK ? Task.Expect.SUCCESS : Task.Expect.FAIL) .writeAll() @@ -188,7 +256,7 @@ void testClass(Path base, List<String> mods, String target) throws Exception { } } - void createClass(Path base, List<String> mods, String target) throws Exception { + void createClass(Path base, List<String> mods, List<String> options) throws Exception { Path src1 = base.resolve("interim-src"); tb.writeJavaFiles(src1, "module m { requires java.base; }"); @@ -197,9 +265,7 @@ void createClass(Path base, List<String> mods, String target) throws Exception { JavacTask jct = new JavacTask(tb) .outdir(modules1); - if (!target.equals("current")) { - jct.options("--release", target); - } + jct.options(options); jct.files(tb.findJavaFiles(src1)) .run(Task.Expect.SUCCESS); @@ -226,6 +292,8 @@ void createClass(Path base, List<String> mods, String target) throws Exception { requires.set(i, e2); } + boolean preview = options.contains("--enable-preview"); + ModuleAttribute modAttr2 = ModuleAttribute.of( modAttr1.moduleName(), modAttr1.moduleFlagsMask(), @@ -237,8 +305,14 @@ void createClass(Path base, List<String> mods, String target) throws Exception { modAttr1.provides()); Path modInfo = base.resolve("test-modules").resolve("module-info.class"); Files.createDirectories(modInfo.getParent()); - byte[] newBytes = ClassFile.of().transformClass(cm1, ClassTransform.dropping(ce -> ce instanceof ModuleAttribute). - andThen(ClassTransform.endHandler(classBuilder -> classBuilder.with(modAttr2)))); + ClassTransform replace = (builder, element) -> { + switch (element) { + case ClassFileVersion cfv when preview -> builder.withVersion(cfv.majorVersion(), 0xFFFF); + case ModuleAttribute _ -> builder.with(modAttr2); + default -> builder.with(element); + } + }; + byte[] newBytes = ClassFile.of().transformClass(cm1, replace); try (OutputStream out = Files.newOutputStream(modInfo)) { out.write(newBytes); } diff --git a/test/langtools/tools/javac/patterns/BindingPatternVarTypeModel.java b/test/langtools/tools/javac/patterns/BindingPatternVarTypeModel.java index 8327580a086..e63cbeb2008 100644 --- a/test/langtools/tools/javac/patterns/BindingPatternVarTypeModel.java +++ b/test/langtools/tools/javac/patterns/BindingPatternVarTypeModel.java @@ -23,18 +23,28 @@ /* * @test - * @bug 8332725 + * @bug 8332725 8341901 * @summary Verify the AST model works correctly for binding patterns with var */ import com.sun.source.tree.BindingPatternTree; import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.IdentifierTree; +import com.sun.source.tree.MemberSelectTree; import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; import com.sun.source.util.JavacTask; +import com.sun.source.util.TreePathScanner; import com.sun.source.util.TreeScanner; +import com.sun.source.util.Trees; import java.net.URI; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; @@ -45,6 +55,7 @@ public class BindingPatternVarTypeModel { public static void main(String... args) throws Exception { new BindingPatternVarTypeModel().run(); + new BindingPatternVarTypeModel().runVarParameterized(); } private void run() throws Exception { @@ -86,4 +97,85 @@ public Void visitBindingPattern(BindingPatternTree node, Void p) { throw new AssertionError("Didn't find the binding pattern!"); } } + + private void runVarParameterized() throws Exception { + JavaFileObject input = + SimpleJavaFileObject.forSource(URI.create("mem:///Test.java"), + """ + package test; + public class Test { + record R(N.I i) {} + int test(Object o) { + Test.N.I checkType0 = null; + var checkType1 = checkType0; + return switch (o) { + case R(var checkType2) -> 0; + default -> 0; + }; + } + static class N<T> { + interface I {} + } + } + """); + DiagnosticListener<JavaFileObject> noErrors = d -> { + if (d.getKind() == Diagnostic.Kind.ERROR) { + throw new IllegalStateException(d.toString()); + } + }; + JavacTask task = + (JavacTask) compiler.getTask(null, null, noErrors, null, null, List.of(input)); + CompilationUnitTree cut = task.parse().iterator().next(); + Trees trees = Trees.instance(task); + + task.analyze(); + + new TreePathScanner<Void, Void>() { + private boolean checkAttributes; + @Override + public Void visitVariable(VariableTree node, Void p) { + boolean prevCheckAttributes = checkAttributes; + try { + checkAttributes |= + node.getName().toString().startsWith("checkType"); + return super.visitVariable(node, p); + } finally { + checkAttributes = prevCheckAttributes; + } + } + + @Override + public Void visitIdentifier(IdentifierTree node, Void p) { + checkType(); + return super.visitIdentifier(node, p); + } + + @Override + public Void visitMemberSelect(MemberSelectTree node, Void p) { + checkType(); + return super.visitMemberSelect(node, p); + } + + private void checkType() { + if (!checkAttributes) { + return ; + } + + TypeMirror type = trees.getTypeMirror(getCurrentPath()); + + if (type.getKind() == TypeKind.PACKAGE) { + return ; //OK + } + if (type.getKind() != TypeKind.DECLARED) { + throw new AssertionError("Expected a declared type, but got: " + + type.getKind()); + } + + if (!((DeclaredType) type).getTypeArguments().isEmpty()) { + throw new AssertionError("Unexpected type arguments: " + + ((DeclaredType) type).getTypeArguments()); + } + } + }.scan(cut, null); + } } diff --git a/test/langtools/tools/javac/patterns/T8340145.java b/test/langtools/tools/javac/patterns/T8340145.java new file mode 100644 index 00000000000..04b12664b72 --- /dev/null +++ b/test/langtools/tools/javac/patterns/T8340145.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024, 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 8340145 + * @summary Problem with generic pattern matching results in internal compiler error + * @compile T8340145.java + * @run main T8340145 + */ +public class T8340145 { + public static void main(String[] args) { + Option<Integer> optionInteger = new Option.Some<>(21); + Number number = Option.unwrapOrElse(optionInteger, 5.2); + + Option2<Impl> optionBound = new Option2.Some<>(new Impl (){}); + Bound number2 = Option2.unwrapOrElse(optionBound, new Impl(){}); + } + + sealed interface Option<T> permits Option.Some, Option.None { + record Some<T>(T value) implements Option<T> {} + record None<T>() implements Option<T> {} + + static <T, T2 extends T> T unwrapOrElse(Option<T2> option, T defaultValue) { + return switch (option) { + case Option.Some(T2 value) -> value; + case Option.None<T2> _ -> defaultValue; + }; + } + } + + interface Bound {} + interface Bound2 {} + static class Impl implements Bound, Bound2 {} + sealed interface Option2<T> permits Option2.Some, Option2.None { + record Some<T>(T value) implements Option2<T> {} + record None<T>() implements Option2<T> {} + + static <T extends Bound & Bound2> T unwrapOrElse(Option2<T> option, T defaultValue) { + return switch (option) { + case Option2.Some(T value) -> value; + case Option2.None<T> _ -> defaultValue; + }; + } + } +} diff --git a/test/langtools/tools/javac/sealed/CheckSubtypesOfSealedTest.java b/test/langtools/tools/javac/sealed/CheckSubtypesOfSealedTest.java index 0366d4982ca..0f9634423ec 100644 --- a/test/langtools/tools/javac/sealed/CheckSubtypesOfSealedTest.java +++ b/test/langtools/tools/javac/sealed/CheckSubtypesOfSealedTest.java @@ -76,7 +76,7 @@ enum CheckFor { void check(ClassModel classFile) throws Exception { boolean found = false; for (Attribute<?> attr: classFile.attributes()) { - if (attr.attributeName().equals("PermittedSubclasses")) { + if (attr.attributeName().equalsString("PermittedSubclasses")) { PermittedSubclassesAttribute permittedSubclasses = (PermittedSubclassesAttribute)attr; found = true; if (permittedSubclasses.permittedSubclasses().isEmpty()) { @@ -99,7 +99,7 @@ void check(ClassModel classFile) throws Exception { NOT_SEALED { void check(ClassModel classFile) throws Exception { for (Attribute<?> attr: classFile.attributes()) { - if (attr.attributeName().equals("PermittedSubclasses")) { + if (attr.attributeName().equalsString("PermittedSubclasses")) { throw new AssertionError(classFile.thisClass().name() + " should not be sealed"); } } diff --git a/test/langtools/tools/javap/T6716452.java b/test/langtools/tools/javap/T6716452.java index 63ccead52e7..20c382918c3 100644 --- a/test/langtools/tools/javap/T6716452.java +++ b/test/langtools/tools/javap/T6716452.java @@ -70,7 +70,7 @@ <T extends Attribute<T>> void test(MethodModel mm, AttributeMapper<T> attr, Clas if (!c.isAssignableFrom(mm.attributes().get(index).getClass())) { error(mm + ": unexpected attribute found," + " expected " + c.getName() - + " found " + mm.attributes().get(index).attributeName()); + + " found " + mm.attributes().get(index).attributeName().stringValue()); } } else { error(mm + ": expected attribute " + attr.name() + " not found"); diff --git a/test/lib/jdk/test/lib/cds/CDSAppTester.java b/test/lib/jdk/test/lib/cds/CDSAppTester.java index c39e6bb8e94..d83c3c36e41 100644 --- a/test/lib/jdk/test/lib/cds/CDSAppTester.java +++ b/test/lib/jdk/test/lib/cds/CDSAppTester.java @@ -28,6 +28,7 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.StringArrayUtils; +import jtreg.SkippedException; /* * This is a base class used for testing CDS functionalities with complex applications. @@ -42,9 +43,13 @@ abstract public class CDSAppTester { private final String staticArchiveFileLog; private final String dynamicArchiveFile; private final String dynamicArchiveFileLog; - private final String productionRunLog; + private int numProductionRuns = 0; public CDSAppTester(String name) { + if (CDSTestUtils.DYNAMIC_DUMP) { + throw new SkippedException("Tests based on CDSAppTester should be excluded when -Dtest.dynamic.cds.archive is specified"); + } + // Old workflow this.name = name; classListFile = name() + ".classlist"; @@ -53,7 +58,14 @@ public CDSAppTester(String name) { staticArchiveFileLog = staticArchiveFile + ".log"; dynamicArchiveFile = name() + ".dynamic.jsa"; dynamicArchiveFileLog = dynamicArchiveFile + ".log"; - productionRunLog = name() + ".production.log"; + } + + private String productionRunLog() { + if (numProductionRuns == 0) { + return name() + ".production.log"; + } else { + return name() + ".production." + numProductionRuns + ".log"; + } } private enum Workflow { @@ -97,6 +109,11 @@ public String classpath(RunMode runMode) { public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception {} private Workflow workflow; + private boolean checkExitValue = true; + + public final void setCheckExitValue(boolean b) { + checkExitValue = b; + } public final boolean isStaticWorkflow() { return workflow == Workflow.STATIC; @@ -134,7 +151,10 @@ private OutputAnalyzer executeAndCheck(String[] cmdLine, RunMode runMode, String for (String logFile : logFiles) { listOutputFile(logFile); } - output.shouldHaveExitValue(0); + if (checkExitValue) { + output.shouldHaveExitValue(0); + } + output.shouldNotContain(CDSTestUtils.MSG_STATIC_FIELD_MAY_HOLD_DIFFERENT_VALUE); CDSTestUtils.checkCommonExecExceptions(output); checkExecution(output, runMode); return output; @@ -189,10 +209,22 @@ private OutputAnalyzer dumpDynamicArchive() throws Exception { } private OutputAnalyzer productionRun() throws Exception { + return productionRun(null, null); + } + + public OutputAnalyzer productionRun(String[] extraVmArgs) throws Exception { + return productionRun(extraVmArgs, null); + } + + // After calling run(String[]), you can call this method to run the app again, with the AOTCache + // using different args to the VM and application. + public OutputAnalyzer productionRun(String[] extraVmArgs, String[] extraAppArgs) throws Exception { RunMode runMode = RunMode.PRODUCTION; String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode), + "-XX:+UnlockDiagnosticVMOptions", + "-XX:VerifyArchivedFields=2", // make sure archived heap objects are good. "-cp", classpath(runMode), - logToFile(productionRunLog, "cds")); + logToFile(productionRunLog(), "cds")); if (isStaticWorkflow()) { cmdLine = StringArrayUtils.concat(cmdLine, "-XX:SharedArchiveFile=" + staticArchiveFile); @@ -200,8 +232,19 @@ private OutputAnalyzer productionRun() throws Exception { cmdLine = StringArrayUtils.concat(cmdLine, "-XX:SharedArchiveFile=" + dynamicArchiveFile); } + if (extraVmArgs != null) { + cmdLine = StringArrayUtils.concat(cmdLine, extraVmArgs); + } + cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); - return executeAndCheck(cmdLine, runMode, productionRunLog); + + if (extraAppArgs != null) { + cmdLine = StringArrayUtils.concat(cmdLine, extraAppArgs); + } + + OutputAnalyzer out = executeAndCheck(cmdLine, runMode, productionRunLog()); + numProductionRuns ++; + return out; } public void run(String args[]) throws Exception { diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index 7115912380a..a913f2f9fa2 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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 @@ -51,6 +51,8 @@ public class CDSTestUtils { "Unable to allocate region, java heap range is already in use."; public static final String MSG_DYNAMIC_NOT_SUPPORTED = "-XX:ArchiveClassesAtExit is unsupported when base CDS archive is not loaded"; + public static final String MSG_STATIC_FIELD_MAY_HOLD_DIFFERENT_VALUE = + "an object points to a static field that may hold a different value at runtime"; public static final boolean DYNAMIC_DUMP = Boolean.getBoolean("test.dynamic.cds.archive"); public interface Checker { @@ -284,6 +286,7 @@ public static OutputAnalyzer checkDump(OutputAnalyzer output, String... extraMat output.shouldContain("Written dynamic archive 0x"); } output.shouldHaveExitValue(0); + output.shouldNotContain(MSG_STATIC_FIELD_MAY_HOLD_DIFFERENT_VALUE); for (String match : extraMatches) { output.shouldContain(match); @@ -296,6 +299,7 @@ public static OutputAnalyzer checkDump(OutputAnalyzer output, String... extraMat public static OutputAnalyzer checkBaseDump(OutputAnalyzer output) throws Exception { output.shouldContain("Loading classes to share"); output.shouldHaveExitValue(0); + output.shouldNotContain(MSG_STATIC_FIELD_MAY_HOLD_DIFFERENT_VALUE); return output; } @@ -859,4 +863,24 @@ public static Path copyFile(String srcFile, String destDir) throws Exception { Files.copy(srcPath, destPath, REPLACE_EXISTING, COPY_ATTRIBUTES); return destPath; } + + // Some tests were initially written without the knowledge of -XX:+AOTClassLinking. These tests need to + // be adjusted if -XX:+AOTClassLinking is specified in jtreg -vmoptions or -javaoptions: + public static boolean isAOTClassLinkingEnabled() { + return isBooleanVMOptionEnabledInCommandLine("AOTClassLinking"); + } + + public static boolean isBooleanVMOptionEnabledInCommandLine(String optionName) { + String lastMatch = null; + String pattern = "^-XX:." + optionName + "$"; + for (String s : Utils.getTestJavaOpts()) { + if (s.matches(pattern)) { + lastMatch = s; + } + } + if (lastMatch != null && lastMatch.equals("-XX:+" + optionName)) { + return true; + } + return false; + } } diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 0db7c46c6cf..2e723d91267 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -776,9 +776,6 @@ public native int validateCgroup(String procCgroups, // Resolved Method Table public native long resolvedMethodItemsCount(); - // Protection Domain Table - public native int protectionDomainRemovedCount(); - public native int getKlassMetadataSize(Class<?> c); // ThreadSMR GC safety check for threadObj diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorStoreToLoadForwarding.java b/test/micro/org/openjdk/bench/vm/compiler/VectorStoreToLoadForwarding.java new file mode 100644 index 00000000000..ac8940ec675 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorStoreToLoadForwarding.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2024, 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.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.*; + +import java.lang.invoke.*; + +import java.util.concurrent.TimeUnit; +import java.util.Random; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(value = 1) +public abstract class VectorStoreToLoadForwarding { + @Param({"10000"}) + public int SIZE; + + @Param({ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", + "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", + "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", + "120", "121", "122", "123", "124", "125", "126", "127", "128", "129"}) + public int OFFSET; + + // To get compile-time constants for OFFSET + static final MutableCallSite MUTABLE_CONSTANT = new MutableCallSite(MethodType.methodType(int.class)); + static final MethodHandle MUTABLE_CONSTANT_HANDLE = MUTABLE_CONSTANT.dynamicInvoker(); + + public int START = 1000; + + private byte[] aB; + private short[] aS; + private int[] aI; + private long[] aL; + + @Param("0") + private int seed; + private Random r = new Random(seed); + + @Setup + public void init() throws Throwable { + aB = new byte[SIZE]; + aS = new short[SIZE]; + aI = new int[SIZE]; + aL = new long[SIZE]; + + for (int i = START; i < SIZE; i++) { + aB[i] = (byte)r.nextInt(); + aS[i] = (short)r.nextInt(); + aI[i] = r.nextInt(); + aL[i] = r.nextLong(); + } + + MethodHandle constant = MethodHandles.constant(int.class, OFFSET); + MUTABLE_CONSTANT.setTarget(constant); + } + + @CompilerControl(CompilerControl.Mode.INLINE) + private int offset_con() throws Throwable { + return (int) MUTABLE_CONSTANT_HANDLE.invokeExact(); + } + + @Benchmark + public void bytes() throws Throwable { + int offset = offset_con(); + for (int i = START; i < SIZE; i++) { + aB[i] = (byte)(aB[i - offset] + 1); + } + } + + @Benchmark + public void shorts() throws Throwable { + int offset = offset_con(); + for (int i = START; i < SIZE; i++) { + aS[i] = (short)(aS[i - offset] + 1); + } + } + + @Benchmark + public void ints() throws Throwable { + int offset = offset_con(); + for (int i = START; i < SIZE; i++) { + aI[i] = aI[i - offset] + 1; + } + } + + @Benchmark + public void longs() throws Throwable { + int offset = offset_con(); + for (int i = START; i < SIZE; i++) { + aL[i] = (long)(aL[i - offset] + 1); + } + } + + @Fork(value = 1, jvmArgs = { + "-XX:+UseSuperWord" + }) + public static class Default extends VectorStoreToLoadForwarding {} + + @Fork(value = 1, jvmArgs = { + "-XX:-UseSuperWord" + }) + public static class NoVectorization extends VectorStoreToLoadForwarding {} + + @Fork(value = 1, jvmArgs = { + "-XX:+UseSuperWord", "-XX:+UnlockDiagnosticVMOptions", "-XX:SuperWordStoreToLoadForwardingFailureDetection=0" + }) + public static class NoStoreToLoadForwardFailureDetection extends VectorStoreToLoadForwarding {} +}