diff --git a/make/data/cacerts/globalsignr2ca b/make/data/cacerts/globalsignr2ca deleted file mode 100644 index 746d1fab985..00000000000 --- a/make/data/cacerts/globalsignr2ca +++ /dev/null @@ -1,29 +0,0 @@ -Owner: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R2 -Issuer: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R2 -Serial number: 400000000010f8626e60d -Valid from: Fri Dec 15 08:00:00 GMT 2006 until: Wed Dec 15 08:00:00 GMT 2021 -Signature algorithm name: SHA1withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- diff --git a/make/data/currency/CurrencyData.properties b/make/data/currency/CurrencyData.properties index a4ad6d613b8..1a92ef5b867 100644 --- a/make/data/currency/CurrencyData.properties +++ b/make/data/currency/CurrencyData.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 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 @@ -317,6 +317,8 @@ KI=AUD KP=KPW # KOREA (THE REPUBLIC OF) KR=KRW +# KOSOVO - Not in ISO 3166/4217 +XK=EUR # KUWAIT KW=KWD # KYRGYZSTAN diff --git a/make/modules/java.desktop/Java.gmk b/make/modules/java.desktop/Java.gmk index 4b1c14a1133..e9f0d1fa318 100644 --- a/make/modules/java.desktop/Java.gmk +++ b/make/modules/java.desktop/Java.gmk @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference \ +DOCLINT += -Xdoclint:all/protected,-reference,-missing \ '-Xdoclint/package:java.*,javax.*' COPY += .gif .png .wav .txt .xml .css .pf CLEAN += iio-plugin.properties cursors.properties diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index 4d0c0c00dbf..ef7eadae206 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -435,7 +435,7 @@ endif ifeq ($(USE_EXTERNAL_HARFBUZZ), true) LIBFONTMANAGER_EXTRA_SRC = - BUILD_LIBFONTMANAGER_FONTLIB += $(LIBHARFBUZZ_LIBS) + BUILD_LIBFONTMANAGER_FONTLIB += $(HARFBUZZ_LIBS) else LIBFONTMANAGER_EXTRA_SRC = libharfbuzz diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh index 42886573f2c..c7215058b50 100644 --- a/make/scripts/compare.sh +++ b/make/scripts/compare.sh @@ -362,8 +362,14 @@ compare_general_files() { THIS_FILE=$WORK_DIR/$f.this $MKDIR -p $(dirname $OTHER_FILE) $(dirname $THIS_FILE) $RM $OTHER_FILE $THIS_FILE - $CAT $OTHER_DIR/$f | $SORT > $OTHER_FILE - $CAT $THIS_DIR/$f | $SORT > $THIS_FILE + # Also filter out the "id: NNNN" in the classlists + if [[ "$f" = *"/lib/classlist" ]]; then + $CAT $OTHER_DIR/$f | $SORT | $SED "s| id: .*||g" > $OTHER_FILE + $CAT $THIS_DIR/$f | $SORT | $SED "s| id: .*||g" > $THIS_FILE + else + $CAT $OTHER_DIR/$f | $SORT > $OTHER_FILE + $CAT $THIS_DIR/$f | $SORT > $THIS_FILE + fi else OTHER_FILE=$OTHER_DIR/$f THIS_FILE=$THIS_DIR/$f diff --git a/src/demo/share/jfc/Font2DTest/Font2DTest.html b/src/demo/share/jfc/Font2DTest/Font2DTest.html deleted file mode 100644 index 4c94fc02b70..00000000000 --- a/src/demo/share/jfc/Font2DTest/Font2DTest.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - -Font2DTest Demo - - - - - -
-
- -

-Font2DTest -

- -An encompassing font/glyph demo application. -Source code is in
-Font2DTest.java,
-Font2DTestApplet.java,
-RangeMenu.java and
-FontPanel.java.
-You can run this program either as an applet or as an application.
-Detailed information about the program can be found in -README.txt
- -

To run it as an application, -execute the Font2DTest class. -For example: - -

-
-% java -jar Font2DTest.jar
-
-
- -

-Note: If AWTPermission's showWindowWithoutWarningBanner permission is not given,
-the zoom feature will not look as good, as characters may be hidden by the warning banner.
- - - - -


- - - - diff --git a/src/demo/share/jfc/Font2DTest/Font2DTest.java b/src/demo/share/jfc/Font2DTest/Font2DTest.java index 0fb8251b718..4c698344c34 100644 --- a/src/demo/share/jfc/Font2DTest/Font2DTest.java +++ b/src/demo/share/jfc/Font2DTest/Font2DTest.java @@ -133,7 +133,7 @@ public final class Font2DTest extends JPanel private static boolean canDisplayCheck = true; /// Initialize GUI variables and its layouts - public Font2DTest( JFrame f, boolean isApplet ) { + public Font2DTest( JFrame f) { parent = f; rm = new RangeMenu( this, parent ); @@ -165,8 +165,8 @@ public Font2DTest( JFrame f, boolean isApplet ) { contrastSlider.setPaintLabels(true); contrastSlider.addChangeListener(this); setupPanel(); - setupMenu( isApplet ); - setupDialog( isApplet ); + setupMenu(); + setupDialog(); if(canDisplayCheck) { fireRangeChanged(); @@ -256,7 +256,7 @@ private void addLabeledComponentToGBL( String name, } /// Sets up menu entries - private void setupMenu( boolean isApplet ) { + private void setupMenu() { JMenu fileMenu = new JMenu( "File" ); JMenu optionMenu = new JMenu( "Option" ); @@ -268,11 +268,7 @@ private void setupMenu( boolean isApplet ) { fileMenu.add( new MenuItemV2( "Page Setup...", this )); fileMenu.add( new MenuItemV2( "Print...", this )); fileMenu.addSeparator(); - if ( !isApplet ) - fileMenu.add( new MenuItemV2( "Exit", this )); - else - fileMenu.add( new MenuItemV2( "Close", this )); - + fileMenu.add( new MenuItemV2( "Exit", this )); displayGridCBMI = new CheckboxMenuItemV2( "Display Grid", true, this ); force16ColsCBMI = new CheckboxMenuItemV2( "Force 16 Columns", false, this ); showFontInfoCBMI = new CheckboxMenuItemV2( "Display Font Info", false, this ); @@ -326,11 +322,8 @@ private void setupMenu( boolean isApplet ) { } /// Sets up the all dialogs used in Font2DTest... - private void setupDialog( boolean isApplet ) { - if (!isApplet) - filePromptDialog = new JFileChooser( ); - else - filePromptDialog = null; + private void setupDialog() { + filePromptDialog = new JFileChooser(); /// Prepare user text dialog... userTextDialog = new JDialog( parent, "User Text", false ); @@ -432,8 +425,6 @@ public void fireRangeChanged() { /// Changes the message on the status bar public void fireChangeStatus( String message, boolean error ) { - /// If this is not ran as an applet, use own status bar, - /// Otherwise, use the appletviewer/browser's status bar statusBar.setText( message ); if ( error ) fp.showingError = true; @@ -1030,7 +1021,7 @@ public static void main(String[] argv) { UIManager.put("swing.boldMetal", Boolean.FALSE); final JFrame f = new JFrame( "Font2DTest" ); - final Font2DTest f2dt = new Font2DTest( f, false ); + final Font2DTest f2dt = new Font2DTest( f); f.addWindowListener( new WindowAdapter() { public void windowOpening( WindowEvent e ) { f2dt.repaint(); } public void windowClosing( WindowEvent e ) { System.exit(0); } diff --git a/src/demo/share/jfc/Font2DTest/README.txt b/src/demo/share/jfc/Font2DTest/README.txt index 1eb959d79ed..60f8c013aab 100644 --- a/src/demo/share/jfc/Font2DTest/README.txt +++ b/src/demo/share/jfc/Font2DTest/README.txt @@ -4,35 +4,17 @@ Font2DTest To run Font2DTest: % java -jar Font2DTest.jar - or -% appletviewer Font2DTest.html -These instructions assume that the 1.7 versions of the java -and appletviewer commands are in your path. If they aren't, -then you should either specify the complete path to the commands +These instructions assume that the java command is in your path. +If they aren't, then you should either specify the complete path to the commands or update your PATH environment variable as described in the installation instructions for the Java(TM) SE Development Kit. -To view Font2DTest within a web browser with Java Plugin, -load Font2DTest.html. - If you wish to modify any of the source code, you may want to extract the contents of the Font2DTest.jar file by executing this command: % jar -xvf Font2DTest.jar -NOTE: - -When Font2DTest is ran as an applet, the browser plugin/viewer needs -following permissions given in order to run properly: - -AWTPermission "showWindowWithoutWarningBanner" -RuntimePermission "queuePrintJob" - -The program will run without these properties set, -but some of its features will be limited. -To enable all features, please add these permissions. - ----------------------------------------------------------------------- Introduction ----------------------------------------------------------------------- @@ -129,23 +111,3 @@ that are within the selected range. Third option, "Print all text..." is similar, and it will print all lines of text that user has put in. ==================================================================== - -Known Problems: - -- When a PostScript font is used, the characters may extend beyond the -enclosing grid or zoom rectangle. This is due to the problem with -FontMetrics.getMaxAscent() and getMaxDescent() functions; the functions -do not always return the right values for PostScript fonts. - -- There are still some bugs around the error handling. -Most of these problems will usually get fixed when some parameters -are changed, or the screen is refreshed. - -- Many fonts on Solaris fails to retrieve outlines properly, -and as the result, they do not align within the grid properly. -These are mainly F3 and fonts that was returned by X server. - -- When showWindowWithoutWarningBanner AWTPermission is not given, -the "zoom" window will look really bad because of the -Applet warning label tacked at the bottom of the zoom window. -To remove this, follow the "NOTE:" instruction at the top. diff --git a/src/demo/share/jfc/SwingSet2/TableDemo.java b/src/demo/share/jfc/SwingSet2/TableDemo.java index 48199c564a8..eeb3b2d3da1 100644 --- a/src/demo/share/jfc/SwingSet2/TableDemo.java +++ b/src/demo/share/jfc/SwingSet2/TableDemo.java @@ -549,7 +549,10 @@ public JScrollPane createTable() { public int getRowCount() { return data.length;} public Object getValueAt(int row, int col) {return data[row][col];} public String getColumnName(int column) {return names[column];} - public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} + public Class getColumnClass(int c) { + Object obj = getValueAt(0, c); + return obj != null ? obj.getClass() : Object.class; + } public boolean isCellEditable(int row, int col) {return col != 5;} public void setValueAt(Object aValue, int row, int column) { data[row][column] = aValue; } }; diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index b439490660c..37a26dbb2b5 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2147,7 +2147,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo as_FloatRegister(Matcher::_regEncode[src_lo])); } } else if (dst_lo_rc == rc_float) { // fpr --> fpr copy - if (cbuf) { + if (is64) { __ fmovd(as_FloatRegister(Matcher::_regEncode[dst_lo]), as_FloatRegister(Matcher::_regEncode[src_lo])); } else { diff --git a/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 index 076eec1c973..15fce08e9ce 100644 --- a/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 @@ -872,7 +872,7 @@ instruct vcmpD(vecD dst, vecD src1, vecD src2, immI cond) format %{ "vcmpD $dst, $src1, $src2\t# vector compare " %} ins_cost(INSN_COST); ins_encode %{ - BasicType bt = vector_element_basic_type(this); + BasicType bt = Matcher::vector_element_basic_type(this); assert(type2aelembytes(bt) != 8, "not supported"); __ neon_compare(as_FloatRegister($dst$$reg), bt, as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg), (int)$cond$$constant, /*isQ*/ false); @@ -887,7 +887,7 @@ instruct vcmpX(vecX dst, vecX src1, vecX src2, immI cond) format %{ "vcmpX $dst, $src1, $src2\t# vector compare " %} ins_cost(INSN_COST); ins_encode %{ - BasicType bt = vector_element_basic_type(this); + BasicType bt = Matcher::vector_element_basic_type(this); __ neon_compare(as_FloatRegister($dst$$reg), bt, as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg), (int)$cond$$constant, /*isQ*/ true); %} @@ -2292,7 +2292,7 @@ ifelse($1, `_LT8B', ` __ clz($dst$$Register, $dst$$Register); __ lsrw($dst$$Register, $dst$$Register, 3);dnl ifelse(`$1', `_LT8B', ` - __ movw(rscratch1, vector_length(this, $src)); + __ movw(rscratch1, Matcher::vector_length(this, $src)); __ cmpw($dst$$Register, rscratch1); __ cselw($dst$$Register, rscratch1, $dst$$Register, Assembler::GE);') %} diff --git a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 index bc166185570..9d86b767d90 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 @@ -214,7 +214,7 @@ instruct loadV(vReg dst, vmemA mem) %{ ins_encode %{ FloatRegister dst_reg = as_FloatRegister($dst$$reg); loadStoreA_predicate(C2_MacroAssembler(&cbuf), false, dst_reg, ptrue, - vector_element_basic_type(this), $mem->opcode(), + Matcher::vector_element_basic_type(this), $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} ins_pipe(pipe_slow); @@ -228,7 +228,7 @@ instruct storeV(vReg src, vmemA mem) %{ ins_encode %{ FloatRegister src_reg = as_FloatRegister($src$$reg); loadStoreA_predicate(C2_MacroAssembler(&cbuf), true, src_reg, ptrue, - vector_element_basic_type(this, $src), $mem->opcode(), + Matcher::vector_element_basic_type(this, $src), $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} ins_pipe(pipe_slow); @@ -386,7 +386,7 @@ instruct vmin(vReg dst_src1, vReg src2) %{ ins_cost(SVE_COST); format %{ "sve_min $dst_src1, $dst_src1, $src2\t # vector (sve)" %} ins_encode %{ - BasicType bt = vector_element_basic_type(this); + BasicType bt = Matcher::vector_element_basic_type(this); Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt); if (is_floating_point_type(bt)) { __ sve_fmin(as_FloatRegister($dst_src1$$reg), size, @@ -406,7 +406,7 @@ instruct vmax(vReg dst_src1, vReg src2) %{ ins_cost(SVE_COST); format %{ "sve_max $dst_src1, $dst_src1, $src2\t # vector (sve)" %} ins_encode %{ - BasicType bt = vector_element_basic_type(this); + BasicType bt = Matcher::vector_element_basic_type(this); Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt); if (is_floating_point_type(bt)) { __ sve_fmax(as_FloatRegister($dst_src1$$reg), size, diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp index 61702f9ad39..5be02aa57e7 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp @@ -236,14 +236,20 @@ inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const { // Compiled frames inline oop frame::saved_oop_result(RegisterMap* map) const { + PRAGMA_DIAG_PUSH + PRAGMA_NONNULL_IGNORED oop* result_adr = (oop *)map->location(r0->as_VMReg()); + PRAGMA_DIAG_POP guarantee(result_adr != NULL, "bad register save location"); return (*result_adr); } inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) { + PRAGMA_DIAG_PUSH + PRAGMA_NONNULL_IGNORED oop* result_adr = (oop *)map->location(r0->as_VMReg()); + PRAGMA_DIAG_POP guarantee(result_adr != NULL, "bad register save location"); *result_adr = obj; diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 824b89e4810..025d419f153 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -38,6 +38,7 @@ #include "gc/shared/tlab_globals.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interpreter.hpp" +#include "compiler/compileTask.hpp" #include "compiler/disassembler.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" diff --git a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp index f08c0d494aa..0a7f14fa23b 100644 --- a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp @@ -138,6 +138,11 @@ return false; } + // Does the CPU supports vector constant rotate instructions? + static constexpr bool supports_vector_constant_rotates(int shift) { + return false; + } + // Does the CPU supports vector unsigned comparison instructions? static const bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { // Not supported on SVE yet. diff --git a/src/hotspot/cpu/arm/c1_globals_arm.hpp b/src/hotspot/cpu/arm/c1_globals_arm.hpp index 8f196bc5e6a..55917decc30 100644 --- a/src/hotspot/cpu/arm/c1_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c1_globals_arm.hpp @@ -35,7 +35,7 @@ #ifndef COMPILER2 // avoid duplicated definitions, favoring C2 version define_pd_global(bool, BackgroundCompilation, true ); -define_pd_global(bool, InlineIntrinsics, false); // TODO: ARM +define_pd_global(bool, InlineIntrinsics, true ); define_pd_global(bool, PreferInterpreterNativeStubs, false); define_pd_global(bool, ProfileTraps, false); define_pd_global(bool, UseOnStackReplacement, true ); diff --git a/src/hotspot/cpu/arm/c2_globals_arm.hpp b/src/hotspot/cpu/arm/c2_globals_arm.hpp index 1d666357b30..57ed8f11c08 100644 --- a/src/hotspot/cpu/arm/c2_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c2_globals_arm.hpp @@ -34,7 +34,7 @@ define_pd_global(bool, BackgroundCompilation, true); define_pd_global(bool, CICompileOSR, true); -define_pd_global(bool, InlineIntrinsics, false); +define_pd_global(bool, InlineIntrinsics, true); define_pd_global(bool, PreferInterpreterNativeStubs, false); define_pd_global(bool, ProfileTraps, true); define_pd_global(bool, UseOnStackReplacement, true); diff --git a/src/hotspot/cpu/arm/matcher_arm.hpp b/src/hotspot/cpu/arm/matcher_arm.hpp index 0d011a620f9..56f77409a89 100644 --- a/src/hotspot/cpu/arm/matcher_arm.hpp +++ b/src/hotspot/cpu/arm/matcher_arm.hpp @@ -131,6 +131,11 @@ return false; // not supported } + // Does the CPU supports vector constant rotate instructions? + static constexpr bool supports_vector_constant_rotates(int shift) { + return false; + } + // Does the CPU supports vector unsigned comparison instructions? static constexpr bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { return false; diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp index 2891532d9bb..fa8d9e7fb58 100644 --- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp @@ -124,14 +124,114 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) { address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { if (!InlineIntrinsics) return NULL; // Generate a vanilla entry - // TODO: ARM - return NULL; + address entry_point = NULL; + Register continuation = LR; + bool use_runtime_call = false; + switch (kind) { + case Interpreter::java_lang_math_abs: + entry_point = __ pc(); +#ifdef __SOFTFP__ + use_runtime_call = true; + __ ldrd(R0, Address(SP)); +#else // !__SOFTFP__ + __ ldr_double(D0, Address(SP)); + __ abs_double(D0, D0); +#endif // __SOFTFP__ + break; + case Interpreter::java_lang_math_sqrt: + entry_point = __ pc(); +#ifdef __SOFTFP__ + use_runtime_call = true; + __ ldrd(R0, Address(SP)); +#else // !__SOFTFP__ + __ ldr_double(D0, Address(SP)); + __ sqrt_double(D0, D0); +#endif // __SOFTFP__ + break; + case Interpreter::java_lang_math_sin: + case Interpreter::java_lang_math_cos: + case Interpreter::java_lang_math_tan: + case Interpreter::java_lang_math_log: + case Interpreter::java_lang_math_log10: + case Interpreter::java_lang_math_exp: + entry_point = __ pc(); + use_runtime_call = true; +#ifdef __SOFTFP__ + __ ldrd(R0, Address(SP)); +#else // !__SOFTFP__ + __ ldr_double(D0, Address(SP)); +#endif // __SOFTFP__ + break; + case Interpreter::java_lang_math_pow: + entry_point = __ pc(); + use_runtime_call = true; +#ifdef __SOFTFP__ + __ ldrd(R0, Address(SP, 2 * Interpreter::stackElementSize)); + __ ldrd(R2, Address(SP)); +#else // !__SOFTFP__ + __ ldr_double(D0, Address(SP, 2 * Interpreter::stackElementSize)); + __ ldr_double(D1, Address(SP)); +#endif // __SOFTFP__ + break; + case Interpreter::java_lang_math_fmaD: + case Interpreter::java_lang_math_fmaF: + // TODO: Implement intrinsic + break; + default: + ShouldNotReachHere(); + } - address entry_point = __ pc(); - STOP("generate_math_entry"); + if (entry_point != NULL) { + __ mov(SP, Rsender_sp); + if (use_runtime_call) { + __ mov(Rtmp_save0, LR); + continuation = Rtmp_save0; + generate_math_runtime_call(kind); + } + __ ret(continuation); + } return entry_point; } +void TemplateInterpreterGenerator::generate_math_runtime_call(AbstractInterpreter::MethodKind kind) { + address fn; + switch (kind) { +#ifdef __SOFTFP__ + case Interpreter::java_lang_math_abs: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dabs); + break; + case Interpreter::java_lang_math_sqrt: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dsqrt); + break; +#endif // __SOFTFP__ + case Interpreter::java_lang_math_sin: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); + break; + case Interpreter::java_lang_math_cos: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); + break; + case Interpreter::java_lang_math_tan: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); + break; + case Interpreter::java_lang_math_log: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); + break; + case Interpreter::java_lang_math_log10: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10); + break; + case Interpreter::java_lang_math_exp: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dexp); + break; + case Interpreter::java_lang_math_pow: + fn = CAST_FROM_FN_PTR(address, SharedRuntime::dpow); + break; + default: + ShouldNotReachHere(); + fn = NULL; // silence "maybe uninitialized" compiler warnings + } + __ call_VM_leaf(fn); +} + address TemplateInterpreterGenerator::generate_StackOverflowError_handler() { address entry = __ pc(); diff --git a/src/hotspot/cpu/ppc/matcher_ppc.hpp b/src/hotspot/cpu/ppc/matcher_ppc.hpp index cbcebc23ddc..d1bb8b21dbf 100644 --- a/src/hotspot/cpu/ppc/matcher_ppc.hpp +++ b/src/hotspot/cpu/ppc/matcher_ppc.hpp @@ -138,6 +138,11 @@ return false; } + // Does the CPU supports vector constant rotate instructions? + static constexpr bool supports_vector_constant_rotates(int shift) { + return false; + } + // Does the CPU supports vector unsigned comparison instructions? static constexpr bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { return false; diff --git a/src/hotspot/cpu/s390/matcher_s390.hpp b/src/hotspot/cpu/s390/matcher_s390.hpp index 2906f584a31..bc6956c445d 100644 --- a/src/hotspot/cpu/s390/matcher_s390.hpp +++ b/src/hotspot/cpu/s390/matcher_s390.hpp @@ -128,6 +128,11 @@ return false; } + // Does the CPU supports vector constant rotate instructions? + static constexpr bool supports_vector_constant_rotates(int shift) { + return false; + } + // Does the CPU supports vector unsigned comparison instructions? static constexpr bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { return false; diff --git a/src/hotspot/cpu/x86/matcher_x86.hpp b/src/hotspot/cpu/x86/matcher_x86.hpp index 9071740aab3..f8c675c87bd 100644 --- a/src/hotspot/cpu/x86/matcher_x86.hpp +++ b/src/hotspot/cpu/x86/matcher_x86.hpp @@ -158,6 +158,11 @@ return true; } + // Does the CPU supports vector constant rotate instructions? + static constexpr bool supports_vector_constant_rotates(int shift) { + return -0x80 <= shift && shift < 0x80; + } + // Does the CPU supports vector unsigned comparison instructions? static const bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { int vlen_in_bytes = vlen * type2aelembytes(bt); diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index c92c58fadfa..50c2f1b8e9d 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1736,6 +1736,9 @@ void VM_Version::get_processor_features() { if (FLAG_IS_DEFAULT(UseSignumIntrinsic)) { FLAG_SET_DEFAULT(UseSignumIntrinsic, true); } + if (FLAG_IS_DEFAULT(UseCopySignIntrinsic)) { + FLAG_SET_DEFAULT(UseCopySignIntrinsic, true); + } } void VM_Version::print_platform_virtualization_info(outputStream* st) { diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index e449b239f67..a7579a715f6 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1560,6 +1560,15 @@ const bool Matcher::match_rule_supported(int opcode) { return false; } break; + case Op_CopySignD: + case Op_CopySignF: + if (UseAVX < 3 || !is_LP64) { + return false; + } + if (!VM_Version::supports_avx512vl()) { + return false; + } + break; #ifndef _LP64 case Op_AddReductionVF: case Op_AddReductionVD: @@ -1638,6 +1647,9 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType break; case Op_RotateRightV: case Op_RotateLeftV: + if (bt != T_INT && bt != T_LONG) { + return false; + } // fallthrough case Op_MacroLogicV: if (!VM_Version::supports_evex() || ((size_in_bits != 512) && !VM_Version::supports_avx512vl())) { @@ -5785,7 +5797,7 @@ instruct evminmaxFP_reg_eavx(vec dst, vec a, vec b, vec atmp, vec btmp, kReg ktm ins_pipe( pipe_slow ); %} -// --------------------------------- Signum --------------------------- +// --------------------------------- Signum/CopySign --------------------------- instruct signumF_reg(regF dst, regF zero, regF one, rRegP scratch, rFlagsReg cr) %{ match(Set dst (SignumF dst (Binary zero one))); @@ -5809,6 +5821,53 @@ instruct signumD_reg(regD dst, regD zero, regD one, rRegP scratch, rFlagsReg cr) ins_pipe( pipe_slow ); %} +// --------------------------------------- +// For copySign use 0xE4 as writemask for vpternlog +// Desired Truth Table: A -> xmm0 bit, B -> xmm1 bit, C -> xmm2 bit +// C (xmm2) is set to 0x7FFFFFFF +// Wherever xmm2 is 0, we want to pick from B (sign) +// Wherever xmm2 is 1, we want to pick from A (src) +// +// A B C Result +// 0 0 0 0 +// 0 0 1 0 +// 0 1 0 1 +// 0 1 1 0 +// 1 0 0 0 +// 1 0 1 1 +// 1 1 0 1 +// 1 1 1 1 +// +// Result going from high bit to low bit is 0x11100100 = 0xe4 +// --------------------------------------- + +#ifdef _LP64 +instruct copySignF_reg(regF dst, regF src, regF tmp1, rRegI tmp2) %{ + match(Set dst (CopySignF dst src)); + effect(TEMP tmp1, TEMP tmp2); + format %{ "CopySignF $dst, $src\t! using $tmp1 and $tmp2 as TEMP" %} + ins_encode %{ + __ movl($tmp2$$Register, 0x7FFFFFFF); + __ movdl($tmp1$$XMMRegister, $tmp2$$Register); + __ vpternlogd($dst$$XMMRegister, 0xE4, $src$$XMMRegister, $tmp1$$XMMRegister, Assembler::AVX_128bit); + %} + ins_pipe( pipe_slow ); +%} + +instruct copySignD_imm(regD dst, regD src, regD tmp1, rRegL tmp2, immD zero) %{ + match(Set dst (CopySignD dst (Binary src zero))); + ins_cost(100); + effect(TEMP tmp1, TEMP tmp2); + format %{ "CopySignD $dst, $src\t! using $tmp1 and $tmp2 as TEMP" %} + ins_encode %{ + __ mov64($tmp2$$Register, 0x7FFFFFFFFFFFFFFF); + __ movq($tmp1$$XMMRegister, $tmp2$$Register); + __ vpternlogq($dst$$XMMRegister, 0xE4, $src$$XMMRegister, $tmp1$$XMMRegister, Assembler::AVX_128bit); + %} + ins_pipe( pipe_slow ); +%} +#endif // _LP64 + // --------------------------------- Sqrt -------------------------------------- instruct vsqrtF_reg(vec dst, vec src) %{ diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 900fedc1f78..2c0ecd0fe6b 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -452,7 +452,9 @@ void os::init_system_properties_values() { } } Arguments::set_java_home(buf); - set_boot_path('/', ':'); + if (!set_boot_path('/', ':')) { + vm_exit_during_initialization("Failed setting boot class path.", NULL); + } } // Where to look for native libraries. diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index fb653c762bc..1593a701e67 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -34,11 +34,15 @@ #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" +// controller names have to match the *_IDX indices +static const char* cg_controller_name[] = { "cpu", "cpuset", "cpuacct", "memory", "pids" }; + CgroupSubsystem* CgroupSubsystemFactory::create() { CgroupV1MemoryController* memory = NULL; CgroupV1Controller* cpuset = NULL; CgroupV1Controller* cpu = NULL; CgroupV1Controller* cpuacct = NULL; + CgroupV1Controller* pids = NULL; CgroupInfo cg_infos[CG_INFO_LENGTH]; u1 cg_type_flags = INVALID_CGROUPS_GENERIC; const char* proc_cgroups = "/proc/cgroups"; @@ -93,22 +97,29 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { assert(is_cgroup_v1(&cg_type_flags), "Cgroup v1 expected"); for (int i = 0; i < CG_INFO_LENGTH; i++) { CgroupInfo info = cg_infos[i]; - if (strcmp(info._name, "memory") == 0) { - memory = new CgroupV1MemoryController(info._root_mount_path, info._mount_path); - memory->set_subsystem_path(info._cgroup_path); - } else if (strcmp(info._name, "cpuset") == 0) { - cpuset = new CgroupV1Controller(info._root_mount_path, info._mount_path); - cpuset->set_subsystem_path(info._cgroup_path); - } else if (strcmp(info._name, "cpu") == 0) { - cpu = new CgroupV1Controller(info._root_mount_path, info._mount_path); - cpu->set_subsystem_path(info._cgroup_path); - } else if (strcmp(info._name, "cpuacct") == 0) { - cpuacct = new CgroupV1Controller(info._root_mount_path, info._mount_path); - cpuacct->set_subsystem_path(info._cgroup_path); + if (info._data_complete) { // pids controller might have incomplete data + if (strcmp(info._name, "memory") == 0) { + memory = new CgroupV1MemoryController(info._root_mount_path, info._mount_path); + memory->set_subsystem_path(info._cgroup_path); + } else if (strcmp(info._name, "cpuset") == 0) { + cpuset = new CgroupV1Controller(info._root_mount_path, info._mount_path); + cpuset->set_subsystem_path(info._cgroup_path); + } else if (strcmp(info._name, "cpu") == 0) { + cpu = new CgroupV1Controller(info._root_mount_path, info._mount_path); + cpu->set_subsystem_path(info._cgroup_path); + } else if (strcmp(info._name, "cpuacct") == 0) { + cpuacct = new CgroupV1Controller(info._root_mount_path, info._mount_path); + cpuacct->set_subsystem_path(info._cgroup_path); + } else if (strcmp(info._name, "pids") == 0) { + pids = new CgroupV1Controller(info._root_mount_path, info._mount_path); + pids->set_subsystem_path(info._cgroup_path); + } + } else { + log_debug(os, container)("CgroupInfo for %s not complete", cg_controller_name[i]); } } cleanup(cg_infos); - return new CgroupV1Subsystem(cpuset, cpu, cpuacct, memory); + return new CgroupV1Subsystem(cpuset, cpu, cpuacct, pids, memory); } bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, @@ -122,9 +133,10 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, char buf[MAXPATHLEN+1]; char *p; bool is_cgroupsV2; - // true iff all controllers, memory, cpu, cpuset, cpuacct are enabled + // true iff all required controllers, memory, cpu, cpuset, cpuacct are enabled // at the kernel level. - bool all_controllers_enabled; + // pids might not be enabled on older Linux distros (SLES 12.1, RHEL 7.1) + bool all_required_controllers_enabled; /* * Read /proc/cgroups so as to be able to distinguish cgroups v2 vs cgroups v1. @@ -136,10 +148,9 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, */ cgroups = fopen(proc_cgroups, "r"); if (cgroups == NULL) { - log_debug(os, container)("Can't open %s, %s", - proc_cgroups, os::strerror(errno)); - *flags = INVALID_CGROUPS_GENERIC; - return false; + log_debug(os, container)("Can't open %s, %s", proc_cgroups, os::strerror(errno)); + *flags = INVALID_CGROUPS_GENERIC; + return false; } while ((p = fgets(buf, MAXPATHLEN, cgroups)) != NULL) { @@ -167,19 +178,30 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, cg_infos[CPUACCT_IDX]._name = os::strdup(name); cg_infos[CPUACCT_IDX]._hierarchy_id = hierarchy_id; cg_infos[CPUACCT_IDX]._enabled = (enabled == 1); + } else if (strcmp(name, "pids") == 0) { + log_debug(os, container)("Detected optional pids controller entry in %s", proc_cgroups); + cg_infos[PIDS_IDX]._name = os::strdup(name); + cg_infos[PIDS_IDX]._hierarchy_id = hierarchy_id; + cg_infos[PIDS_IDX]._enabled = (enabled == 1); } } fclose(cgroups); is_cgroupsV2 = true; - all_controllers_enabled = true; + all_required_controllers_enabled = true; for (int i = 0; i < CG_INFO_LENGTH; i++) { - is_cgroupsV2 = is_cgroupsV2 && cg_infos[i]._hierarchy_id == 0; - all_controllers_enabled = all_controllers_enabled && cg_infos[i]._enabled; + // pids controller is optional. All other controllers are required + if (i != PIDS_IDX) { + is_cgroupsV2 = is_cgroupsV2 && cg_infos[i]._hierarchy_id == 0; + all_required_controllers_enabled = all_required_controllers_enabled && cg_infos[i]._enabled; + } + if (log_is_enabled(Debug, os, container) && !cg_infos[i]._enabled) { + log_debug(os, container)("controller %s is not enabled\n", cg_controller_name[i]); + } } - if (!all_controllers_enabled) { - // one or more controllers disabled, disable container support + if (!all_required_controllers_enabled) { + // one or more required controllers disabled, disable container support log_debug(os, container)("One or more required controllers disabled at kernel level."); cleanup(cg_infos); *flags = INVALID_CGROUPS_GENERIC; @@ -220,17 +242,21 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, while (!is_cgroupsV2 && (token = strsep(&controllers, ",")) != NULL) { if (strcmp(token, "memory") == 0) { - assert(hierarchy_id == cg_infos[MEMORY_IDX]._hierarchy_id, "/proc/cgroups and /proc/self/cgroup hierarchy mismatch"); + assert(hierarchy_id == cg_infos[MEMORY_IDX]._hierarchy_id, "/proc/cgroups and /proc/self/cgroup hierarchy mismatch for memory"); cg_infos[MEMORY_IDX]._cgroup_path = os::strdup(cgroup_path); } else if (strcmp(token, "cpuset") == 0) { - assert(hierarchy_id == cg_infos[CPUSET_IDX]._hierarchy_id, "/proc/cgroups and /proc/self/cgroup hierarchy mismatch"); + assert(hierarchy_id == cg_infos[CPUSET_IDX]._hierarchy_id, "/proc/cgroups and /proc/self/cgroup hierarchy mismatch for cpuset"); cg_infos[CPUSET_IDX]._cgroup_path = os::strdup(cgroup_path); } else if (strcmp(token, "cpu") == 0) { - assert(hierarchy_id == cg_infos[CPU_IDX]._hierarchy_id, "/proc/cgroups and /proc/self/cgroup hierarchy mismatch"); + assert(hierarchy_id == cg_infos[CPU_IDX]._hierarchy_id, "/proc/cgroups and /proc/self/cgroup hierarchy mismatch for cpu"); cg_infos[CPU_IDX]._cgroup_path = os::strdup(cgroup_path); } else if (strcmp(token, "cpuacct") == 0) { - assert(hierarchy_id == cg_infos[CPUACCT_IDX]._hierarchy_id, "/proc/cgroups and /proc/self/cgroup hierarchy mismatch"); + assert(hierarchy_id == cg_infos[CPUACCT_IDX]._hierarchy_id, "/proc/cgroups and /proc/self/cgroup hierarchy mismatch for cpuacc"); cg_infos[CPUACCT_IDX]._cgroup_path = os::strdup(cgroup_path); + } else if (strcmp(token, "pids") == 0) { + assert(hierarchy_id == cg_infos[PIDS_IDX]._hierarchy_id, "/proc/cgroups (%d) and /proc/self/cgroup (%d) hierarchy mismatch for pids", + cg_infos[PIDS_IDX]._hierarchy_id, hierarchy_id); + cg_infos[PIDS_IDX]._cgroup_path = os::strdup(cgroup_path); } } if (is_cgroupsV2) { @@ -281,13 +307,15 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, /* Cgroup v1 relevant info * - * Find the cgroup mount point for memory, cpuset, cpu, cpuacct + * Find the cgroup mount point for memory, cpuset, cpu, cpuacct, pids * * Example for docker: * 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory * * Example for host: * 34 28 0:29 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,memory + * + * 44 31 0:39 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:23 - cgroup cgroup rw,pids */ if (sscanf(p, "%*d %*d %*d:%*d %s %s %*[^-]- %s %*s %s", tmproot, tmpmount, tmp_fs_type, tmpcgroups) == 4) { if (strcmp("cgroup", tmp_fs_type) != 0) { @@ -333,6 +361,12 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, cg_infos[CPUACCT_IDX]._mount_path = os::strdup(tmpmount); cg_infos[CPUACCT_IDX]._root_mount_path = os::strdup(tmproot); cg_infos[CPUACCT_IDX]._data_complete = true; + } else if (strcmp(token, "pids") == 0) { + any_cgroup_mounts_found = true; + assert(cg_infos[PIDS_IDX]._mount_path == NULL, "stomping of _mount_path"); + cg_infos[PIDS_IDX]._mount_path = os::strdup(tmpmount); + cg_infos[PIDS_IDX]._root_mount_path = os::strdup(tmproot); + cg_infos[PIDS_IDX]._data_complete = true; } } } @@ -387,10 +421,13 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, *flags = INVALID_CGROUPS_V1; return false; } + if (log_is_enabled(Debug, os, container) && !cg_infos[PIDS_IDX]._data_complete) { + log_debug(os, container)("Optional cgroup v1 pids subsystem not found"); + // keep the other controller info, pids is optional + } // Cgroups v1 case, we have all the info we need. *flags = CGROUPS_V1; return true; - }; void CgroupSubsystemFactory::cleanup(CgroupInfo* cg_infos) { @@ -514,3 +551,22 @@ jlong CgroupSubsystem::memory_limit_in_bytes() { memory_limit->set_value(mem_limit, OSCONTAINER_CACHE_TIMEOUT); return mem_limit; } + +jlong CgroupSubsystem::limit_from_str(char* limit_str) { + if (limit_str == NULL) { + return OSCONTAINER_ERROR; + } + // Unlimited memory in cgroups is the literal string 'max' for + // some controllers, for example the pids controller. + if (strcmp("max", limit_str) == 0) { + os::free(limit_str); + return (jlong)-1; + } + julong limit; + if (sscanf(limit_str, JULONG_FORMAT, &limit) != 1) { + os::free(limit_str); + return OSCONTAINER_ERROR; + } + os::free(limit_str); + return (jlong)limit; +} diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 80c147c7576..c58c1ddf982 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -61,12 +61,13 @@ #define INVALID_CGROUPS_NO_MOUNT 5 #define INVALID_CGROUPS_GENERIC 6 -// Four controllers: cpu, cpuset, cpuacct, memory -#define CG_INFO_LENGTH 4 +// Five controllers: cpu, cpuset, cpuacct, memory, pids +#define CG_INFO_LENGTH 5 #define CPUSET_IDX 0 #define CPU_IDX 1 #define CPUACCT_IDX 2 #define MEMORY_IDX 3 +#define PIDS_IDX 4 typedef char * cptr; @@ -238,10 +239,12 @@ class CgroupSubsystem: public CHeapObj { public: jlong memory_limit_in_bytes(); int active_processor_count(); + jlong limit_from_str(char* limit_str); virtual int cpu_quota() = 0; virtual int cpu_period() = 0; virtual int cpu_shares() = 0; + virtual jlong pids_max() = 0; virtual jlong memory_usage_in_bytes() = 0; virtual jlong memory_and_swap_limit_in_bytes() = 0; virtual jlong memory_soft_limit_in_bytes() = 0; diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 5638213cd60..973d9f414ad 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -241,3 +241,28 @@ int CgroupV1Subsystem::cpu_shares() { return shares; } + + +char* CgroupV1Subsystem::pids_max_val() { + GET_CONTAINER_INFO_CPTR(cptr, _pids, "/pids.max", + "Maximum number of tasks is: %s", "%s %*d", pidsmax, 1024); + if (pidsmax == NULL) { + return NULL; + } + return os::strdup(pidsmax); +} + +/* pids_max + * + * Return the maximum number of tasks available to the process + * + * return: + * maximum number of tasks + * -1 for unlimited + * OSCONTAINER_ERROR for not supported + */ +jlong CgroupV1Subsystem::pids_max() { + if (_pids == NULL) return OSCONTAINER_ERROR; + char * pidsmax_str = pids_max_val(); + return limit_from_str(pidsmax_str); +} diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index 79a247a4562..8fba1b0843b 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -87,6 +87,8 @@ class CgroupV1Subsystem: public CgroupSubsystem { int cpu_shares(); + jlong pids_max(); + const char * container_type() { return "cgroupv1"; } @@ -101,15 +103,20 @@ class CgroupV1Subsystem: public CgroupSubsystem { CgroupV1Controller* _cpuset = NULL; CachingCgroupController* _cpu = NULL; CgroupV1Controller* _cpuacct = NULL; + CgroupV1Controller* _pids = NULL; + + char * pids_max_val(); public: CgroupV1Subsystem(CgroupV1Controller* cpuset, CgroupV1Controller* cpu, CgroupV1Controller* cpuacct, + CgroupV1Controller* pids, CgroupV1MemoryController* memory) { _cpuset = cpuset; _cpu = new CachingCgroupController(cpu); _cpuacct = cpuacct; + _pids = pids; _memory = new CachingCgroupController(memory); _unlimited_memory = (LONG_MAX / os::vm_page_size()) * os::vm_page_size(); } diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 66192f1d271..d1c00fd5db9 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Red Hat Inc. + * Copyright (c) 2020, 2021, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,24 +203,6 @@ jlong CgroupV2Subsystem::read_memory_limit_in_bytes() { return limit; } -jlong CgroupV2Subsystem::limit_from_str(char* limit_str) { - if (limit_str == NULL) { - return OSCONTAINER_ERROR; - } - // Unlimited memory in Cgroups V2 is the literal string 'max' - if (strcmp("max", limit_str) == 0) { - os::free(limit_str); - return (jlong)-1; - } - julong limit; - if (sscanf(limit_str, JULONG_FORMAT, &limit) != 1) { - os::free(limit_str); - return OSCONTAINER_ERROR; - } - os::free(limit_str); - return (jlong)limit; -} - char* CgroupV2Subsystem::mem_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.max", "Raw value for memory limit is: %s", "%s", mem_limit_str, 1024); @@ -244,3 +226,26 @@ char* CgroupV2Controller::construct_path(char* mount_path, char *cgroup_path) { return os::strdup(buf); } +char* CgroupV2Subsystem::pids_max_val() { + GET_CONTAINER_INFO_CPTR(cptr, _unified, "/pids.max", + "Maximum number of tasks is: %s", "%s %*d", pidsmax, 1024); + if (pidsmax == NULL) { + return NULL; + } + return os::strdup(pidsmax); +} + +/* pids_max + * + * Return the maximum number of tasks available to the process + * + * return: + * maximum number of tasks + * -1 for unlimited + * OSCONTAINER_ERROR for not supported + */ +jlong CgroupV2Subsystem::pids_max() { + char * pidsmax_str = pids_max_val(); + return limit_from_str(pidsmax_str); +} + diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index bd3380e22e3..5cc55009df6 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -60,7 +60,7 @@ class CgroupV2Subsystem: public CgroupSubsystem { char *mem_swp_limit_val(); char *mem_soft_limit_val(); char *cpu_quota_val(); - jlong limit_from_str(char* limit_str); + char *pids_max_val(); public: CgroupV2Subsystem(CgroupController * unified) { @@ -79,6 +79,8 @@ class CgroupV2Subsystem: public CgroupSubsystem { jlong memory_max_usage_in_bytes(); char * cpu_cpuset_cpus(); char * cpu_cpuset_memory_nodes(); + jlong pids_max(); + const char * container_type() { return "cgroupv2"; } diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index b89cfd676eb..d95f67427f4 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -129,3 +129,8 @@ int OSContainer::cpu_shares() { assert(cgroup_subsystem != NULL, "cgroup subsystem not available"); return cgroup_subsystem->cpu_shares(); } + +jlong OSContainer::pids_max() { + assert(cgroup_subsystem != NULL, "cgroup subsystem not available"); + return cgroup_subsystem->pids_max(); +} diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index 21801b7dc4b..8debcc1fe8a 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -62,6 +62,7 @@ class OSContainer: AllStatic { static int cpu_shares(); + static jlong pids_max(); }; inline bool OSContainer::is_containerized() { diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 6f7c8ec6e19..0cbf96a6b77 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2238,6 +2238,7 @@ void os::Linux::print_uptime_info(outputStream* st) { bool os::Linux::print_container_info(outputStream* st) { if (!OSContainer::is_containerized()) { + st->print_cr("container information not found."); return false; } @@ -2326,6 +2327,14 @@ bool os::Linux::print_container_info(outputStream* st) { st->print_cr("%s", j == OSCONTAINER_ERROR ? "not supported" : "unlimited"); } + j = OSContainer::OSContainer::pids_max(); + st->print("maximum number of tasks: "); + if (j > 0) { + st->print_cr(JLONG_FORMAT, j); + } else { + st->print_cr("%s", j == OSCONTAINER_ERROR ? "not supported" : "unlimited"); + } + return true; } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 8919afffb2c..a89947f32ed 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -31,6 +31,7 @@ #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "os_posix.inline.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/os.hpp" #include "runtime/perfMemory.hpp" @@ -1023,18 +1024,23 @@ static char* mmap_create_shared(size_t size) { return mapAddress; } -// release a named shared memory region +// release a named shared memory region that was mmap-ed. // static void unmap_shared(char* addr, size_t bytes) { -#if defined(_AIX) - // Do not rely on os::reserve_memory/os::release_memory to use mmap. - // Use os::reserve_memory/os::release_memory for PerfDisableSharedMem=1, mmap/munmap for PerfDisableSharedMem=0 - if (::munmap(addr, bytes) == -1) { - warning("perfmemory: munmap failed (%d)\n", errno); + int res; + if (MemTracker::tracking_level() > NMT_minimal) { + // Note: Tracker contains a ThreadCritical. + Tracker tkr(Tracker::release); + res = ::munmap(addr, bytes); + if (res == 0) { + tkr.record((address)addr, bytes); + } + } else { + res = ::munmap(addr, bytes); + } + if (res != 0) { + log_info(os)("os::release_memory failed (" PTR_FORMAT ", " SIZE_FORMAT ")", p2i(addr), bytes); } -#else - os::release_memory(addr, bytes); -#endif } // create the PerfData memory region in shared memory. @@ -1234,7 +1240,7 @@ void PerfMemory::create_memory_region(size_t size) { if (PrintMiscellaneous && Verbose) { warning("Reverting to non-shared PerfMemory region.\n"); } - PerfDisableSharedMem = true; + FLAG_SET_ERGO(PerfDisableSharedMem, true); _start = create_standard_memory(size); } } diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index d825c540f6e..600eb8882f9 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -29,6 +29,7 @@ #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "os_windows.inline.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/os.hpp" #include "runtime/perfMemory.hpp" @@ -1745,7 +1746,7 @@ void PerfMemory::create_memory_region(size_t size) { if (PrintMiscellaneous && Verbose) { warning("Reverting to non-shared PerfMemory region.\n"); } - PerfDisableSharedMem = true; + FLAG_SET_ERGO(PerfDisableSharedMem, true); _start = create_standard_memory(size); } } diff --git a/src/hotspot/share/asm/register.hpp b/src/hotspot/share/asm/register.hpp index dea7e9dd3d0..861c43b2c84 100644 --- a/src/hotspot/share/asm/register.hpp +++ b/src/hotspot/share/asm/register.hpp @@ -60,263 +60,17 @@ const type name = ((type)value) // Debugging support -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b -) { - assert( - a != b, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT "", p2i(a), p2i(b) - ); -} - - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c -) { - assert( - a != b && a != c - && b != c, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c) - ); -} - - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d -) { - assert( - a != b && a != c && a != d - && b != c && b != d - && c != d, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d) - ); -} - - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d, - AbstractRegister e -) { - assert( - a != b && a != c && a != d && a != e - && b != c && b != d && b != e - && c != d && c != e - && d != e, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d), p2i(e) - ); -} - - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d, - AbstractRegister e, - AbstractRegister f -) { - assert( - a != b && a != c && a != d && a != e && a != f - && b != c && b != d && b != e && b != f - && c != d && c != e && c != f - && d != e && d != f - && e != f, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT - ", f=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f) - ); -} - - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d, - AbstractRegister e, - AbstractRegister f, - AbstractRegister g -) { - assert( - a != b && a != c && a != d && a != e && a != f && a != g - && b != c && b != d && b != e && b != f && b != g - && c != d && c != e && c != f && c != g - && d != e && d != f && d != g - && e != f && e != g - && f != g, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT - ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g) - ); -} - - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d, - AbstractRegister e, - AbstractRegister f, - AbstractRegister g, - AbstractRegister h -) { - assert( - a != b && a != c && a != d && a != e && a != f && a != g && a != h - && b != c && b != d && b != e && b != f && b != g && b != h - && c != d && c != e && c != f && c != g && c != h - && d != e && d != f && d != g && d != h - && e != f && e != g && e != h - && f != g && f != h - && g != h, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT - ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h) - ); -} - - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d, - AbstractRegister e, - AbstractRegister f, - AbstractRegister g, - AbstractRegister h, - AbstractRegister i -) { - assert( - a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i - && b != c && b != d && b != e && b != f && b != g && b != h && b != i - && c != d && c != e && c != f && c != g && c != h && c != i - && d != e && d != f && d != g && d != h && d != i - && e != f && e != g && e != h && e != i - && f != g && f != h && f != i - && g != h && g != i - && h != i, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT - ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT - ", i=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i) - ); -} - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d, - AbstractRegister e, - AbstractRegister f, - AbstractRegister g, - AbstractRegister h, - AbstractRegister i, - AbstractRegister j -) { - assert( - a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j - && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j - && c != d && c != e && c != f && c != g && c != h && c != i && c != j - && d != e && d != f && d != g && d != h && d != i && d != j - && e != f && e != g && e != h && e != i && e != j - && f != g && f != h && f != i && f != j - && g != h && g != i && g != j - && h != i && h != j - && i != j, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT - ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT - ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j) - ); -} - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d, - AbstractRegister e, - AbstractRegister f, - AbstractRegister g, - AbstractRegister h, - AbstractRegister i, - AbstractRegister j, - AbstractRegister k -) { - assert( - a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k - && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k - && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k - && d != e && d != f && d != g && d != h && d != i && d != j && d !=k - && e != f && e != g && e != h && e != i && e != j && e !=k - && f != g && f != h && f != i && f != j && f !=k - && g != h && g != i && g != j && g !=k - && h != i && h != j && h !=k - && i != j && i !=k - && j !=k, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT - ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT - ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k) - ); -} - -inline void assert_different_registers( - AbstractRegister a, - AbstractRegister b, - AbstractRegister c, - AbstractRegister d, - AbstractRegister e, - AbstractRegister f, - AbstractRegister g, - AbstractRegister h, - AbstractRegister i, - AbstractRegister j, - AbstractRegister k, - AbstractRegister l -) { - assert( - a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k && a !=l - && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k && b !=l - && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k && c !=l - && d != e && d != f && d != g && d != h && d != i && d != j && d !=k && d !=l - && e != f && e != g && e != h && e != i && e != j && e !=k && e !=l - && f != g && f != h && f != i && f != j && f !=k && f !=l - && g != h && g != i && g != j && g !=k && g !=l - && h != i && h != j && h !=k && h !=l - && i != j && i !=k && i !=l - && j !=k && j !=l - && k !=l, - "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT - ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT - ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT - ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT - ", l=" INTPTR_FORMAT "", - p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k), p2i(l) - ); +template +inline void assert_different_registers(R first_register, Rx... more_registers) { +#ifdef ASSERT + const R regs[] = { first_register, more_registers... }; + // Verify there are no equal entries. + for (size_t i = 0; i < ARRAY_SIZE(regs) - 1; ++i) { + for (size_t j = i + 1; j < ARRAY_SIZE(regs); ++j) { + assert(regs[i] != regs[j], "Multiple uses of register: %s", regs[i]->name()); + } + } +#endif } #endif // SHARE_ASM_REGISTER_HPP diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 294761bc815..58b87a754a9 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -2509,10 +2509,10 @@ void LIRGenerator::do_UnsafeGet(UnsafeGet* x) { LIR_Opr offset = off.result(); #endif LIR_Address* addr = new LIR_Address(src.result(), offset, type); - if (type == T_LONG || type == T_DOUBLE) { - __ move(addr, result); + if (is_reference_type(type)) { + __ move_wide(addr, result); } else { - access_load(IN_NATIVE, type, LIR_OprFact::address(addr), result); + __ move(addr, result); } } } diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index f857d8f61ea..2e60287250c 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -161,9 +161,6 @@ ArchiveBuilder::ArchiveBuilder() : _rw_src_objs(), _ro_src_objs(), _src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE), - _num_instance_klasses(0), - _num_obj_array_klasses(0), - _num_type_array_klasses(0), _total_closed_heap_region_size(0), _total_open_heap_region_size(0), _estimated_metaspaceobj_bytes(0), @@ -222,14 +219,6 @@ 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_instance_klass()) { - _num_instance_klasses ++; - } else if (klass->is_objArray_klass()) { - _num_obj_array_klasses ++; - } else { - assert(klass->is_typeArray_klass(), "sanity"); - _num_type_array_klasses ++; - } } // See RunTimeClassInfo::get_for() _estimated_metaspaceobj_bytes += align_up(BytesPerWord, SharedSpaceObjectAlignment); @@ -258,12 +247,6 @@ void ArchiveBuilder::gather_klasses_and_symbols() { #endif doit.finish(); - 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)(" 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()); - if (DumpSharedSpaces) { // To ensure deterministic contents in the static archive, we need to ensure that // we iterate the MetaspaceObjs in a deterministic order. It doesn't matter where @@ -742,31 +725,85 @@ void ArchiveBuilder::relocate_vm_classes() { } 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; + int num_unlinked_klasses = 0; + int num_unregistered_klasses = 0; + int num_obj_array_klasses = 0; + int num_type_array_klasses = 0; + for (int i = 0; i < klasses()->length(); i++) { + const char* type; + const char* unlinked = ""; + const char* hidden = ""; Klass* k = klasses()->at(i); k->remove_java_mirror(); if (k->is_objArray_klass()) { // InstanceKlass and TypeArrayKlass will in turn call remove_unshareable_info // on their array classes. + num_obj_array_klasses ++; + type = "array"; } else if (k->is_typeArray_klass()) { + num_type_array_klasses ++; + type = "array"; k->remove_unshareable_info(); } else { assert(k->is_instance_klass(), " must be"); + num_instance_klasses ++; InstanceKlass* ik = InstanceKlass::cast(k); if (DynamicDumpSharedSpaces) { // For static dump, class loader type are already set. ik->assign_class_loader_type(); } + if (ik->is_shared_boot_class()) { + type = "boot"; + num_boot_klasses ++; + } else if (ik->is_shared_platform_class()) { + type = "plat"; + num_platform_klasses ++; + } else if (ik->is_shared_app_class()) { + type = "app"; + num_app_klasses ++; + } else { + assert(ik->is_shared_unregistered_class(), "must be"); + type = "unreg"; + num_unregistered_klasses ++; + } + + if (!ik->is_linked()) { + num_unlinked_klasses ++; + unlinked = " ** unlinked"; + } + + if (ik->is_hidden()) { + num_hidden_klasses ++; + hidden = " ** hidden"; + } 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[%4d] = " PTR_FORMAT " %s", i, p2i(to_requested(ik)), ik->external_name()); - } + if (log_is_enabled(Debug, cds, class)) { + ResourceMark rm; + log_debug(cds, class)("klasses[%5d] = " PTR_FORMAT " %-5s %s%s%s", i, p2i(to_requested(k)), type, k->external_name(), hidden, unlinked); } } + + 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)(" 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()); } 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 58067f15dfc..664f33b0822 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -210,9 +210,6 @@ class ArchiveBuilder : public StackObj { GrowableArray* _special_refs; // statistics - int _num_instance_klasses; - int _num_obj_array_klasses; - int _num_type_array_klasses; DumpAllocStats _alloc_stats; size_t _total_closed_heap_region_size; size_t _total_open_heap_region_size; diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index beabd780c04..42531d6c752 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -330,23 +330,24 @@ void ReadClosure::do_region(u_char* start, size_t size) { } } -fileStream* ClassListWriter::_classlist_file = NULL; - void ArchiveUtils::log_to_classlist(BootstrapInfo* bootstrap_specifier, TRAPS) { if (ClassListWriter::is_enabled()) { if (SystemDictionaryShared::is_supported_invokedynamic(bootstrap_specifier)) { - ResourceMark rm(THREAD); const constantPoolHandle& pool = bootstrap_specifier->pool(); - int pool_index = bootstrap_specifier->bss_index(); - ClassListWriter w; - w.stream()->print("%s %s", LAMBDA_PROXY_TAG, pool->pool_holder()->name()->as_C_string()); - CDSIndyInfo cii; - ClassListParser::populate_cds_indy_info(pool, pool_index, &cii, CHECK); - GrowableArray* indy_items = cii.items(); - for (int i = 0; i < indy_items->length(); i++) { - w.stream()->print(" %s", indy_items->at(i)); + if (SystemDictionaryShared::is_builtin_loader(pool->pool_holder()->class_loader_data())) { + // Currently lambda proxy classes are supported only for the built-in loaders. + ResourceMark rm(THREAD); + int pool_index = bootstrap_specifier->bss_index(); + ClassListWriter w; + w.stream()->print("%s %s", LAMBDA_PROXY_TAG, pool->pool_holder()->name()->as_C_string()); + CDSIndyInfo cii; + ClassListParser::populate_cds_indy_info(pool, pool_index, &cii, CHECK); + GrowableArray* indy_items = cii.items(); + for (int i = 0; i < indy_items->length(); i++) { + w.stream()->print(" %s", indy_items->at(i)); + } + w.stream()->cr(); } - w.stream()->cr(); } } } diff --git a/src/hotspot/share/cds/classListWriter.cpp b/src/hotspot/share/cds/classListWriter.cpp new file mode 100644 index 00000000000..45421457a63 --- /dev/null +++ b/src/hotspot/share/cds/classListWriter.cpp @@ -0,0 +1,175 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "cds/classListWriter.hpp" +#include "classfile/classFileStream.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/classLoaderData.hpp" +#include "classfile/moduleEntry.hpp" +#include "classfile/systemDictionaryShared.hpp" +#include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" +#include "runtime/mutexLocker.hpp" + +fileStream* ClassListWriter::_classlist_file = NULL; + +void ClassListWriter::init() { + // For -XX:DumpLoadedClassList= option + if (DumpLoadedClassList != NULL) { + const char* list_name = make_log_name(DumpLoadedClassList, NULL); + _classlist_file = new(ResourceObj::C_HEAP, mtInternal) + fileStream(list_name); + _classlist_file->print_cr("# NOTE: Do not modify this file."); + _classlist_file->print_cr("#"); + _classlist_file->print_cr("# This file is generated via the -XX:DumpLoadedClassList= option"); + _classlist_file->print_cr("# and is used at CDS archive dump time (see -Xshare:dump)."); + _classlist_file->print_cr("#"); + FREE_C_HEAP_ARRAY(char, list_name); + } +} + +void ClassListWriter::write(const InstanceKlass* k, const ClassFileStream* cfs) { + assert(is_enabled(), "must be"); + + if (!ClassLoader::has_jrt_entry()) { + warning("DumpLoadedClassList and CDS are not supported in exploded build"); + DumpLoadedClassList = NULL; + return; + } + + ClassListWriter w; + write_to_stream(k, w.stream(), cfs); +} + +class ClassListWriter::IDTable : public ResourceHashtable< + const InstanceKlass*, int, + 15889, // prime number + ResourceObj::C_HEAP> {}; + +ClassListWriter::IDTable* ClassListWriter::_id_table = NULL; +int ClassListWriter::_total_ids = 0; + +int ClassListWriter::get_id(const InstanceKlass* k) { + assert_locked(); + if (_id_table == NULL) { + _id_table = new (ResourceObj::C_HEAP, mtClass)IDTable(); + } + bool created; + int* v = _id_table->put_if_absent(k, &created); + if (created) { + *v = _total_ids++; + } + return *v; +} + +bool ClassListWriter::has_id(const InstanceKlass* k) { + assert_locked(); + if (_id_table != NULL) { + return _id_table->get(k) != NULL; + } else { + return false; + } +} + +void ClassListWriter::handle_class_unloading(const InstanceKlass* klass) { + assert_locked(); + if (_id_table != NULL) { + _id_table->remove(klass); + } +} + +void ClassListWriter::write_to_stream(const InstanceKlass* k, outputStream* stream, const ClassFileStream* cfs) { + assert_locked(); + ClassLoaderData* loader_data = k->class_loader_data(); + + if (!SystemDictionaryShared::is_builtin_loader(loader_data)) { + if (cfs == NULL || strncmp(cfs->source(), "file:", 5) != 0) { + return; + } + if (!SystemDictionaryShared::add_unregistered_class(Thread::current(), (InstanceKlass*)k)) { + return; + } + } + + + { + InstanceKlass* super = k->java_super(); + if (super != NULL && !has_id(super)) { + return; + } + + Array* interfaces = k->local_interfaces(); + int len = interfaces->length(); + for (int i = 0; i < len; i++) { + InstanceKlass* intf = interfaces->at(i); + if (!has_id(intf)) { + return; + } + } + } + + if (k->is_hidden()) { + return; + } + + if (k->module()->is_patched()) { + return; + } + + ResourceMark rm; + stream->print("%s id: %d", k->name()->as_C_string(), get_id(k)); + if (!SystemDictionaryShared::is_builtin_loader(loader_data)) { + InstanceKlass* super = k->java_super(); + assert(super != NULL, "must be"); + stream->print(" super: %d", get_id(super)); + + Array* interfaces = k->local_interfaces(); + int len = interfaces->length(); + if (len > 0) { + stream->print(" interfaces:"); + for (int i = 0; i < len; i++) { + InstanceKlass* intf = interfaces->at(i); + stream->print(" %d", get_id(intf)); + } + } + +#ifdef _WINDOWS + // "file:/C:/dir/foo.jar" -> "C:/dir/foo.jar" + stream->print(" source: %s", cfs->source() + 6); +#else + // "file:/dir/foo.jar" -> "/dir/foo.jar" + stream->print(" source: %s", cfs->source() + 5); +#endif + } + + stream->cr(); + stream->flush(); +} + +void ClassListWriter::delete_classlist() { + if (_classlist_file != NULL) { + delete _classlist_file; + } +} diff --git a/src/hotspot/share/cds/classListWriter.hpp b/src/hotspot/share/cds/classListWriter.hpp index 6ece57ef429..db7265b1209 100644 --- a/src/hotspot/share/cds/classListWriter.hpp +++ b/src/hotspot/share/cds/classListWriter.hpp @@ -29,54 +29,44 @@ #include "runtime/thread.hpp" #include "utilities/ostream.hpp" -class ClassListWriter { - friend const char* make_log_name(const char* log_name, const char* force_directory); +class ClassFileStream; +class ClassListWriter { +#if INCLUDE_CDS + class IDTable; static fileStream* _classlist_file; + static IDTable* _id_table; + static int _total_ids; MutexLocker _locker; + + static int get_id(const InstanceKlass* k); + static bool has_id(const InstanceKlass* k); + static void assert_locked() { assert_lock_strong(ClassListFile_lock); } public: -#if INCLUDE_CDS ClassListWriter() : _locker(Thread::current(), ClassListFile_lock, Mutex::_no_safepoint_check_flag) {} -#else - ClassListWriter() : _locker(Thread::current(), NULL, Mutex::_no_safepoint_check_flag) {} -#endif outputStream* stream() { return _classlist_file; } + void handle_class_unloading(const InstanceKlass* klass); + static bool is_enabled() { -#if INCLUDE_CDS return _classlist_file != NULL && _classlist_file->is_open(); + } + #else +public: + static bool is_enabled() { return false; -#endif } +#endif // INCLUDE_CDS - static void init() { -#if INCLUDE_CDS - // For -XX:DumpLoadedClassList= option - if (DumpLoadedClassList != NULL) { - const char* list_name = make_log_name(DumpLoadedClassList, NULL); - _classlist_file = new(ResourceObj::C_HEAP, mtInternal) - fileStream(list_name); - _classlist_file->print_cr("# NOTE: Do not modify this file."); - _classlist_file->print_cr("#"); - _classlist_file->print_cr("# This file is generated via the -XX:DumpLoadedClassList= option"); - _classlist_file->print_cr("# and is used at CDS archive dump time (see -Xshare:dump)."); - _classlist_file->print_cr("#"); - FREE_C_HEAP_ARRAY(char, list_name); - } -#endif - } - static void delete_classlist() { -#if INCLUDE_CDS - if (_classlist_file != NULL) { - delete _classlist_file; - } -#endif - } + static void init() NOT_CDS_RETURN; + static void write(const InstanceKlass* k, const ClassFileStream* cfs) NOT_CDS_RETURN; + static void write_to_stream(const InstanceKlass* k, outputStream* stream, const ClassFileStream* cfs = NULL) NOT_CDS_RETURN; + static void delete_classlist() NOT_CDS_RETURN; }; #endif // SHARE_CDS_CLASSLISTWRITER_HPP diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 4f9d6210a27..0ef1424db45 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -1027,7 +1027,7 @@ oop HeapShared::archive_reachable_objects_from(int level, // class_data will be restored explicitly at run time. guarantee(orig_obj == SystemDictionary::java_platform_loader() || orig_obj == SystemDictionary::java_system_loader() || - java_lang_ClassLoader::loader_data_raw(orig_obj) == NULL, "must be"); + java_lang_ClassLoader::loader_data(orig_obj) == NULL, "must be"); java_lang_ClassLoader::release_set_loader_data(archived_obj, NULL); } } diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 2c73ba06e26..341ac638306 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -26,6 +26,7 @@ #include "jvm_io.h" #include "cds/archiveBuilder.hpp" #include "cds/cdsProtectionDomain.hpp" +#include "cds/classListWriter.hpp" #include "cds/classListParser.hpp" #include "cds/cppVtables.hpp" #include "cds/dumpAllocStats.hpp" @@ -77,6 +78,7 @@ #include "utilities/bitMap.inline.hpp" #include "utilities/ostream.hpp" #include "utilities/defaultStream.hpp" +#include "utilities/resourceHash.hpp" #if INCLUDE_G1GC #include "gc/g1/g1CollectedHeap.inline.hpp" #endif @@ -150,16 +152,43 @@ static bool shared_base_valid(char* shared_base) { } class DumpClassListCLDClosure : public CLDClosure { + static const int INITIAL_TABLE_SIZE = 1987; + static const int MAX_TABLE_SIZE = 61333; + fileStream *_stream; + ResizeableResourceHashtable _dumped_classes; + + void dump(InstanceKlass* ik) { + bool created; + _dumped_classes.put_if_absent(ik, &created); + if (!created) { + return; + } + if (_dumped_classes.maybe_grow(MAX_TABLE_SIZE)) { + log_info(cds, hashtables)("Expanded _dumped_classes table to %d", _dumped_classes.table_size()); + } + if (ik->java_super()) { + dump(ik->java_super()); + } + Array* interfaces = ik->local_interfaces(); + int len = interfaces->length(); + for (int i = 0; i < len; i++) { + dump(interfaces->at(i)); + } + ClassListWriter::write_to_stream(ik, _stream); + } + public: - DumpClassListCLDClosure(fileStream* f) : CLDClosure() { _stream = f; } + DumpClassListCLDClosure(fileStream* f) + : CLDClosure(), _dumped_classes(INITIAL_TABLE_SIZE) { + _stream = f; + } + void do_cld(ClassLoaderData* cld) { for (Klass* klass = cld->klasses(); klass != NULL; klass = klass->next_link()) { if (klass->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(klass); - if (ik->is_shareable()) { - _stream->print_cr("%s", ik->name()->as_C_string()); - } + dump(InstanceKlass::cast(klass)); } } } @@ -169,6 +198,7 @@ void MetaspaceShared::dump_loaded_classes(const char* file_name, TRAPS) { fileStream stream(file_name, "w"); if (stream.is_open()) { MutexLocker lock(ClassLoaderDataGraph_lock); + MutexLocker lock2(ClassListFile_lock, Mutex::_no_safepoint_check_flag); DumpClassListCLDClosure collect_classes(&stream); ClassLoaderDataGraph::loaded_cld_do(&collect_classes); } else { diff --git a/src/hotspot/share/ci/ciMethod.cpp b/src/hotspot/share/ci/ciMethod.cpp index 63688b288e3..2c0a8da0f05 100644 --- a/src/hotspot/share/ci/ciMethod.cpp +++ b/src/hotspot/share/ci/ciMethod.cpp @@ -914,17 +914,16 @@ ciKlass* ciMethod::get_declared_method_holder_at_bci(int bci) { // invocation counts in methods. int ciMethod::scale_count(int count, float prof_factor) { if (count > 0 && method_data() != NULL) { - int counter_life; + int counter_life = method_data()->invocation_count(); int method_life = interpreter_invocation_count(); - // In tiered the MDO's life is measured directly, so just use the snapshotted counters - counter_life = MAX2(method_data()->invocation_count(), method_data()->backedge_count()); - - // counter_life due to backedge_counter could be > method_life - if (counter_life > method_life) - counter_life = method_life; - if (0 < counter_life && counter_life <= method_life) { + if (method_life < counter_life) { // may happen because of the snapshot timing + method_life = counter_life; + } + if (counter_life > 0) { count = (int)((double)count * prof_factor * method_life / counter_life + 0.5); count = (count > 0) ? count : 1; + } else { + count = 1; } } return count; diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 3a319649d8e..165841e0c8c 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -1428,14 +1428,6 @@ void java_lang_Class::fixup_module_field(Klass* k, Handle module) { java_lang_Class::set_module(k->java_mirror(), module()); } -int java_lang_Class::oop_size(oop java_class) { - assert(_oop_size_offset != 0, "must be set"); - int size = java_class->int_field(_oop_size_offset); - assert(size > 0, "Oop size must be greater than zero, not %d", size); - return size; -} - - void java_lang_Class::set_oop_size(HeapWord* java_class, int size) { assert(_oop_size_offset != 0, "must be set"); assert(size > 0, "Oop size must be greater than zero, not %d", size); @@ -1447,11 +1439,6 @@ int java_lang_Class::static_oop_field_count(oop java_class) { return java_class->int_field(_static_oop_field_count_offset); } -int java_lang_Class::static_oop_field_count_raw(oop java_class) { - assert(_static_oop_field_count_offset != 0, "must be set"); - return java_class->int_field_raw(_static_oop_field_count_offset); -} - void java_lang_Class::set_static_oop_field_count(oop java_class, int size) { assert(_static_oop_field_count_offset != 0, "must be set"); java_class->int_field_put(_static_oop_field_count_offset, size); @@ -1578,16 +1565,6 @@ oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, Basic return java_class; } - -Klass* java_lang_Class::as_Klass_raw(oop java_class) { - //%note memory_2 - assert(java_lang_Class::is_instance(java_class), "must be a Class object"); - Klass* k = ((Klass*)java_class->metadata_field_raw(_klass_offset)); - assert(k == NULL || k->is_klass(), "type check"); - return k; -} - - void java_lang_Class::set_klass(oop java_class, Klass* klass) { assert(java_lang_Class::is_instance(java_class), "must be a Class object"); java_class->metadata_field_put(_klass_offset, klass); @@ -2746,6 +2723,51 @@ void java_lang_Throwable::get_stack_trace_elements(Handle throwable, } } +Handle java_lang_Throwable::get_cause_with_stack_trace(Handle throwable, TRAPS) { + // Call to JVM to fill in the stack trace and clear declaringClassObject to + // not keep classes alive in the stack trace. + // call this: public StackTraceElement[] getStackTrace() + assert(throwable.not_null(), "shouldn't be"); + + JavaValue result(T_ARRAY); + JavaCalls::call_virtual(&result, throwable, + vmClasses::Throwable_klass(), + vmSymbols::getStackTrace_name(), + vmSymbols::getStackTrace_signature(), + CHECK_NH); + Handle stack_trace(THREAD, result.get_oop()); + assert(stack_trace->is_objArray(), "Should be an array"); + + // Throw ExceptionInInitializerError as the cause with this exception in + // the message and stack trace. + + // Now create the message with the original exception and thread name. + Symbol* message = java_lang_Throwable::detail_message(throwable()); + ResourceMark rm(THREAD); + stringStream st; + st.print("Exception %s%s ", throwable()->klass()->name()->as_klass_external_name(), + message == nullptr ? "" : ":"); + if (message == NULL) { + st.print("[in thread \"%s\"]", THREAD->name()); + } else { + st.print("%s [in thread \"%s\"]", message->as_C_string(), THREAD->name()); + } + + Symbol* exception_name = vmSymbols::java_lang_ExceptionInInitializerError(); + Handle h_cause = Exceptions::new_exception(THREAD, exception_name, st.as_string()); + + // If new_exception returns a different exception while creating the exception, return null. + if (h_cause->klass()->name() != exception_name) { + log_info(class, init)("Exception thrown while saving initialization exception %s", + h_cause->klass()->external_name()); + return Handle(); + } + java_lang_Throwable::set_stacktrace(h_cause(), stack_trace()); + // Clear backtrace because the stacktrace should be used instead. + set_backtrace(h_cause(), NULL); + return h_cause; +} + bool java_lang_Throwable::get_top_method_and_bci(oop throwable, Method** method, int* bci) { JavaThread* current = JavaThread::current(); objArrayHandle result(current, objArrayOop(backtrace(throwable))); @@ -4342,10 +4364,10 @@ ClassLoaderData* java_lang_ClassLoader::loader_data_acquire(oop loader) { return HeapAccess::load_at(loader, _loader_data_offset); } -ClassLoaderData* java_lang_ClassLoader::loader_data_raw(oop loader) { +ClassLoaderData* java_lang_ClassLoader::loader_data(oop loader) { assert(loader != NULL, "loader must not be NULL"); assert(oopDesc::is_oop(loader), "loader must be oop"); - return RawAccess<>::load_at(loader, _loader_data_offset); + return HeapAccess<>::load_at(loader, _loader_data_offset); } void java_lang_ClassLoader::release_set_loader_data(oop loader, ClassLoaderData* new_data) { diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 748dcb99e98..5c09f786c8d 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -329,7 +329,6 @@ class java_lang_Class : AllStatic { // Conversion static Klass* as_Klass(oop java_class); - static Klass* as_Klass_raw(oop java_class); static void set_klass(oop java_class, Klass* klass); static BasicType as_BasicType(oop java_class, Klass** reference_klass = NULL); static Symbol* as_signature(oop java_class, bool intern_if_not_found); @@ -381,10 +380,8 @@ class java_lang_Class : AllStatic { static void set_source_file(oop java_class, oop source_file); static int oop_size(oop java_class); - static int oop_size_raw(oop java_class); static void set_oop_size(HeapWord* java_class, int size); static int static_oop_field_count(oop java_class); - static int static_oop_field_count_raw(oop java_class); static void set_static_oop_field_count(oop java_class, int size); static GrowableArray* fixup_mirror_list() { @@ -579,6 +576,10 @@ class java_lang_Throwable: AllStatic { static void fill_in_stack_trace(Handle throwable, const methodHandle& method = methodHandle()); // Programmatic access to stack trace static void get_stack_trace_elements(Handle throwable, objArrayHandle stack_trace, TRAPS); + + // For recreating class initialization error exceptions. + static Handle get_cause_with_stack_trace(Handle throwable, TRAPS); + // Printing static void print(oop throwable, outputStream* st); static void print_stack_trace(Handle throwable, outputStream* st); @@ -1367,7 +1368,7 @@ class java_lang_ClassLoader : AllStatic { static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; static ClassLoaderData* loader_data_acquire(oop loader); - static ClassLoaderData* loader_data_raw(oop loader); + static ClassLoaderData* loader_data(oop loader); static void release_set_loader_data(oop loader, ClassLoaderData* new_data); static oop parent(oop loader); diff --git a/src/hotspot/share/classfile/javaClasses.inline.hpp b/src/hotspot/share/classfile/javaClasses.inline.hpp index ef734494023..0dfb64aafc8 100644 --- a/src/hotspot/share/classfile/javaClasses.inline.hpp +++ b/src/hotspot/share/classfile/javaClasses.inline.hpp @@ -279,9 +279,9 @@ inline bool java_lang_Class::is_secondary_mirror(oop java_class) { } } -inline int java_lang_Class::oop_size_raw(oop java_class) { +inline int java_lang_Class::oop_size(oop java_class) { assert(_oop_size_offset != 0, "must be set"); - int size = java_class->int_field_raw(_oop_size_offset); + int size = java_class->int_field(_oop_size_offset); assert(size > 0, "Oop size must be greater than zero, not %d", size); return size; } diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index abe7d5104a7..91f943cd58a 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1706,6 +1706,8 @@ bool SystemDictionary::do_unloading(GCTimer* gc_timer) { } else { assert(_pd_cache_table->number_of_entries() == 0, "should be empty"); } + + InstanceKlass::clean_initialization_error_table(); } return unloading_occurred; diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 083fcf53d88..a28b5254533 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -26,6 +26,7 @@ #include "cds/archiveUtils.hpp" #include "cds/archiveBuilder.hpp" #include "cds/classListParser.hpp" +#include "cds/classListWriter.hpp" #include "cds/dynamicArchive.hpp" #include "cds/filemap.hpp" #include "cds/heapShared.hpp" @@ -332,7 +333,7 @@ bool SystemDictionaryShared::check_for_exclusion_impl(InstanceKlass* k) { return false; // false == k should NOT be excluded } -bool SystemDictionaryShared::is_sharing_possible(ClassLoaderData* loader_data) { +bool SystemDictionaryShared::is_builtin_loader(ClassLoaderData* loader_data) { oop class_loader = loader_data->class_loader(); return (class_loader == NULL || SystemDictionary::is_system_class_loader(class_loader) || @@ -433,7 +434,7 @@ bool SystemDictionaryShared::add_unregistered_class(Thread* current, InstanceKla // We don't allow duplicated unregistered classes with the same name. // We only archive the first class with that name that succeeds putting // itself into the table. - Arguments::assert_is_dumping_archive(); + assert(Arguments::is_dumping_archive() || ClassListWriter::is_enabled(), "sanity"); MutexLocker ml(current, UnregisteredClassesTable_lock); Symbol* name = klass->name(); if (_unregistered_classes_table == NULL) { @@ -547,7 +548,9 @@ void SystemDictionaryShared::remove_dumptime_info(InstanceKlass* k) { } void SystemDictionaryShared::handle_class_unloading(InstanceKlass* klass) { - remove_dumptime_info(klass); + if (Arguments::is_dumping_archive()) { + remove_dumptime_info(klass); + } if (_unregistered_classes_table != NULL) { // Remove the class from _unregistered_classes_table: keep the entry but @@ -559,6 +562,11 @@ void SystemDictionaryShared::handle_class_unloading(InstanceKlass* klass) { *v = NULL; } } + + if (ClassListWriter::is_enabled()) { + ClassListWriter cw; + cw.handle_class_unloading((const InstanceKlass*)klass); + } } // Check if a class or any of its supertypes has been redefined. diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index ac041f92561..e08bd5bede1 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -206,8 +206,7 @@ class SystemDictionaryShared: public SystemDictionary { static void allocate_shared_data_arrays(int size, TRAPS); - // Check if sharing is supported for the class loader. - static bool is_sharing_possible(ClassLoaderData* loader_data); + static bool is_builtin_loader(ClassLoaderData* loader_data); static bool add_unregistered_class_for_static_archive(Thread* current, InstanceKlass* k); static InstanceKlass* lookup_super_for_unregistered_class(Symbol* class_name, diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index afac636ba85..00c696c909c 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -372,6 +372,7 @@ template(class_initializer_name, "") \ template(println_name, "println") \ template(printStackTrace_name, "printStackTrace") \ + template(getStackTrace_name, "getStackTrace") \ template(main_name, "main") \ template(name_name, "name") \ template(priority_name, "priority") \ @@ -601,7 +602,9 @@ template(int_String_signature, "(I)Ljava/lang/String;") \ template(boolean_boolean_int_signature, "(ZZ)I") \ template(big_integer_shift_worker_signature, "([I[IIII)V") \ - template(reflect_method_signature, "Ljava/lang/reflect/Method;") \ + template(reflect_method_signature, "Ljava/lang/reflect/Method;") \ + template(getStackTrace_signature, "()[Ljava/lang/StackTraceElement;") \ + \ /* signature symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \ \ diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp index 0ed0c27330d..0eb6c58fb42 100644 --- a/src/hotspot/share/code/dependencies.cpp +++ b/src/hotspot/share/code/dependencies.cpp @@ -239,7 +239,9 @@ void Dependencies::assert_common_2(DepType dept, } } } else { - if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) { + bool dep_seen_x0 = note_dep_seen(dept, x0); // records x0 for future queries + bool dep_seen_x1 = note_dep_seen(dept, x1); // records x1 for future queries + if (dep_seen_x0 && dep_seen_x1) { // look in this bucket for redundant assertions const int stride = 2; for (int i = deps->length(); (i -= stride) >= 0; ) { @@ -266,7 +268,10 @@ void Dependencies::assert_common_4(DepType dept, GrowableArray* deps = _deps[dept]; // see if the same (or a similar) dep is already recorded - if (note_dep_seen(dept, x1) && note_dep_seen(dept, x2) && note_dep_seen(dept, x3)) { + bool dep_seen_x1 = note_dep_seen(dept, x1); // records x1 for future queries + bool dep_seen_x2 = note_dep_seen(dept, x2); // records x2 for future queries + bool dep_seen_x3 = note_dep_seen(dept, x3); // records x3 for future queries + if (dep_seen_x1 && dep_seen_x2 && dep_seen_x3) { // look in this bucket for redundant assertions const int stride = 4; for (int i = deps->length(); (i -= stride) >= 0; ) { @@ -339,7 +344,9 @@ void Dependencies::assert_common_2(DepType dept, } } } else { - if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) { + bool dep_seen_x0 = note_dep_seen(dept, x0); // records x0 for future queries + bool dep_seen_x1 = note_dep_seen(dept, x1); // records x1 for future queries + if (dep_seen_x0 && dep_seen_x1) { // look in this bucket for redundant assertions const int stride = 2; for (int i = deps->length(); (i -= stride) >= 0; ) { diff --git a/src/hotspot/share/compiler/methodMatcher.cpp b/src/hotspot/share/compiler/methodMatcher.cpp index 6d6af709034..50cae0430d7 100644 --- a/src/hotspot/share/compiler/methodMatcher.cpp +++ b/src/hotspot/share/compiler/methodMatcher.cpp @@ -115,7 +115,7 @@ bool MethodMatcher::canonicalize(char * line, const char *& error_msg) { } if (*lp == '/') { - error_msg = "Method pattern uses '/' together with '::'"; + error_msg = "Method pattern uses '/' together with '::' (tips: replace '/' with '+' for hidden classes)"; return false; } } diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index 5501ab601cd..b5ddd07b9fa 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -248,11 +248,16 @@ HeapWord* G1Allocator::survivor_attempt_allocation(size_t min_word_size, actual_word_size); if (result == NULL && !survivor_is_full()) { MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag); - result = survivor_gc_alloc_region(node_index)->attempt_allocation_locked(min_word_size, - desired_word_size, - actual_word_size); - if (result == NULL) { - set_survivor_full(); + // Multiple threads may have queued at the FreeList_lock above after checking whether there + // actually is still memory available. Redo the check under the lock to avoid unnecessary work; + // the memory may have been used up as the threads waited to acquire the lock. + if (!survivor_is_full()) { + result = survivor_gc_alloc_region(node_index)->attempt_allocation_locked(min_word_size, + desired_word_size, + actual_word_size); + if (result == NULL) { + set_survivor_full(); + } } } if (result != NULL) { @@ -272,11 +277,16 @@ HeapWord* G1Allocator::old_attempt_allocation(size_t min_word_size, actual_word_size); if (result == NULL && !old_is_full()) { MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag); - result = old_gc_alloc_region()->attempt_allocation_locked(min_word_size, - desired_word_size, - actual_word_size); - if (result == NULL) { - set_old_full(); + // Multiple threads may have queued at the FreeList_lock above after checking whether there + // actually is still memory available. Redo the check under the lock to avoid unnecessary work; + // the memory may have been used up as the threads waited to acquire the lock. + if (!old_is_full()) { + result = old_gc_alloc_region()->attempt_allocation_locked(min_word_size, + desired_word_size, + actual_word_size); + if (result == NULL) { + set_old_full(); + } } } return result; diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index e09bd750b5d..5f78a40e36d 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -235,7 +235,6 @@ HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr_slow(HeapWord "next_boundary is beyond the end of the covered region " " next_boundary " PTR_FORMAT " _array->_end " PTR_FORMAT, p2i(next_boundary), p2i(_bot->_reserved.end())); - if (addr >= _hr->top()) return _hr->top(); while (next_boundary < addr) { while (n <= next_boundary) { q = n; diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index 4af48441354..47b90985b78 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -132,7 +132,6 @@ inline HeapWord* G1BlockOffsetTablePart::block_at_or_preceding(const void* addr) inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n, const void* addr) const { - if (addr >= _hr->top()) return _hr->top(); while (n <= addr) { q = n; oop obj = cast_to_oop(q); diff --git a/src/hotspot/share/gc/g1/g1CardSet.cpp b/src/hotspot/share/gc/g1/g1CardSet.cpp index 108d0aa4294..caa9124bd6f 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.cpp +++ b/src/hotspot/share/gc/g1/g1CardSet.cpp @@ -45,7 +45,7 @@ G1CardSet::CardSetPtr G1CardSet::FullCardSet = (G1CardSet::CardSetPtr)-1; G1CardSetConfiguration::G1CardSetConfiguration() : - _inline_ptr_bits_per_card(HeapRegion::LogOfHRGrainBytes - CardTable::card_shift) { + _inline_ptr_bits_per_card(HeapRegion::LogCardsPerRegion) { // Array of Cards card set container size calculation _num_cards_in_array = G1RemSetArrayOfCardsEntries; @@ -194,6 +194,8 @@ class G1CardSetHashTable : public CHeapObj { class G1CardSetHashTableFound : public StackObj { G1CardSetHashTableValue* _value; public: + G1CardSetHashTableFound() : _value(nullptr) { } + void operator()(G1CardSetHashTableValue* value) { _value = value; } @@ -247,14 +249,12 @@ class G1CardSetHashTable : public CHeapObj { return found.value(); } - CardSetPtr get(uint region_idx) { + G1CardSetHashTableValue* get(uint region_idx) { G1CardSetHashTableLookUp lookup(region_idx); G1CardSetHashTableFound found; - if (_table.get(Thread::current(), lookup, found)) { - return found.value()->_card_set; - } - return nullptr; + _table.get(Thread::current(), lookup, found); + return found.value(); } void iterate_safepoint(G1CardSet::G1CardSetPtrIterator* cl2) { @@ -611,8 +611,9 @@ void G1CardSet::transfer_cards_in_howl(CardSetPtr parent_card_set, G1CardSetHowl* howling_array = card_set_ptr(parent_card_set); Atomic::add(&howling_array->_num_entries, diff, memory_order_relaxed); - bool should_grow_table = false; - G1CardSetHashTableValue* table_entry = get_or_add_card_set(card_region, &should_grow_table); + G1CardSetHashTableValue* table_entry = get_card_set(card_region); + assert(table_entry != nullptr, "Table entry not found for transferred cards"); + Atomic::add(&table_entry->_num_occupied, diff, memory_order_relaxed); Atomic::add(&_num_occupied, diff, memory_order_relaxed); @@ -656,7 +657,7 @@ G1CardSetHashTableValue* G1CardSet::get_or_add_card_set(uint card_region, bool* return _table->get_or_add(card_region, should_grow_table); } -G1CardSet::CardSetPtr G1CardSet::get_card_set(uint card_region) { +G1CardSetHashTableValue* G1CardSet::get_card_set(uint card_region) { return _table->get(card_region); } @@ -709,10 +710,13 @@ bool G1CardSet::contains_card(uint card_region, uint card_in_region) { // Protect the card set from reclamation. GlobalCounter::CriticalSection cs(Thread::current()); - CardSetPtr card_set = get_card_set(card_region); - if (card_set == nullptr) { + G1CardSetHashTableValue* table_entry = get_card_set(card_region); + if (table_entry == nullptr) { return false; - } else if (card_set == FullCardSet) { + } + + CardSetPtr card_set = table_entry->_card_set; + if (card_set == FullCardSet) { // contains_card() is not a performance critical method so we do not hide that // case in the switch below. return true; @@ -736,11 +740,14 @@ bool G1CardSet::contains_card(uint card_region, uint card_in_region) { } void G1CardSet::print_info(outputStream* st, uint card_region, uint card_in_region) { - CardSetPtr card_set = get_card_set(card_region); - if (card_set == nullptr) { + G1CardSetHashTableValue* table_entry = get_card_set(card_region); + if (table_entry == nullptr) { st->print("NULL card set"); return; - } else if (card_set == FullCardSet) { + } + + CardSetPtr card_set = table_entry->_card_set; + if (card_set == FullCardSet) { st->print("FULL card set)"); return; } diff --git a/src/hotspot/share/gc/g1/g1CardSet.hpp b/src/hotspot/share/gc/g1/g1CardSet.hpp index 09466b2fe32..5220c2ce272 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.hpp +++ b/src/hotspot/share/gc/g1/g1CardSet.hpp @@ -47,7 +47,10 @@ enum G1AddCardResult { }; class G1CardSetConfiguration { + // Holds the number of bits required to cover the maximum card index for the + // regions covered by this card set. uint _inline_ptr_bits_per_card; + uint _num_cards_in_array; uint _num_cards_in_howl_bitmap; uint _num_buckets_in_howl; @@ -254,7 +257,7 @@ class G1CardSet : public CHeapObj { G1AddCardResult add_to_howl(CardSetPtr parent_card_set, uint card_region, uint card_in_region, bool increment_total = true); G1CardSetHashTableValue* get_or_add_card_set(uint card_region, bool* should_grow_table); - CardSetPtr get_card_set(uint card_region); + G1CardSetHashTableValue* get_card_set(uint card_region); // Iterate over cards of a card set container during transfer of the cards from // one container to another. Executes diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp index a511f75f631..267af7d3695 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp @@ -36,6 +36,37 @@ #include "runtime/thread.inline.hpp" +// A helper class to encode a few card indexes within a CardSetPtr. +// +// The pointer value (either 32 or 64 bits) is split into two areas: +// +// - Header containing identifying tag and number of encoded cards. +// - Data area containing the card indexes themselves +// +// The header starts (from LSB) with the identifying tag (two bits, +// always 00), and three bits size. The size stores the number of +// valid card indexes after the header. +// +// The data area makes up the remainder of the word, with card indexes +// put one after another at increasing bit positions. The separate +// card indexes use just enough space (bits) to represent the whole +// range of cards needed for covering the whole range of values +// (typically in a region). There may be unused space at the top of +// the word. +// +// Example: +// +// 64 bit pointer size, with 8M-size regions (8M == 2^23) +// -> 2^14 (2^23 / 2^9) cards; each card represents 512 bytes in a region +// -> 14 bits per card; must have enough bits to hold the max card index +// -> may encode up to 4 cards into it, using 61 bits (5 bits header + 4 * 14) +// +// M L +// S S +// B B +// +------+ +---------------+--------------+-----+ +// |unused| ... | card_index1 | card_index0 |SSS00| +// +------+ +---------------+--------------+-----+ class G1CardSetInlinePtr : public StackObj { friend class G1CardSetContainersTest; @@ -63,15 +94,18 @@ class G1CardSetInlinePtr : public StackObj { uint result = ((uintptr_t)value >> card_pos) & (((uintptr_t)1 << bits_per_card) - 1); return result; } + + uint find(uint const card_idx, uint const bits_per_card, uint start_at, uint num_elems); + public: G1CardSetInlinePtr() : _value_addr(nullptr), _value((CardSetPtr)G1CardSet::CardSetInlinePtr) { } G1CardSetInlinePtr(CardSetPtr value) : _value_addr(nullptr), _value(value) { - assert(((uintptr_t)_value & G1CardSet::CardSetInlinePtr) == G1CardSet::CardSetInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInPtr.", p2i(_value)); + assert(G1CardSet::card_set_type(_value) == G1CardSet::CardSetInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInPtr.", p2i(_value)); } G1CardSetInlinePtr(CardSetPtr volatile* value_addr, CardSetPtr value) : _value_addr(value_addr), _value(value) { - assert(((uintptr_t)_value & G1CardSet::CardSetInlinePtr) == G1CardSet::CardSetInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInPtr.", p2i(_value)); + assert(G1CardSet::card_set_type(_value) == G1CardSet::CardSetInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInPtr.", p2i(_value)); } G1AddCardResult add(uint const card_idx, uint const bits_per_card, uint const max_cards_in_inline_ptr); diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp index 29c53bee3b3..7562f5b18a0 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp @@ -47,10 +47,14 @@ inline G1CardSetInlinePtr::CardSetPtr G1CardSetInlinePtr::merge(CardSetPtr orig_ inline G1AddCardResult G1CardSetInlinePtr::add(uint card_idx, uint bits_per_card, uint max_cards_in_inline_ptr) { assert(_value_addr != nullptr, "No value address available, cannot add to set."); + uint cur_idx = 0; while (true) { uint num_elems = num_cards_in(_value); + if (num_elems > 0) { + cur_idx = find(card_idx, bits_per_card, cur_idx, num_elems); + } // Check if the card is already stored in the pointer. - if (contains(card_idx, bits_per_card)) { + if (cur_idx < num_elems) { return Found; } // Check if there is actually enough space. @@ -72,19 +76,29 @@ inline G1AddCardResult G1CardSetInlinePtr::add(uint card_idx, uint bits_per_card } } -inline bool G1CardSetInlinePtr::contains(uint card_idx, uint bits_per_card) { - uint num_elems = num_cards_in(_value); +inline uint G1CardSetInlinePtr::find(uint card_idx, uint bits_per_card, uint start_at, uint num_elems) { + assert(start_at < num_elems, "Precondition!"); + uintptr_t const card_mask = (1 << bits_per_card) - 1; + uintptr_t value = ((uintptr_t)_value) >> card_pos_for(start_at, bits_per_card); - uintptr_t value = ((uintptr_t)_value) >> card_pos_for(0, bits_per_card); // Check if the card is already stored in the pointer. - for (uint cur_idx = 0; cur_idx < num_elems; cur_idx++) { + for (uint cur_idx = start_at; cur_idx < num_elems; cur_idx++) { if ((value & card_mask) == card_idx) { - return true; + return cur_idx; } value >>= bits_per_card; } - return false; + return num_elems; +} + +inline bool G1CardSetInlinePtr::contains(uint card_idx, uint bits_per_card) { + uint num_elems = num_cards_in(_value); + if (num_elems == 0) { + return false; + } + uint cur_idx = find(card_idx, bits_per_card, 0, num_elems); + return cur_idx < num_elems; } template diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 943ee25eb42..ef0b3e81ad7 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -42,6 +42,7 @@ #include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1FullCollector.hpp" +#include "gc/g1/g1GCCounters.hpp" #include "gc/g1/g1GCParPhaseTimesTracker.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1GCPauseType.hpp" @@ -163,11 +164,10 @@ HeapRegion* G1CollectedHeap::new_region(size_t word_size, HeapRegion* res = _hrm.allocate_free_region(type, node_index); - if (res == NULL && do_expand && _expand_heap_after_alloc_failure) { + if (res == NULL && do_expand) { // Currently, only attempts to allocate GC alloc regions set // do_expand to true. So, we should only reach here during a - // safepoint. If this assumption changes we might have to - // reconsider the use of _expand_heap_after_alloc_failure. + // safepoint. assert(SafepointSynchronize::is_at_safepoint(), "invariant"); log_debug(gc, ergo, heap)("Attempt heap expansion (region allocation request failed). Allocation request: " SIZE_FORMAT "B", @@ -182,8 +182,6 @@ HeapRegion* G1CollectedHeap::new_region(size_t word_size, // region size, the free list should in theory not be empty. // In either case allocate_free_region() will check for NULL. res = _hrm.allocate_free_region(type, node_index); - } else { - _expand_heap_after_alloc_failure = false; } } return res; @@ -1455,7 +1453,6 @@ G1CollectedHeap::G1CollectedHeap() : _archive_allocator(NULL), _survivor_evac_stats("Young", YoungPLABSize, PLABWeight), _old_evac_stats("Old", OldPLABSize, PLABWeight), - _expand_heap_after_alloc_failure(true), _monitoring_support(nullptr), _humongous_reclaim_candidates(), _num_humongous_objects(0), @@ -1514,7 +1511,6 @@ G1CollectedHeap::G1CollectedHeap() : for (uint i = 0; i < n_queues; i++) { G1ScannerTasksQueue* q = new G1ScannerTasksQueue(); - q->initialize(); _task_queues->register_queue(i, q); ::new (&_evacuation_failed_info_array[i]) EvacuationFailedInfo(); } @@ -2015,8 +2011,14 @@ void G1CollectedHeap::increment_old_marking_cycles_completed(bool concurrent, ml.notify_all(); } +// Helper for collect(). +static G1GCCounters collection_counters(G1CollectedHeap* g1h) { + MutexLocker ml(Heap_lock); + return G1GCCounters(g1h); +} + void G1CollectedHeap::collect(GCCause::Cause cause) { - try_collect(cause); + try_collect(cause, collection_counters(this)); } // Return true if (x < y) with allowance for wraparound. @@ -2211,25 +2213,13 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause, } } -bool G1CollectedHeap::try_collect(GCCause::Cause cause) { - assert_heap_not_locked(); - - // Lock to get consistent set of values. - uint gc_count_before; - uint full_gc_count_before; - uint old_marking_started_before; - { - MutexLocker ml(Heap_lock); - gc_count_before = total_collections(); - full_gc_count_before = total_full_collections(); - old_marking_started_before = _old_marking_cycles_started; - } - +bool G1CollectedHeap::try_collect(GCCause::Cause cause, + const G1GCCounters& counters_before) { if (should_do_concurrent_full_gc(cause)) { return try_collect_concurrently(cause, - gc_count_before, - old_marking_started_before); - } else if (GCLocker::should_discard(cause, gc_count_before)) { + counters_before.total_collections(), + counters_before.old_marking_cycles_started()); + } else if (GCLocker::should_discard(cause, counters_before.total_collections())) { // Indicate failure to be consistent with VMOp failure due to // another collection slipping in after our gc_count but before // our request is processed. @@ -2240,14 +2230,16 @@ bool G1CollectedHeap::try_collect(GCCause::Cause cause) { // Schedule a standard evacuation pause. We're setting word_size // to 0 which means that we are not requesting a post-GC allocation. VM_G1CollectForAllocation op(0, /* word_size */ - gc_count_before, + counters_before.total_collections(), cause, policy()->max_pause_time_ms()); VMThread::execute(&op); return op.gc_succeeded(); } else { // Schedule a Full GC. - VM_G1CollectFull op(gc_count_before, full_gc_count_before, cause); + VM_G1CollectFull op(counters_before.total_collections(), + counters_before.total_full_collections(), + cause); VMThread::execute(&op); return op.gc_succeeded(); } @@ -3521,7 +3513,6 @@ void G1CollectedHeap::pre_evacuate_collection_set(G1EvacuationInfo* evacuation_i _bytes_used_during_gc = 0; - _expand_heap_after_alloc_failure = true; Atomic::store(&_num_regions_failed_evacuation, 0u); gc_prologue(false); @@ -3721,14 +3712,16 @@ void G1CollectedHeap::evacuate_initial_collection_set(G1ParScanThreadStateSet* p num_workers, has_optional_evacuation_work); task_time = run_task_timed(&g1_par_task); - // Closing the inner scope will execute the destructor for the G1RootProcessor object. - // To extract its code root fixup time we measure total time of this scope and - // subtract from the time the WorkGang task took. + // Closing the inner scope will execute the destructor for the + // G1RootProcessor object. By subtracting the WorkGang task from the total + // time of this scope, we get the "NMethod List Cleanup" time. This list is + // constructed during "STW two-phase nmethod root processing", see more in + // nmethod.hpp } Tickspan total_processing = Ticks::now() - start_processing; p->record_initial_evac_time(task_time.seconds() * 1000.0); - p->record_or_add_code_root_fixup_time((total_processing - task_time).seconds() * 1000.0); + p->record_or_add_nmethod_list_cleanup_time((total_processing - task_time).seconds() * 1000.0); rem_set()->complete_evac_phase(has_optional_evacuation_work); } @@ -3753,6 +3746,7 @@ class G1EvacuateOptionalRegionsTask : public G1EvacuateRegionsBaseTask { }; void G1CollectedHeap::evacuate_next_optional_regions(G1ParScanThreadStateSet* per_thread_states) { + // To access the protected constructor/destructor class G1MarkScope : public MarkScope { }; Tickspan task_time; @@ -3762,12 +3756,12 @@ void G1CollectedHeap::evacuate_next_optional_regions(G1ParScanThreadStateSet* pe G1MarkScope code_mark_scope; G1EvacuateOptionalRegionsTask task(per_thread_states, _task_queues, workers()->active_workers()); task_time = run_task_timed(&task); - // See comment in evacuate_collection_set() for the reason of the scope. + // See comment in evacuate_initial_collection_set() for the reason of the scope. } Tickspan total_processing = Ticks::now() - start_processing; G1GCPhaseTimes* p = phase_times(); - p->record_or_add_code_root_fixup_time((total_processing - task_time).seconds() * 1000.0); + p->record_or_add_nmethod_list_cleanup_time((total_processing - task_time).seconds() * 1000.0); } void G1CollectedHeap::evacuate_optional_collection_set(G1ParScanThreadStateSet* per_thread_states) { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 1efb9b79e9c..5311b25cab3 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -81,6 +81,7 @@ class Space; class G1BatchedGangTask; class G1CardTableEntryClosure; class G1CollectionSet; +class G1GCCounters; class G1Policy; class G1HotCardCache; class G1RemSet; @@ -239,14 +240,6 @@ class G1CollectedHeap : public CollectedHeap { // GC allocation statistics policy for tenured objects. G1EvacStats _old_evac_stats; - // It specifies whether we should attempt to expand the heap after a - // region allocation failure. If heap expansion fails we set this to - // false so that we don't re-attempt the heap expansion (it's likely - // that subsequent expansion attempts will also fail if one fails). - // Currently, it is only consulted during GC and it's reset at the - // start of each GC. - bool _expand_heap_after_alloc_failure; - // Helper for monitoring and management support. G1MonitoringSupport* _monitoring_support; @@ -670,7 +663,11 @@ class G1CollectedHeap : public CollectedHeap { // to only parts, or aborted before completion). void increment_old_marking_cycles_completed(bool concurrent, bool whole_heap_examined); - uint old_marking_cycles_completed() { + uint old_marking_cycles_started() const { + return _old_marking_cycles_started; + } + + uint old_marking_cycles_completed() const { return _old_marking_cycles_completed; } @@ -1136,7 +1133,7 @@ class G1CollectedHeap : public CollectedHeap { // Perform a collection of the heap with the given cause. // Returns whether this collection actually executed. - bool try_collect(GCCause::Cause cause); + bool try_collect(GCCause::Cause cause, const G1GCCounters& counters_before); // True iff an evacuation has failed in the most-recent collection. inline bool evacuation_failed() const; diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.cpp b/src/hotspot/share/gc/g1/g1CollectionSet.cpp index f77a16d7a7e..e447356f1df 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -458,13 +458,7 @@ double G1CollectionSet::finalize_young_part(double target_pause_time_ms, G1Survi } static int compare_region_idx(const uint a, const uint b) { - if (a > b) { - return 1; - } else if (a == b) { - return 0; - } else { - return -1; - } + return static_cast(a-b); } void G1CollectionSet::finalize_old_part(double time_remaining_ms) { diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 95c1cb3de30..edc0164f3e9 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -445,7 +445,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, for (uint i = 0; i < _max_num_tasks; ++i) { G1CMTaskQueue* task_queue = new G1CMTaskQueue(); - task_queue->initialize(); _task_queues->register_queue(i, task_queue); _tasks[i] = new G1CMTask(i, this, task_queue, _region_mark_stats); diff --git a/src/hotspot/share/gc/g1/g1EvacFailure.cpp b/src/hotspot/share/gc/g1/g1EvacFailure.cpp index 07a4603ade0..e99f647dfe1 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp @@ -80,6 +80,7 @@ class RemoveSelfForwardPtrObjClosure: public ObjectClosure { G1CollectedHeap* _g1h; G1ConcurrentMark* _cm; HeapRegion* _hr; + const bool _is_young; size_t _marked_bytes; UpdateLogBuffersDeferred* _log_buffer_cl; bool _during_concurrent_start; @@ -94,6 +95,7 @@ class RemoveSelfForwardPtrObjClosure: public ObjectClosure { _g1h(G1CollectedHeap::heap()), _cm(_g1h->concurrent_mark()), _hr(hr), + _is_young(hr->is_young()), _marked_bytes(0), _log_buffer_cl(log_buffer_cl), _during_concurrent_start(during_concurrent_start), @@ -140,19 +142,14 @@ class RemoveSelfForwardPtrObjClosure: public ObjectClosure { _marked_bytes += (obj_size * HeapWordSize); PreservedMarks::init_forwarded_mark(obj); - // While we were processing RSet buffers during the collection, - // we actually didn't scan any cards on the collection set, - // since we didn't want to update remembered sets with entries - // that point into the collection set, given that live objects - // from the collection set are about to move and such entries - // will be stale very soon. - // This change also dealt with a reliability issue which - // involved scanning a card in the collection set and coming - // across an array that was being chunked and looking malformed. - // The problem is that, if evacuation fails, we might have - // remembered set entries missing given that we skipped cards on - // the collection set. So, we'll recreate such entries now. - obj->oop_iterate(_log_buffer_cl); + // During evacuation failure we do not record inter-region + // references referencing regions that need a remembered set + // update originating from young regions (including eden) that + // failed evacuation. Make up for that omission now by rescanning + // these failed objects. + if (_is_young) { + obj->oop_iterate(_log_buffer_cl); + } HeapWord* obj_end = obj_addr + obj_size; _last_forwarded_object_end = obj_end; diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.cpp b/src/hotspot/share/gc/g1/g1FullGCMarker.cpp index f945cd5139f..2e2773c54dd 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.cpp @@ -46,8 +46,6 @@ G1FullGCMarker::G1FullGCMarker(G1FullCollector* collector, _cld_closure(mark_closure(), ClassLoaderData::_claim_strong), _mark_stats_cache(mark_stats, G1RegionMarkStatsCache::RegionMarkStatsCacheSize) { _mark_stats_cache.reset(); - _oop_stack.initialize(); - _objarray_stack.initialize(); } G1FullGCMarker::~G1FullGCMarker() { diff --git a/src/hotspot/share/gc/g1/g1GCCounters.cpp b/src/hotspot/share/gc/g1/g1GCCounters.cpp new file mode 100644 index 00000000000..403651ab332 --- /dev/null +++ b/src/hotspot/share/gc/g1/g1GCCounters.cpp @@ -0,0 +1,34 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1GCCounters.hpp" + +G1GCCounters::G1GCCounters(G1CollectedHeap* g1h) : + _total_collections(g1h->total_collections()), + _total_full_collections(g1h->total_full_collections()), + _old_marking_cycles_started(g1h->old_marking_cycles_started()) +{} + diff --git a/src/hotspot/share/gc/g1/g1GCCounters.hpp b/src/hotspot/share/gc/g1/g1GCCounters.hpp new file mode 100644 index 00000000000..23eb87171d7 --- /dev/null +++ b/src/hotspot/share/gc/g1/g1GCCounters.hpp @@ -0,0 +1,51 @@ +/* + * 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. + * + */ + +#ifndef SHARE_GC_G1_G1GCCOUNTERS_HPP +#define SHARE_GC_G1_G1GCCOUNTERS_HPP + +#include "utilities/globalDefinitions.hpp" + +class G1CollectedHeap; + +// Record collection counters for later use when deciding whether a GC has +// been run since the counter state was recorded. +class G1GCCounters { + uint _total_collections; + uint _total_full_collections; + uint _old_marking_cycles_started; + +public: + G1GCCounters() {} // Uninitialized + + // Capture the current counters from the heap. The caller must ensure no + // collections will occur while this constructor is executing. + explicit G1GCCounters(G1CollectedHeap* g1h); + + uint total_collections() const { return _total_collections; } + uint total_full_collections() const { return _total_full_collections; } + uint old_marking_cycles_started() const { return _old_marking_cycles_started; } +}; + +#endif // SHARE_GC_G1_G1GCCOUNTERS_HPP diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index f1240c39f8a..d6207bd1f93 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -154,7 +154,7 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : void G1GCPhaseTimes::reset() { _cur_collection_initial_evac_time_ms = 0.0; _cur_optional_evac_time_ms = 0.0; - _cur_collection_code_root_fixup_time_ms = 0.0; + _cur_collection_nmethod_list_cleanup_time_ms = 0.0; _cur_merge_heap_roots_time_ms = 0.0; _cur_optional_merge_heap_roots_time_ms = 0.0; _cur_prepare_merge_heap_roots_time_ms = 0.0; @@ -448,7 +448,7 @@ double G1GCPhaseTimes::print_evacuate_initial_collection_set() const { } double G1GCPhaseTimes::print_post_evacuate_collection_set() const { - const double sum_ms = _cur_collection_code_root_fixup_time_ms + + const double sum_ms = _cur_collection_nmethod_list_cleanup_time_ms + _recorded_preserve_cm_referents_time_ms + _cur_ref_proc_time_ms + (_weak_phase_times.total_time_sec() * MILLIUNITS) + @@ -461,7 +461,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { info_time("Post Evacuate Collection Set", sum_ms); - debug_time("Code Roots Fixup", _cur_collection_code_root_fixup_time_ms); + debug_time("NMethod List Cleanup", _cur_collection_nmethod_list_cleanup_time_ms); debug_time_for_reference("Reference Processing", _cur_ref_proc_time_ms); _ref_phase_times.print_all_references(2, false); diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index 38fab5ec194..3a12194cd92 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -154,7 +154,7 @@ class G1GCPhaseTimes : public CHeapObj { double _cur_collection_initial_evac_time_ms; double _cur_optional_evac_time_ms; - double _cur_collection_code_root_fixup_time_ms; + double _cur_collection_nmethod_list_cleanup_time_ms; double _cur_merge_heap_roots_time_ms; double _cur_optional_merge_heap_roots_time_ms; @@ -283,8 +283,8 @@ class G1GCPhaseTimes : public CHeapObj { _cur_optional_evac_time_ms += ms; } - void record_or_add_code_root_fixup_time(double ms) { - _cur_collection_code_root_fixup_time_ms += ms; + void record_or_add_nmethod_list_cleanup_time(double ms) { + _cur_collection_nmethod_list_cleanup_time_ms += ms; } void record_merge_heap_roots_time(double ms) { diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index 441dfead6cb..12f65ef64dd 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -94,11 +94,6 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, _plab_allocator = new G1PLABAllocator(_g1h->allocator()); - // The dest for Young is used when the objects are aged enough to - // need to be moved to the next space. - _dest[G1HeapRegionAttr::Young] = G1HeapRegionAttr::Old; - _dest[G1HeapRegionAttr::Old] = G1HeapRegionAttr::Old; - _closures = G1EvacuationRootClosures::create_root_closures(this, _g1h); _oops_into_optional_regions = new G1OopStarChunkedList[_num_optional_regions]; @@ -356,6 +351,8 @@ HeapWord* G1ParScanThreadState::allocate_in_next_plab(G1HeapRegionAttr* dest, } G1HeapRegionAttr G1ParScanThreadState::next_region_attr(G1HeapRegionAttr const region_attr, markWord const m, uint& age) { + assert(region_attr.is_young() || region_attr.is_old(), "must be either Young or Old"); + if (region_attr.is_young()) { age = !m.has_displaced_mark_helper() ? m.age() : m.displaced_mark_helper().age(); @@ -363,7 +360,8 @@ G1HeapRegionAttr G1ParScanThreadState::next_region_attr(G1HeapRegionAttr const r return region_attr; } } - return dest(region_attr); + // young-to-old (promotion) or old-to-old; destination is old in both cases. + return G1HeapRegionAttr::Old; } void G1ParScanThreadState::report_promotion_event(G1HeapRegionAttr const dest_attr, diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index 79f5b3a22cb..75df743a9b8 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -55,7 +55,6 @@ class G1ParScanThreadState : public CHeapObj { G1PLABAllocator* _plab_allocator; AgeTable _age_table; - G1HeapRegionAttr _dest[G1HeapRegionAttr::Num]; // Local tenuring threshold. uint _tenuring_threshold; G1ScanEvacuatedObjClosure _scanner; @@ -88,14 +87,6 @@ class G1ParScanThreadState : public CHeapObj { G1CardTable* ct() { return _ct; } - G1HeapRegionAttr dest(G1HeapRegionAttr original) const { - assert(original.is_valid(), - "Original region attr invalid: %s", original.get_type_str()); - assert(_dest[original.type()].is_valid_gen(), - "Dest region attr is invalid: %s", _dest[original.type()].get_type_str()); - return _dest[original.type()]; - } - size_t _num_optional_regions; G1OopStarChunkedList* _oops_into_optional_regions; diff --git a/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp b/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp index 1e212824c7a..fea7c2f3c86 100644 --- a/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp +++ b/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -26,6 +26,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" +#include "gc/g1/g1GCCounters.hpp" #include "gc/g1/g1PeriodicGCTask.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "logging/log.hpp" @@ -33,11 +34,11 @@ #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" -bool G1PeriodicGCTask::should_start_periodic_gc() { +bool G1PeriodicGCTask::should_start_periodic_gc(G1CollectedHeap* g1h, + G1GCCounters* counters) { // Ensure no GC safepoints while we're doing the checks, to avoid data races. SuspendibleThreadSetJoiner sts; - G1CollectedHeap* g1h = G1CollectedHeap::heap(); // If we are currently in a concurrent mark we are going to uncommit memory soon. if (g1h->concurrent_mark()->cm_thread()->in_progress()) { log_debug(gc, periodic)("Concurrent cycle in progress. Skipping."); @@ -60,6 +61,11 @@ bool G1PeriodicGCTask::should_start_periodic_gc() { recent_load, G1PeriodicGCSystemLoadThreshold); return false; } + + // Record counters with GC safepoints blocked, to get a consistent snapshot. + // These are passed to try_collect so a GC between our release of the + // STS-joiner and the GC VMOp can be detected and cancel the request. + *counters = G1GCCounters(g1h); return true; } @@ -70,8 +76,10 @@ void G1PeriodicGCTask::check_for_periodic_gc() { } log_debug(gc, periodic)("Checking for periodic GC."); - if (should_start_periodic_gc()) { - if (!G1CollectedHeap::heap()->try_collect(GCCause::_g1_periodic_collection)) { + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + G1GCCounters counters; + if (should_start_periodic_gc(g1h, &counters)) { + if (!g1h->try_collect(GCCause::_g1_periodic_collection, counters)) { log_debug(gc, periodic)("GC request denied. Skipping."); } } diff --git a/src/hotspot/share/gc/g1/g1PeriodicGCTask.hpp b/src/hotspot/share/gc/g1/g1PeriodicGCTask.hpp index 237968898c4..8c3c7968c47 100644 --- a/src/hotspot/share/gc/g1/g1PeriodicGCTask.hpp +++ b/src/hotspot/share/gc/g1/g1PeriodicGCTask.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -27,9 +27,13 @@ #include "gc/g1/g1ServiceThread.hpp" +class G1CollectedHeap; +class G1GCCounters; + // Task handling periodic GCs class G1PeriodicGCTask : public G1ServiceTask { - bool should_start_periodic_gc(); + bool should_start_periodic_gc(G1CollectedHeap* g1h, + G1GCCounters* counters); void check_for_periodic_gc(); public: @@ -37,4 +41,4 @@ class G1PeriodicGCTask : public G1ServiceTask { virtual void execute(); }; -#endif // SHARE_GC_G1_G1PERIODICGCTASK_HPP \ No newline at end of file +#endif // SHARE_GC_G1_G1PERIODICGCTASK_HPP diff --git a/src/hotspot/share/gc/g1/g1RemSet.hpp b/src/hotspot/share/gc/g1/g1RemSet.hpp index 808a799736d..874ccd3c8f5 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.hpp +++ b/src/hotspot/share/gc/g1/g1RemSet.hpp @@ -107,8 +107,7 @@ class G1RemSet: public CHeapObj { // Prepare for and cleanup after scanning the heap roots. Must be called // once before and after in sequential code. void prepare_for_scan_heap_roots(); - // Cleans the card table from temporary duplicate detection information. - void cleanup_after_scan_heap_roots(); + // Print coarsening stats. void print_coarsen_stats(); // Creates a gang task for cleaining up temporary data structures and the diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index 4d9c2f81259..75d209b94a5 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -36,6 +36,17 @@ #include "memory/universe.hpp" #include "runtime/interfaceSupport.inline.hpp" +bool VM_G1CollectFull::skip_operation() const { + // There is a race between the periodic collection task's checks for + // wanting a collection and processing its request. A collection in that + // gap should cancel the request. + if ((_gc_cause == GCCause::_g1_periodic_collection) && + (G1CollectedHeap::heap()->total_collections() != _gc_count_before)) { + return true; + } + return VM_GC_Operation::skip_operation(); +} + void VM_G1CollectFull::doit() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); GCCauseSetter x(g1h, _gc_cause); diff --git a/src/hotspot/share/gc/g1/g1VMOperations.hpp b/src/hotspot/share/gc/g1/g1VMOperations.hpp index 317ab76a5a9..b5f36a51b78 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.hpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -33,14 +33,17 @@ class VM_G1CollectFull : public VM_GC_Operation { bool _gc_succeeded; +protected: + bool skip_operation() const override; + public: VM_G1CollectFull(uint gc_count_before, uint full_gc_count_before, GCCause::Cause cause) : VM_GC_Operation(gc_count_before, cause, full_gc_count_before, true), _gc_succeeded(false) { } - virtual VMOp_Type type() const { return VMOp_G1CollectFull; } - virtual void doit(); + VMOp_Type type() const override { return VMOp_G1CollectFull; } + void doit() override; bool gc_succeeded() const { return _gc_succeeded; } }; diff --git a/src/hotspot/share/gc/g1/heapRegion.inline.hpp b/src/hotspot/share/gc/g1/heapRegion.inline.hpp index 54da24902a1..0d9e93f7700 100644 --- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp @@ -178,9 +178,7 @@ inline bool HeapRegion::is_obj_dead(const oop obj, const G1CMBitMap* const prev_ } inline size_t HeapRegion::block_size(const HeapWord *addr) const { - if (addr == top()) { - return pointer_delta(end(), addr); - } + assert(addr < top(), "precondition"); if (block_is_obj(addr)) { return cast_to_oop(addr)->size(); diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index 272c1e28c3a..c3cacaa86d0 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -784,14 +784,6 @@ void ParallelScavengeHeap::resize_old_gen(size_t desired_free_space) { _old_gen->resize(desired_free_space); } -ParallelScavengeHeap::ParStrongRootsScope::ParStrongRootsScope() { - // nothing particular -} - -ParallelScavengeHeap::ParStrongRootsScope::~ParStrongRootsScope() { - // nothing particular -} - #ifndef PRODUCT void ParallelScavengeHeap::record_gen_tops_before_GC() { if (ZapUnusedHeapArea) { diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp index 689400fbe04..f2eb1e33d96 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp @@ -247,13 +247,6 @@ class ParallelScavengeHeap : public CollectedHeap { // Mangle the unused parts of all spaces in the heap void gen_mangle_unused_area() PRODUCT_RETURN; - // Call these in sequential code around the processing of strong roots. - class ParStrongRootsScope : public MarkScope { - public: - ParStrongRootsScope(); - ~ParStrongRootsScope(); - }; - GCMemoryManager* old_gc_manager() const { return _old_manager; } GCMemoryManager* young_gc_manager() const { return _young_manager; } diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.cpp b/src/hotspot/share/gc/parallel/psCompactionManager.cpp index ec9692eca2a..09a50994d6c 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp @@ -59,10 +59,6 @@ ParCompactionManager::ParCompactionManager() { _old_gen = heap->old_gen(); _start_array = old_gen()->start_array(); - marking_stack()->initialize(); - _objarray_stack.initialize(); - _region_stack.initialize(); - reset_bitmap_query_cache(); } diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index 9c73deeb706..47376a9bf83 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -191,7 +191,6 @@ PSPromotionManager::PSPromotionManager() { _old_lab.set_start_array(old_gen()->start_array()); uint queue_size; - claimed_stack_depth()->initialize(); queue_size = claimed_stack_depth()->max_elems(); _totally_drain = (ParallelGCThreads == 1) || (GCDrainStackTargetSize == 0); diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.hpp index e94be81b621..923dec1ec1c 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.hpp @@ -81,7 +81,6 @@ class PSPromotionManager { bool _old_gen_is_full; PSScannerTasksQueue _claimed_stack_depth; - OverflowTaskQueue _claimed_stack_breadth; bool _totally_drain; uint _target_stack_size; diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp index 23d13ce4aa8..30369ecb5e6 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp @@ -116,7 +116,7 @@ size_t StringDedup::Config::desired_table_size(size_t entry_count) { bool StringDedup::Config::ergo_initialize() { if (!UseStringDeduplication) { return true; - } else if (!UseG1GC && !UseShenandoahGC) { + } else if (!UseG1GC && !UseShenandoahGC && !UseZGC) { // String deduplication requested but not supported by the selected GC. // Warn and force disable, but don't error except in debug build with // incorrect default. diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index 0342241465c..325ab352917 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -345,8 +345,6 @@ class GenericTaskQueue: public TaskQueueSuper { // Initializes the queue to empty. GenericTaskQueue(); - void initialize(); - // Push the task "t" on the queue. Returns "false" iff the queue is full. inline bool push(E t); @@ -392,11 +390,6 @@ class GenericTaskQueue: public TaskQueueSuper { void invalidate_last_stolen_queue_id() { _last_stolen_queue_id = InvalidQueueId; } }; -template -GenericTaskQueue::GenericTaskQueue() : _last_stolen_queue_id(InvalidQueueId), _seed(17 /* random number */) { - assert(sizeof(Age) == sizeof(size_t), "Depends on this."); -} - // OverflowTaskQueue is a TaskQueue that also includes an overflow stack for // elements that do not fit in the TaskQueue. // diff --git a/src/hotspot/share/gc/shared/taskqueue.inline.hpp b/src/hotspot/share/gc/shared/taskqueue.inline.hpp index 265666551cf..b6e8e7a4095 100644 --- a/src/hotspot/share/gc/shared/taskqueue.inline.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.inline.hpp @@ -49,9 +49,10 @@ inline GenericTaskQueueSet::~GenericTaskQueueSet() { } template -inline void GenericTaskQueue::initialize() { - _elems = ArrayAllocator::allocate(N, F); -} +inline GenericTaskQueue::GenericTaskQueue() : + _elems(ArrayAllocator::allocate(N, F)), + _last_stolen_queue_id(InvalidQueueId), + _seed(17 /* random number */) {} template inline GenericTaskQueue::~GenericTaskQueue() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 68c15481251..c226b9ba21c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1425,7 +1425,6 @@ class ShenandoahParallelObjectIterator : public ParallelObjectIterator { // Initialize queues for every workers for (uint i = 0; i < _num_workers; ++i) { ShenandoahObjToScanQueue* task_queue = new ShenandoahObjToScanQueue(); - task_queue->initialize(); _task_queues->register_queue(i, task_queue); } // Divide roots among the workers. Assume that object referencing distribution diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp index 7c9ee7d2222..929965ce8ec 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp @@ -261,7 +261,9 @@ inline void ShenandoahMark::mark_through_ref(T* p, ShenandoahObjToScanQueue* q, if ((STRING_DEDUP == ENQUEUE_DEDUP) && ShenandoahStringDedup::is_candidate(obj)) { assert(ShenandoahStringDedup::is_enabled(), "Must be enabled"); req->add(obj); - } else if ((STRING_DEDUP == ALWAYS_DEDUP) && ShenandoahStringDedup::is_string_candidate(obj)) { + } else if ((STRING_DEDUP == ALWAYS_DEDUP) && + ShenandoahStringDedup::is_string_candidate(obj) && + !ShenandoahStringDedup::dedup_requested(obj)) { assert(ShenandoahStringDedup::is_enabled(), "Must be enabled"); req->add(obj); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp index 5eef4c4dadc..eaed74ceeb5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp @@ -40,7 +40,6 @@ ShenandoahMarkingContext::ShenandoahMarkingContext(MemRegion heap_region, MemReg assert(max_queues > 0, "At least one queue"); for (uint i = 0; i < max_queues; ++i) { ShenandoahObjToScanQueue* task_queue = new ShenandoahObjToScanQueue(); - task_queue->initialize(); _task_queues->register_queue(i, task_queue); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.hpp b/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.hpp index a8bd674a6b5..da4b1a6f470 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.hpp @@ -31,6 +31,7 @@ class ShenandoahStringDedup : public StringDedup { public: static inline bool is_string_candidate(oop obj); static inline bool is_candidate(oop obj); + static inline bool dedup_requested(oop obj); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHSTRINGDEDUP_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.inline.hpp index e2d97798969..57b30358e94 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.inline.hpp @@ -36,6 +36,10 @@ bool ShenandoahStringDedup::is_string_candidate(oop obj) { java_lang_String::value(obj) != nullptr; } +bool ShenandoahStringDedup::dedup_requested(oop obj) { + return java_lang_String::test_and_set_deduplication_requested(obj); +} + bool ShenandoahStringDedup::is_candidate(oop obj) { if (!is_string_candidate(obj)) { return false; @@ -51,7 +55,8 @@ bool ShenandoahStringDedup::is_candidate(oop obj) { // Increase string age and enqueue it when it rearches age threshold markWord new_mark = mark.incr_age(); if (mark == obj->cas_set_mark(new_mark, mark)) { - return StringDedup::is_threshold_age(new_mark.age()); + return StringDedup::is_threshold_age(new_mark.age()) && + !dedup_requested(obj); } } return false; diff --git a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp index b71999382d2..0ddbc3b598f 100644 --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp @@ -268,27 +268,16 @@ static const TypeFunc* clone_type() { void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const { Node* const src = ac->in(ArrayCopyNode::Src); + const TypeAryPtr* ary_ptr = src->get_ptr_type()->isa_aryptr(); - if (ac->is_clone_array()) { - const TypeAryPtr* ary_ptr = src->get_ptr_type()->isa_aryptr(); - BasicType bt; - if (ary_ptr == NULL) { - // ary_ptr can be null iff we are running with StressReflectiveCode - // This code will be unreachable - assert(StressReflectiveCode, "Guard against surprises"); - bt = T_LONG; - } else if (ary_ptr->is_flat()) { - // Clone flat inline type array - bt = T_LONG; + if (ac->is_clone_array() && ary_ptr != NULL) { + BasicType bt = ary_ptr->elem()->array_element_basic_type(); + if (is_reference_type(bt) && (!ary_ptr->is_flat())) { + // Clone object array + bt = T_OBJECT; } else { - bt = ary_ptr->elem()->array_element_basic_type(); - if (is_reference_type(bt)) { - // Clone object array - bt = T_OBJECT; - } else { - // Clone primitive array - bt = T_LONG; - } + // Clone primitive array + bt = T_LONG; } Node* ctrl = ac->in(TypeFunc::Control); @@ -336,12 +325,11 @@ void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* a Node* const dst = ac->in(ArrayCopyNode::Dest); Node* const size = ac->in(ArrayCopyNode::Length); - assert(ac->is_clone_inst(), "Sanity check"); assert(size->bottom_type()->is_long(), "Should be long"); // The native clone we are calling here expects the instance size in words // Add header/offset size to payload size to get instance size. - Node* const base_offset = phase->longcon(arraycopy_payload_base_offset(false) >> LogBytesPerLong); + Node* const base_offset = phase->longcon(arraycopy_payload_base_offset(ac->is_clone_array()) >> LogBytesPerLong); Node* const full_size = phase->transform_later(new AddLNode(size, base_offset)); Node* const call = phase->make_leaf_call(ctrl, diff --git a/src/hotspot/share/gc/z/zBarrier.inline.hpp b/src/hotspot/share/gc/z/zBarrier.inline.hpp index 5a4824aec15..0f9f8dd2a20 100644 --- a/src/hotspot/share/gc/z/zBarrier.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp @@ -117,7 +117,7 @@ inline void ZBarrier::self_heal(volatile oop* p, uintptr_t addr, uintptr_t heal_ for (;;) { // Heal - const uintptr_t prev_addr = Atomic::cmpxchg((volatile uintptr_t*)p, addr, heal_addr); + const uintptr_t prev_addr = Atomic::cmpxchg((volatile uintptr_t*)p, addr, heal_addr, memory_order_relaxed); if (prev_addr == addr) { // Success return; diff --git a/src/hotspot/share/gc/z/zDirector.cpp b/src/hotspot/share/gc/z/zDirector.cpp index 3028bb616fb..a9668a6a77f 100644 --- a/src/hotspot/share/gc/z/zDirector.cpp +++ b/src/hotspot/share/gc/z/zDirector.cpp @@ -212,8 +212,7 @@ ZDriverRequest rule_allocation_rate_dynamic() { // Calculate time until GC given the time until OOM and GC duration. // We also subtract the sample interval, so that we don't overshoot the // target time and end up starting the GC too late in the next interval. - const double more_safety_for_fewer_workers = (ConcGCThreads - actual_gc_workers) * sample_interval; - const double time_until_gc = time_until_oom - actual_gc_duration - sample_interval - more_safety_for_fewer_workers; + const double time_until_gc = time_until_oom - actual_gc_duration - sample_interval; log_debug(gc, director)("Rule: Allocation Rate (Dynamic GC Workers), " "MaxAllocRate: %.1fMB/s (+/-%.1f%%), Free: " SIZE_FORMAT "MB, GCCPUTime: %.3f, " diff --git a/src/hotspot/share/gc/z/zForwarding.inline.hpp b/src/hotspot/share/gc/z/zForwarding.inline.hpp index 9207dfdb012..cff6d7a905c 100644 --- a/src/hotspot/share/gc/z/zForwarding.inline.hpp +++ b/src/hotspot/share/gc/z/zForwarding.inline.hpp @@ -136,8 +136,12 @@ inline uintptr_t ZForwarding::insert(uintptr_t from_index, uintptr_t to_offset, const ZForwardingEntry new_entry(from_index, to_offset); const ZForwardingEntry old_entry; // Empty + // Make sure that object copy is finished + // before forwarding table installation + OrderAccess::release(); + for (;;) { - const ZForwardingEntry prev_entry = Atomic::cmpxchg(entries() + *cursor, old_entry, new_entry, memory_order_release); + const ZForwardingEntry prev_entry = Atomic::cmpxchg(entries() + *cursor, old_entry, new_entry, memory_order_relaxed); if (!prev_entry.populated()) { // Success return to_offset; diff --git a/src/hotspot/share/gc/z/zHeapIterator.cpp b/src/hotspot/share/gc/z/zHeapIterator.cpp index a777caedb61..89ff2680c0b 100644 --- a/src/hotspot/share/gc/z/zHeapIterator.cpp +++ b/src/hotspot/share/gc/z/zHeapIterator.cpp @@ -206,14 +206,12 @@ ZHeapIterator::ZHeapIterator(uint nworkers, bool visit_weaks) : // Create queues for (uint i = 0; i < _queues.size(); i++) { ZHeapIteratorQueue* const queue = new ZHeapIteratorQueue(); - queue->initialize(); _queues.register_queue(i, queue); } // Create array queues for (uint i = 0; i < _array_queues.size(); i++) { ZHeapIteratorArrayQueue* const array_queue = new ZHeapIteratorArrayQueue(); - array_queue->initialize(); _array_queues.register_queue(i, array_queue); } } diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index f528752c1c6..72f459b97fc 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -24,8 +24,10 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" #include "classfile/classLoaderDataGraph.hpp" +#include "classfile/javaClasses.inline.hpp" #include "code/nmethod.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/stringdedup/stringDedup.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "gc/z/zAbort.inline.hpp" #include "gc/z/zBarrier.inline.hpp" @@ -33,6 +35,7 @@ #include "gc/z/zLock.inline.hpp" #include "gc/z/zMark.inline.hpp" #include "gc/z/zMarkCache.inline.hpp" +#include "gc/z/zMarkContext.inline.hpp" #include "gc/z/zMarkStack.inline.hpp" #include "gc/z/zMarkTerminate.inline.hpp" #include "gc/z/zNMethod.hpp" @@ -279,7 +282,27 @@ void ZMark::follow_object(oop obj, bool finalizable) { } } -void ZMark::mark_and_follow(ZMarkCache* cache, ZMarkStackEntry entry) { +static void try_deduplicate(ZMarkContext* context, oop obj) { + if (!StringDedup::is_enabled()) { + // Not enabled + return; + } + + if (!java_lang_String::is_instance_inlined(obj)) { + // Not a String object + return; + } + + if (java_lang_String::test_and_set_deduplication_requested(obj)) { + // Already requested deduplication + return; + } + + // Request deduplication + context->string_dedup_requests()->add(obj); +} + +void ZMark::mark_and_follow(ZMarkContext* context, ZMarkStackEntry entry) { // Decode flags const bool finalizable = entry.finalizable(); const bool partial_array = entry.partial_array(); @@ -311,7 +334,7 @@ void ZMark::mark_and_follow(ZMarkCache* cache, ZMarkStackEntry entry) { // and alignment paddings can never be reclaimed. const size_t size = ZUtils::object_size(addr); const size_t aligned_size = align_up(size, page->object_alignment()); - cache->inc_live(page, aligned_size); + context->cache()->inc_live(page, aligned_size); } // Follow @@ -319,18 +342,24 @@ void ZMark::mark_and_follow(ZMarkCache* cache, ZMarkStackEntry entry) { if (is_array(addr)) { follow_array_object(objArrayOop(ZOop::from_address(addr)), finalizable); } else { - follow_object(ZOop::from_address(addr), finalizable); + const oop obj = ZOop::from_address(addr); + follow_object(obj, finalizable); + + // Try deduplicate + try_deduplicate(context, obj); } } } template -bool ZMark::drain(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, ZMarkCache* cache, T* timeout) { +bool ZMark::drain(ZMarkContext* context, T* timeout) { + ZMarkStripe* const stripe = context->stripe(); + ZMarkThreadLocalStacks* const stacks = context->stacks(); ZMarkStackEntry entry; // Drain stripe stacks while (stacks->pop(&_allocator, &_stripes, stripe, entry)) { - mark_and_follow(cache, entry); + mark_and_follow(context, entry); // Check timeout if (timeout->has_expired()) { @@ -343,7 +372,10 @@ bool ZMark::drain(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, ZMarkCach return !timeout->has_expired(); } -bool ZMark::try_steal_local(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) { +bool ZMark::try_steal_local(ZMarkContext* context) { + ZMarkStripe* const stripe = context->stripe(); + ZMarkThreadLocalStacks* const stacks = context->stacks(); + // Try to steal a local stack from another stripe for (ZMarkStripe* victim_stripe = _stripes.stripe_next(stripe); victim_stripe != stripe; @@ -360,7 +392,10 @@ bool ZMark::try_steal_local(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) return false; } -bool ZMark::try_steal_global(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) { +bool ZMark::try_steal_global(ZMarkContext* context) { + ZMarkStripe* const stripe = context->stripe(); + ZMarkThreadLocalStacks* const stacks = context->stacks(); + // Try to steal a stack from another stripe for (ZMarkStripe* victim_stripe = _stripes.stripe_next(stripe); victim_stripe != stripe; @@ -377,8 +412,8 @@ bool ZMark::try_steal_global(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks return false; } -bool ZMark::try_steal(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) { - return try_steal_local(stripe, stacks) || try_steal_global(stripe, stacks); +bool ZMark::try_steal(ZMarkContext* context) { + return try_steal_local(context) || try_steal_global(context); } void ZMark::idle() const { @@ -496,17 +531,17 @@ class ZMarkNoTimeout : public StackObj { } }; -void ZMark::work_without_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) { +void ZMark::work_without_timeout(ZMarkContext* context) { ZStatTimer timer(ZSubPhaseConcurrentMark); ZMarkNoTimeout no_timeout; for (;;) { - if (!drain(stripe, stacks, cache, &no_timeout)) { + if (!drain(context, &no_timeout)) { // Abort break; } - if (try_steal(stripe, stacks)) { + if (try_steal(context)) { // Stole work continue; } @@ -561,17 +596,17 @@ class ZMarkTimeout : public StackObj { } }; -void ZMark::work_with_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, uint64_t timeout_in_micros) { +void ZMark::work_with_timeout(ZMarkContext* context, uint64_t timeout_in_micros) { ZStatTimer timer(ZSubPhaseMarkTryComplete); ZMarkTimeout timeout(timeout_in_micros); for (;;) { - if (!drain(stripe, stacks, cache, &timeout)) { + if (!drain(context, &timeout)) { // Timed out break; } - if (try_steal(stripe, stacks)) { + if (try_steal(context)) { // Stole work continue; } @@ -582,14 +617,14 @@ void ZMark::work_with_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkThrea } void ZMark::work(uint64_t timeout_in_micros) { - ZMarkCache cache(_stripes.nstripes()); ZMarkStripe* const stripe = _stripes.stripe_for_worker(_nworkers, ZThread::worker_id()); ZMarkThreadLocalStacks* const stacks = ZThreadLocalData::stacks(Thread::current()); + ZMarkContext context(_stripes.nstripes(), stripe, stacks); if (timeout_in_micros == 0) { - work_without_timeout(&cache, stripe, stacks); + work_without_timeout(&context); } else { - work_with_timeout(&cache, stripe, stacks, timeout_in_micros); + work_with_timeout(&context, timeout_in_micros); } // Flush and publish stacks diff --git a/src/hotspot/share/gc/z/zMark.hpp b/src/hotspot/share/gc/z/zMark.hpp index 1f4b53758aa..1de4eb604ea 100644 --- a/src/hotspot/share/gc/z/zMark.hpp +++ b/src/hotspot/share/gc/z/zMark.hpp @@ -32,7 +32,7 @@ #include "utilities/globalDefinitions.hpp" class Thread; -class ZMarkCache; +class ZMarkContext; class ZPageTable; class ZWorkers; @@ -64,15 +64,12 @@ class ZMark { void follow_partial_array(ZMarkStackEntry entry, bool finalizable); void follow_array_object(objArrayOop obj, bool finalizable); void follow_object(oop obj, bool finalizable); - void mark_and_follow(ZMarkCache* cache, ZMarkStackEntry entry); - - template bool drain(ZMarkStripe* stripe, - ZMarkThreadLocalStacks* stacks, - ZMarkCache* cache, - T* timeout); - bool try_steal_local(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks); - bool try_steal_global(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks); - bool try_steal(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks); + void mark_and_follow(ZMarkContext* context, ZMarkStackEntry entry); + + template bool drain(ZMarkContext* context, T* timeout); + bool try_steal_local(ZMarkContext* context); + bool try_steal_global(ZMarkContext* context); + bool try_steal(ZMarkContext* context); void idle() const; bool flush(bool at_safepoint); bool try_proactive_flush(); @@ -84,13 +81,8 @@ class ZMark { void prepare_work(); void finish_work(); - void work_without_timeout(ZMarkCache* cache, - ZMarkStripe* stripe, - ZMarkThreadLocalStacks* stacks); - void work_with_timeout(ZMarkCache* cache, - ZMarkStripe* stripe, - ZMarkThreadLocalStacks* stacks, - uint64_t timeout_in_micros); + void work_without_timeout(ZMarkContext* context); + void work_with_timeout(ZMarkContext* context, uint64_t timeout_in_micros); void work(uint64_t timeout_in_micros); void verify_all_stacks_empty() const; diff --git a/src/hotspot/share/gc/z/zMarkContext.hpp b/src/hotspot/share/gc/z/zMarkContext.hpp new file mode 100644 index 00000000000..1b5ab76db7a --- /dev/null +++ b/src/hotspot/share/gc/z/zMarkContext.hpp @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef SHARE_GC_Z_ZMARKCONTEXT_HPP +#define SHARE_GC_Z_ZMARKCONTEXT_HPP + +#include "gc/z/zMarkCache.hpp" +#include "gc/shared/stringdedup/stringDedup.hpp" +#include "memory/allocation.hpp" + +class ZMarkStripe; +class ZMarkThreadLocalStacks; + +class ZMarkContext : public StackObj { +private: + ZMarkCache _cache; + ZMarkStripe* const _stripe; + ZMarkThreadLocalStacks* const _stacks; + StringDedup::Requests _string_dedup_requests; + +public: + ZMarkContext(size_t nstripes, + ZMarkStripe* stripe, + ZMarkThreadLocalStacks* stacks); + + ZMarkCache* cache(); + ZMarkStripe* stripe(); + ZMarkThreadLocalStacks* stacks(); + StringDedup::Requests* string_dedup_requests(); +}; + +#endif // SHARE_GC_Z_ZMARKCONTEXT_HPP diff --git a/src/hotspot/share/gc/z/zMarkContext.inline.hpp b/src/hotspot/share/gc/z/zMarkContext.inline.hpp new file mode 100644 index 00000000000..b104ab61e4f --- /dev/null +++ b/src/hotspot/share/gc/z/zMarkContext.inline.hpp @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef SHARE_GC_Z_ZMARKCONTEXT_INLINE_HPP +#define SHARE_GC_Z_ZMARKCONTEXT_INLINE_HPP + +#include "gc/z/zMarkContext.hpp" + +inline ZMarkContext::ZMarkContext(size_t nstripes, + ZMarkStripe* stripe, + ZMarkThreadLocalStacks* stacks) : + _cache(nstripes), + _stripe(stripe), + _stacks(stacks), + _string_dedup_requests() {} + +inline ZMarkCache* ZMarkContext::cache() { + return &_cache; +} + +inline ZMarkStripe* ZMarkContext::stripe() { + return _stripe; +} + +inline ZMarkThreadLocalStacks* ZMarkContext::stacks() { + return _stacks; +} + +inline StringDedup::Requests* ZMarkContext::string_dedup_requests() { + return &_string_dedup_requests; +} + +#endif // SHARE_GC_Z_ZMARKCACHE_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zStat.cpp b/src/hotspot/share/gc/z/zStat.cpp index 1d1067b9bb6..0df9d061087 100644 --- a/src/hotspot/share/gc/z/zStat.cpp +++ b/src/hotspot/share/gc/z/zStat.cpp @@ -760,8 +760,10 @@ ZStatCriticalPhase::ZStatCriticalPhase(const char* name, bool verbose) : _verbose(verbose) {} void ZStatCriticalPhase::register_start(const Ticks& start) const { - LogTarget(Debug, gc, start) log; - log_start(log, true /* thread */); + // This is called from sensitive contexts, for example before an allocation stall + // has been resolved. This means we must not access any oops in here since that + // could lead to infinite recursion. Without access to the thread name we can't + // really log anything useful here. } void ZStatCriticalPhase::register_end(const Ticks& start, const Ticks& end) const { diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp index 4e167ff451a..fcb50cfbe01 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp @@ -114,6 +114,10 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator { void generate_transcendental_entry(AbstractInterpreter::MethodKind kind, int fpargs); #endif // AARCH64 +#ifdef ARM32 + void generate_math_runtime_call(AbstractInterpreter::MethodKind kind); +#endif // ARM32 + #ifdef PPC void lock_method(Register Rflags, Register Rscratch1, Register Rscratch2, bool flags_preloaded=false); void generate_fixed_frame(bool native_call, Register Rsize_of_parameters, Register Rsize_of_locals); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index 80e629cb0e7..0bd6c3355dd 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -455,7 +455,7 @@ size_t JfrCheckpointManager::flush_type_set() { elements = ::flush_type_set(thread); } } - if (_new_checkpoint.is_signaled()) { + if (_new_checkpoint.is_signaled_with_reset()) { WriteOperation wo(_chunkwriter); MutexedWriteOperation mwo(wo); _thread_local_mspace->iterate(mwo); // current epoch list diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index 6cbfa44464d..0d338187775 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -1101,6 +1101,10 @@ void JfrTypeSet::clear() { } size_t JfrTypeSet::on_unloading_classes(JfrCheckpointWriter* writer) { + // JfrTraceIdEpoch::has_changed_tag_state_no_reset() is a load-acquire we issue to see side-effects (i.e. tags). + // The JfrRecorderThread does this as part of normal processing, but with concurrent class unloading, which can + // happen in arbitrary threads, we invoke it explicitly. + JfrTraceIdEpoch::has_changed_tag_state_no_reset(); if (JfrRecorder::is_recording()) { return serialize(writer, NULL, true, false); } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp index 653c90fdba8..ba14919c935 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp @@ -108,6 +108,10 @@ class JfrTraceIdEpoch : AllStatic { } static bool has_changed_tag_state() { + return _tag_state.is_signaled_with_reset(); + } + + static bool has_changed_tag_state_no_reset() { return _tag_state.is_signaled(); } diff --git a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp index f9d84d3dd26..7001f0f0a02 100644 --- a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp +++ b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp @@ -44,7 +44,7 @@ typedef JfrStringPool::BufferPtr BufferPtr; static JfrSignal _new_string; bool JfrStringPool::is_modified() { - return _new_string.is_signaled(); + return _new_string.is_signaled_with_reset(); } static JfrStringPool* _instance = NULL; diff --git a/src/hotspot/share/jfr/utilities/jfrSignal.hpp b/src/hotspot/share/jfr/utilities/jfrSignal.hpp index 410ec1e8504..74d1b9e21ca 100644 --- a/src/hotspot/share/jfr/utilities/jfrSignal.hpp +++ b/src/hotspot/share/jfr/utilities/jfrSignal.hpp @@ -34,14 +34,16 @@ class JfrSignal { JfrSignal() : _signaled(false) {} void signal() const { - if (!Atomic::load_acquire(&_signaled)) { - Atomic::release_store(&_signaled, true); - } + Atomic::release_store(&_signaled, true); } bool is_signaled() const { - if (Atomic::load_acquire(&_signaled)) { - Atomic::release_store(&_signaled, false); // auto-reset + return Atomic::load_acquire(&_signaled); + } + + bool is_signaled_with_reset() const { + if (is_signaled()) { + Atomic::release_store(&_signaled, false); return true; } return false; diff --git a/src/hotspot/share/memory/arena.cpp b/src/hotspot/share/memory/arena.cpp index 500b9b7c4cc..c32c355bee7 100644 --- a/src/hotspot/share/memory/arena.cpp +++ b/src/hotspot/share/memory/arena.cpp @@ -44,124 +44,90 @@ STATIC_ASSERT(is_aligned((int)Chunk::non_pool_size, ARENA_AMALLOC_ALIGNMENT)); //-------------------------------------------------------------------------------------- // ChunkPool implementation -// MT-safe pool of chunks to reduce malloc/free thrashing +// MT-safe pool of same-sized chunks to reduce malloc/free thrashing // NB: not using Mutex because pools are used before Threads are initialized -class ChunkPool: public CHeapObj { +class ChunkPool { Chunk* _first; // first cached Chunk; its first word points to next chunk size_t _num_chunks; // number of unused chunks in pool - size_t _num_used; // number of chunks currently checked out - const size_t _size; // size of each chunk (must be uniform) + const size_t _size; // (inner payload) size of the chunks this pool serves // Our four static pools - static ChunkPool* _large_pool; - static ChunkPool* _medium_pool; - static ChunkPool* _small_pool; - static ChunkPool* _tiny_pool; + static const int _num_pools = 4; + static ChunkPool _pools[_num_pools]; - // return first element or null - void* get_first() { + public: + ChunkPool(size_t size) : _first(NULL), _num_chunks(0), _size(size) {} + + // Allocate a chunk from the pool; returns NULL if pool is empty. + Chunk* allocate() { + ThreadCritical tc; Chunk* c = _first; - if (_first) { + if (_first != nullptr) { _first = _first->next(); _num_chunks--; } return c; } - public: - // All chunks in a ChunkPool has the same size - ChunkPool(size_t size) : _size(size) { _first = NULL; _num_chunks = _num_used = 0; } - - // Allocate a new chunk from the pool (might expand the pool) - NOINLINE void* allocate(size_t bytes, AllocFailType alloc_failmode) { - assert(bytes == _size, "bad size"); - void* p = NULL; - // No VM lock can be taken inside ThreadCritical lock, so os::malloc - // should be done outside ThreadCritical lock due to NMT - { ThreadCritical tc; - _num_used++; - p = get_first(); - } - if (p == NULL) p = os::malloc(bytes, mtChunk, CURRENT_PC); - if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) { - vm_exit_out_of_memory(bytes, OOM_MALLOC_ERROR, "ChunkPool::allocate"); - } - return p; - } - // Return a chunk to the pool void free(Chunk* chunk) { - assert(chunk->length() + Chunk::aligned_overhead_size() == _size, "bad size"); + assert(chunk->length() == _size, "wrong pool for this chunk"); ThreadCritical tc; - _num_used--; - - // Add chunk to list chunk->set_next(_first); _first = chunk; _num_chunks++; } // Prune the pool - void free_all_but(size_t n) { + void prune() { + static const int blocksToKeep = 5; Chunk* cur = NULL; Chunk* next; - { - // if we have more than n chunks, free all of them - ThreadCritical tc; - if (_num_chunks > n) { - // free chunks at end of queue, for better locality - cur = _first; - for (size_t i = 0; i < (n - 1) && cur != NULL; i++) cur = cur->next(); - - if (cur != NULL) { - next = cur->next(); - cur->set_next(NULL); - cur = next; - - // Free all remaining chunks while in ThreadCritical lock - // so NMT adjustment is stable. - while(cur != NULL) { - next = cur->next(); - os::free(cur); - _num_chunks--; - cur = next; - } - } + // if we have more than n chunks, free all of them + ThreadCritical tc; + if (_num_chunks > blocksToKeep) { + // free chunks at end of queue, for better locality + cur = _first; + for (size_t i = 0; i < (blocksToKeep - 1); i++) { + assert(cur != NULL, "counter out of sync?"); + cur = cur->next(); + } + assert(cur != NULL, "counter out of sync?"); + + next = cur->next(); + cur->set_next(NULL); + cur = next; + + // Free all remaining chunks while in ThreadCritical lock + // so NMT adjustment is stable. + while(cur != NULL) { + next = cur->next(); + os::free(cur); + _num_chunks--; + cur = next; } } } - // Accessors to preallocated pool's - static ChunkPool* large_pool() { assert(_large_pool != NULL, "must be initialized"); return _large_pool; } - static ChunkPool* medium_pool() { assert(_medium_pool != NULL, "must be initialized"); return _medium_pool; } - static ChunkPool* small_pool() { assert(_small_pool != NULL, "must be initialized"); return _small_pool; } - static ChunkPool* tiny_pool() { assert(_tiny_pool != NULL, "must be initialized"); return _tiny_pool; } - - static void initialize() { - _large_pool = new ChunkPool(Chunk::size + Chunk::aligned_overhead_size()); - _medium_pool = new ChunkPool(Chunk::medium_size + Chunk::aligned_overhead_size()); - _small_pool = new ChunkPool(Chunk::init_size + Chunk::aligned_overhead_size()); - _tiny_pool = new ChunkPool(Chunk::tiny_size + Chunk::aligned_overhead_size()); - } - static void clean() { - enum { BlocksToKeep = 5 }; - _tiny_pool->free_all_but(BlocksToKeep); - _small_pool->free_all_but(BlocksToKeep); - _medium_pool->free_all_but(BlocksToKeep); - _large_pool->free_all_but(BlocksToKeep); + for (int i = 0; i < _num_pools; i++) { + _pools[i].prune(); + } } -}; -ChunkPool* ChunkPool::_large_pool = NULL; -ChunkPool* ChunkPool::_medium_pool = NULL; -ChunkPool* ChunkPool::_small_pool = NULL; -ChunkPool* ChunkPool::_tiny_pool = NULL; + // Given a (inner payload) size, return the pool responsible for it, or NULL if the size is non-standard + static ChunkPool* get_pool_for_size(size_t size) { + for (int i = 0; i < _num_pools; i++) { + if (_pools[i]._size == size) { + return _pools + i; + } + } + return NULL; + } -void chunkpool_init() { - ChunkPool::initialize(); -} +}; +ChunkPool ChunkPool::_pools[] = { Chunk::size, Chunk::medium_size, Chunk::init_size, Chunk::tiny_size }; //-------------------------------------------------------------------------------------- // ChunkPoolCleaner implementation @@ -181,7 +147,6 @@ class ChunkPoolCleaner : public PeriodicTask { // Chunk implementation void* Chunk::operator new (size_t sizeofChunk, AllocFailType alloc_failmode, size_t length) throw() { - // - requested_size = sizeof(Chunk) // - length = payload size // We must ensure that the boundaries of the payload (C and D) are aligned to 64-bit: @@ -203,34 +168,35 @@ void* Chunk::operator new (size_t sizeofChunk, AllocFailType alloc_failmode, siz assert(sizeofChunk == sizeof(Chunk), "weird request size"); assert(is_aligned(length, ARENA_AMALLOC_ALIGNMENT), "chunk payload length misaligned: " SIZE_FORMAT ".", length); + // Try to reuse a freed chunk from the pool + ChunkPool* pool = ChunkPool::get_pool_for_size(length); + if (pool != NULL) { + Chunk* c = pool->allocate(); + if (c != NULL) { + assert(c->length() == length, "wrong length?"); + return c; + } + } + // Either the pool was empty, or this is a non-standard length. Allocate a new Chunk from C-heap. size_t bytes = ARENA_ALIGN(sizeofChunk) + length; - switch (length) { - case Chunk::size: return ChunkPool::large_pool()->allocate(bytes, alloc_failmode); - case Chunk::medium_size: return ChunkPool::medium_pool()->allocate(bytes, alloc_failmode); - case Chunk::init_size: return ChunkPool::small_pool()->allocate(bytes, alloc_failmode); - case Chunk::tiny_size: return ChunkPool::tiny_pool()->allocate(bytes, alloc_failmode); - default: { - void* p = os::malloc(bytes, mtChunk, CALLER_PC); - if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) { - vm_exit_out_of_memory(bytes, OOM_MALLOC_ERROR, "Chunk::new"); - } - // We rely on arena alignment <= malloc alignment. - assert(is_aligned(p, ARENA_AMALLOC_ALIGNMENT), "Chunk start address misaligned."); - return p; - } + void* p = os::malloc(bytes, mtChunk, CALLER_PC); + if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) { + vm_exit_out_of_memory(bytes, OOM_MALLOC_ERROR, "Chunk::new"); } + // We rely on arena alignment <= malloc alignment. + assert(is_aligned(p, ARENA_AMALLOC_ALIGNMENT), "Chunk start address misaligned."); + return p; } void Chunk::operator delete(void* p) { + // If this is a standard-sized chunk, return it to its pool; otherwise free it. Chunk* c = (Chunk*)p; - switch (c->length()) { - case Chunk::size: ChunkPool::large_pool()->free(c); break; - case Chunk::medium_size: ChunkPool::medium_pool()->free(c); break; - case Chunk::init_size: ChunkPool::small_pool()->free(c); break; - case Chunk::tiny_size: ChunkPool::tiny_pool()->free(c); break; - default: - ThreadCritical tc; // Free chunks under TC lock so that NMT adjustment is stable. - os::free(c); + ChunkPool* pool = ChunkPool::get_pool_for_size(c->length()); + if (pool != NULL) { + pool->free(c); + } else { + ThreadCritical tc; // Free chunks under TC lock so that NMT adjustment is stable. + os::free(c); } } diff --git a/src/hotspot/share/memory/iterator.hpp b/src/hotspot/share/memory/iterator.hpp index 67559629c47..4afe308d2ce 100644 --- a/src/hotspot/share/memory/iterator.hpp +++ b/src/hotspot/share/memory/iterator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -348,17 +348,6 @@ class SerializeClosure : public Closure { class SymbolClosure : public StackObj { public: virtual void do_symbol(Symbol**) = 0; - - // Clear LSB in symbol address; it can be set by CPSlot. - static Symbol* load_symbol(Symbol** p) { - return (Symbol*)(intptr_t(*p) & ~1); - } - - // Store symbol, adjusting new pointer if the original pointer was adjusted - // (symbol references in constant pool slots have their LSB set to 1). - static void store_symbol(Symbol** p, Symbol* sym) { - *p = (Symbol*)(intptr_t(sym) | (intptr_t(*p) & 1)); - } }; template diff --git a/src/hotspot/share/memory/metaspaceClosure.hpp b/src/hotspot/share/memory/metaspaceClosure.hpp index 51cf2b7a320..8bec21adbc5 100644 --- a/src/hotspot/share/memory/metaspaceClosure.hpp +++ b/src/hotspot/share/memory/metaspaceClosure.hpp @@ -132,8 +132,8 @@ class MetaspaceClosure { virtual ~Ref() {} address obj() const { - // In some rare cases (see CPSlot in constantPool.hpp) we store some flags in the lowest - // 2 bits of a MetaspaceObj pointer. Unmask these when manipulating the pointer. + // In some rare cases we store some flags in the lowest 2 bits of a + // MetaspaceObj pointer. Unmask these when manipulating the pointer. uintx p = (uintx)*mpp(); return (address)(p & (~FLAG_MASK)); } diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 36d581cdab3..65daa729ac1 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -2445,11 +2445,11 @@ void ConstantPool::verify_on(outputStream* st) { if (tag.is_klass() || tag.is_unresolved_klass()) { guarantee(klass_name_at(i)->refcount() != 0, "should have nonzero reference count"); } else if (tag.is_symbol()) { - CPSlot entry = slot_at(i); - guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count"); + Symbol* entry = symbol_at(i); + guarantee(entry->refcount() != 0, "should have nonzero reference count"); } else if (tag.is_string()) { - CPSlot entry = slot_at(i); - guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count"); + Symbol* entry = unresolved_string_at(i); + guarantee(entry->refcount() != 0, "should have nonzero reference count"); } } if (pool_holder() != NULL) { diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index 24cd19399fa..46b42f78e7e 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -49,22 +49,6 @@ class SymbolHashMap; -class CPSlot { - friend class ConstantPool; - intptr_t _ptr; - enum TagBits {_pseudo_bit = 1}; - public: - - CPSlot(intptr_t ptr): _ptr(ptr) {} - CPSlot(Symbol* ptr, int tag_bits = 0): _ptr((intptr_t)ptr | tag_bits) {} - - intptr_t value() { return _ptr; } - - Symbol* get_symbol() { - return (Symbol*)(_ptr & ~_pseudo_bit); - } -}; - // This represents a JVM_CONSTANT_Class, JVM_CONSTANT_UnresolvedClass, or // JVM_CONSTANT_UnresolvedClassInError slot in the constant pool. class CPKlassSlot { @@ -152,13 +136,6 @@ class ConstantPool : public Metadata { private: intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); } - CPSlot slot_at(int which) const; - - void slot_at_put(int which, CPSlot s) const { - assert(is_within_bounds(which), "index out of bounds"); - assert(s.value() != 0, "Caught something"); - *(intptr_t*)&base()[which] = s.value(); - } intptr_t* obj_at_addr(int which) const { assert(is_within_bounds(which), "index out of bounds"); return (intptr_t*) &base()[which]; @@ -352,8 +329,12 @@ class ConstantPool : public Metadata { } void unresolved_string_at_put(int which, Symbol* s) { - release_tag_at_put(which, JVM_CONSTANT_String); - slot_at_put(which, CPSlot(s)); + assert(s->refcount() != 0, "should have nonzero refcount"); + // Note that release_tag_at_put is not needed here because this is called only + // when constructing a ConstantPool in a single thread, with no possibility + // of concurrent access. + tag_at_put(which, JVM_CONSTANT_String); + *symbol_at_addr(which) = s; } void int_at_put(int which, jint i) { @@ -506,8 +487,7 @@ class ConstantPool : public Metadata { Symbol* unresolved_string_at(int which) { assert(tag_at(which).is_string(), "Corrupted constant pool"); - Symbol* sym = slot_at(which).get_symbol(); - return sym; + return *symbol_at_addr(which); } // Returns an UTF8 for a CONSTANT_String entry at a given index. diff --git a/src/hotspot/share/oops/constantPool.inline.hpp b/src/hotspot/share/oops/constantPool.inline.hpp index 2ade0851968..89a449c06e9 100644 --- a/src/hotspot/share/oops/constantPool.inline.hpp +++ b/src/hotspot/share/oops/constantPool.inline.hpp @@ -30,15 +30,6 @@ #include "oops/cpCache.inline.hpp" #include "runtime/atomic.hpp" -inline CPSlot ConstantPool::slot_at(int which) const { - assert(is_within_bounds(which), "index out of bounds"); - assert(!tag_at(which).is_unresolved_klass() && !tag_at(which).is_unresolved_klass_in_error(), "Corrupted constant pool"); - // Uses volatile because the klass slot changes without a lock. - intptr_t adr = Atomic::load_acquire(obj_at_addr(which)); - assert(adr != 0 || which == 0, "cp entry for klass should not be zero"); - return CPSlot(adr); -} - inline Klass* ConstantPool::resolved_klass_at(int which) const { // Used by Compiler guarantee(tag_at(which).is_klass(), "Corrupted constant pool"); // Must do an acquire here in case another thread resolved the klass diff --git a/src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp b/src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp index 5a389205cea..53068e906cc 100644 --- a/src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp +++ b/src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp @@ -40,7 +40,7 @@ inline void InstanceClassLoaderKlass::oop_oop_iterate(oop obj, OopClosureType* c InstanceKlass::oop_oop_iterate(obj, closure); if (Devirtualizer::do_metadata(closure)) { - ClassLoaderData* cld = java_lang_ClassLoader::loader_data_raw(obj); + ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj); // cld can be null if we have a non-registered class loader. if (cld != NULL) { Devirtualizer::do_cld(closure, cld); @@ -62,7 +62,7 @@ inline void InstanceClassLoaderKlass::oop_oop_iterate_bounded(oop obj, OopClosur if (Devirtualizer::do_metadata(closure)) { if (mr.contains(obj)) { - ClassLoaderData* cld = java_lang_ClassLoader::loader_data_raw(obj); + ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj); // cld can be null if we have a non-registered class loader. if (cld != NULL) { Devirtualizer::do_cld(closure, cld); diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 864ea89c3ad..b4b8f64f3f0 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -727,9 +727,7 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { } set_annotations(NULL); - if (Arguments::is_dumping_archive()) { - SystemDictionaryShared::handle_class_unloading(this); - } + SystemDictionaryShared::handle_class_unloading(this); } bool InstanceKlass::is_record() const { @@ -1124,6 +1122,54 @@ void InstanceKlass::initialize_super_interfaces(TRAPS) { } } +ResourceHashtable + _initialization_error_table; + +void InstanceKlass::add_initialization_error(JavaThread* current, Handle exception) { + // Create the same exception with a message indicating the thread name, + // and the StackTraceElements. + // If the initialization error is OOM, this might not work, but if GC kicks in + // this would be still be helpful. + JavaThread* THREAD = current; + Handle cause = java_lang_Throwable::get_cause_with_stack_trace(exception, THREAD); + if (HAS_PENDING_EXCEPTION || cause.is_null()) { + CLEAR_PENDING_EXCEPTION; + return; + } + + MutexLocker ml(THREAD, ClassInitError_lock); + OopHandle elem = OopHandle(Universe::vm_global(), cause()); + bool created = false; + _initialization_error_table.put_if_absent(this, elem, &created); + assert(created, "Initialization is single threaded"); + ResourceMark rm(THREAD); + log_trace(class, init)("Initialization error added for class %s", external_name()); +} + +oop InstanceKlass::get_initialization_error(JavaThread* current) { + MutexLocker ml(current, ClassInitError_lock); + OopHandle* h = _initialization_error_table.get(this); + return (h != nullptr) ? h->resolve() : nullptr; +} + +// Need to remove entries for unloaded classes. +void InstanceKlass::clean_initialization_error_table() { + struct InitErrorTableCleaner { + bool do_entry(const InstanceKlass* ik, OopHandle h) { + if (!ik->is_loader_alive()) { + h.release(Universe::vm_global()); + return true; + } else { + return false; + } + } + }; + + MutexLocker ml(ClassInitError_lock); + InitErrorTableCleaner cleaner; + _initialization_error_table.unlink(&cleaner); +} + void InstanceKlass::initialize_impl(TRAPS) { HandleMark hm(THREAD); @@ -1170,16 +1216,15 @@ void InstanceKlass::initialize_impl(TRAPS) { if (is_in_error_state()) { DTRACE_CLASSINIT_PROBE_WAIT(erroneous, -1, wait); ResourceMark rm(THREAD); - const char* desc = "Could not initialize class "; - const char* className = external_name(); - size_t msglen = strlen(desc) + strlen(className) + 1; - char* message = NEW_RESOURCE_ARRAY(char, msglen); - if (NULL == message) { - // Out of memory: can't create detailed error message - THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className); + Handle cause(THREAD, get_initialization_error(THREAD)); + + stringStream ss; + ss.print("Could not initialize class %s", external_name()); + if (cause.is_null()) { + THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), ss.as_string()); } else { - jio_snprintf(message, msglen, "%s%s", desc, className); - THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message); + THROW_MSG_CAUSE(vmSymbols::java_lang_NoClassDefFoundError(), + ss.as_string(), cause); } } @@ -1210,6 +1255,7 @@ void InstanceKlass::initialize_impl(TRAPS) { CLEAR_PENDING_EXCEPTION; { EXCEPTION_MARK; + add_initialization_error(THREAD, e); // Locks object, set state, and notify all waiting threads set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; @@ -1274,9 +1320,7 @@ void InstanceKlass::initialize_impl(TRAPS) { // Step 10 if (!HAS_PENDING_EXCEPTION) { set_initialization_state_and_notify(fully_initialized, CHECK); - { - debug_only(vtable().verify(tty, true);) - } + debug_only(vtable().verify(tty, true);) } else { // Step 11 and 12 @@ -1287,6 +1331,7 @@ void InstanceKlass::initialize_impl(TRAPS) { JvmtiExport::clear_detected_exception(jt); { EXCEPTION_MARK; + add_initialization_error(THREAD, e); set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below // JVMTI has already reported the pending exception @@ -2782,9 +2827,7 @@ void InstanceKlass::unload_class(InstanceKlass* ik) { // notify ClassLoadingService of class unload ClassLoadingService::notify_class_unloaded(ik); - if (Arguments::is_dumping_archive()) { - SystemDictionaryShared::handle_class_unloading(ik); - } + SystemDictionaryShared::handle_class_unloading(ik); if (log_is_enabled(Info, class, unload)) { ResourceMark rm; @@ -3781,7 +3824,9 @@ const char* InstanceKlass::internal_name() const { void InstanceKlass::print_class_load_logging(ClassLoaderData* loader_data, const ModuleEntry* module_entry, const ClassFileStream* cfs) const { - log_to_classlist(); + if (ClassListWriter::is_enabled()) { + ClassListWriter::write(this, cfs); + } if (!log_is_enabled(Info, class, load)) { return; @@ -4322,45 +4367,6 @@ unsigned char * InstanceKlass::get_cached_class_file_bytes() { } #endif -bool InstanceKlass::is_shareable() const { -#if INCLUDE_CDS - ClassLoaderData* loader_data = class_loader_data(); - if (!SystemDictionaryShared::is_sharing_possible(loader_data)) { - return false; - } - - if (is_hidden()) { - return false; - } - - if (module()->is_patched()) { - return false; - } - - return true; -#else - return false; -#endif -} - -void InstanceKlass::log_to_classlist() const { -#if INCLUDE_CDS - ResourceMark rm; - if (ClassListWriter::is_enabled()) { - if (!ClassLoader::has_jrt_entry()) { - warning("DumpLoadedClassList and CDS are not supported in exploded build"); - DumpLoadedClassList = NULL; - return; - } - if (is_shareable()) { - ClassListWriter w; - w.stream()->print_cr("%s", name()->as_C_string()); - w.stream()->flush(); - } - } -#endif // INCLUDE_CDS -} - // Make a step iterating over the class hierarchy under the root class. // Skips subclasses if requested. void ClassHierarchyIterator::next() { diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 7bf24d7bd92..ff4dba942c9 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -1333,6 +1333,7 @@ class InstanceKlass: public Klass { virtual Klass* array_klass(TRAPS); virtual Klass* array_klass_or_null(); + static void clean_initialization_error_table(); private: void fence_and_clear_init_lock(); @@ -1344,6 +1345,9 @@ class InstanceKlass: public Klass { /* jni_id_for_impl for jfieldID only */ JNIid* jni_id_for_impl (int offset); + void add_initialization_error(JavaThread* current, Handle exception); + oop get_initialization_error(JavaThread* current); + // find a local method (returns NULL if not found) Method* find_method_impl(const Symbol* name, const Symbol* signature, diff --git a/src/hotspot/share/oops/instanceMirrorKlass.cpp b/src/hotspot/share/oops/instanceMirrorKlass.cpp index 3e267eaf95b..e405b104826 100644 --- a/src/hotspot/share/oops/instanceMirrorKlass.cpp +++ b/src/hotspot/share/oops/instanceMirrorKlass.cpp @@ -56,7 +56,7 @@ instanceOop InstanceMirrorKlass::allocate_instance(Klass* k, TRAPS) { } int InstanceMirrorKlass::oop_size(oop obj) const { - return java_lang_Class::oop_size_raw(obj); + return java_lang_Class::oop_size(obj); } int InstanceMirrorKlass::compute_static_oop_field_count(oop obj) { diff --git a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp index e30e6f5a9e5..9b0067e6bdf 100644 --- a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp +++ b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp @@ -38,7 +38,7 @@ template void InstanceMirrorKlass::oop_oop_iterate_statics(oop obj, OopClosureType* closure) { T* p = (T*)start_of_static_fields(obj); - T* const end = p + java_lang_Class::static_oop_field_count_raw(obj); + T* const end = p + java_lang_Class::static_oop_field_count(obj); for (; p < end; ++p) { Devirtualizer::do_oop(closure, p); @@ -50,7 +50,7 @@ void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) { InstanceKlass::oop_oop_iterate(obj, closure); if (Devirtualizer::do_metadata(closure)) { - Klass* klass = java_lang_Class::as_Klass_raw(obj); + Klass* klass = java_lang_Class::as_Klass(obj); // We'll get NULL for primitive mirrors. if (klass != NULL) { if (klass->class_loader_data() == NULL) { @@ -97,7 +97,7 @@ void InstanceMirrorKlass::oop_oop_iterate_statics_bounded(oop obj, OopClosureType* closure, MemRegion mr) { T* p = (T*)start_of_static_fields(obj); - T* end = p + java_lang_Class::static_oop_field_count_raw(obj); + T* end = p + java_lang_Class::static_oop_field_count(obj); T* const l = (T*)mr.start(); T* const h = (T*)mr.end(); @@ -123,7 +123,7 @@ void InstanceMirrorKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closu if (Devirtualizer::do_metadata(closure)) { if (mr.contains(obj)) { - Klass* klass = java_lang_Class::as_Klass_raw(obj); + Klass* klass = java_lang_Class::as_Klass(obj); // We'll get NULL for primitive mirrors. if (klass != NULL) { Devirtualizer::do_klass(closure, klass); diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index ac30fef4cd3..fed1ea21fde 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -188,7 +188,6 @@ void oopDesc::address_field_put(int offset, address value) { HeapAcce void oopDesc::release_address_field_put(int offset, address value) { HeapAccess::store_at(as_oop(), offset, value); } Metadata* oopDesc::metadata_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } -Metadata* oopDesc::metadata_field_raw(int offset) const { return RawAccess<>::load_at(as_oop(), offset); } void oopDesc::metadata_field_put(int offset, Metadata* value) { HeapAccess<>::store_at(as_oop(), offset, value); } Metadata* oopDesc::metadata_field_acquire(int offset) const { return HeapAccess::load_at(as_oop(), offset); } diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index 1dcae387b1f..607890cf1cc 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -162,7 +162,6 @@ class oopDesc { void obj_field_put_volatile(int offset, oop value); Metadata* metadata_field(int offset) const; - Metadata* metadata_field_raw(int offset) const; void metadata_field_put(int offset, Metadata* value); Metadata* metadata_field_acquire(int offset) const; @@ -180,7 +179,6 @@ class oopDesc { void bool_field_put_volatile(int offset, jboolean contents); jint int_field(int offset) const; - jint int_field_raw(int offset) const; void int_field_put(int offset, jint contents); jshort short_field(int offset) const; diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index 2459fc15155..1ea10633ac4 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -254,7 +254,6 @@ inline jshort oopDesc::short_field(int offset) const { return Hea inline void oopDesc::short_field_put(int offset, jshort value) { HeapAccess<>::store_at(as_oop(), offset, value); } inline jint oopDesc::int_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } -inline jint oopDesc::int_field_raw(int offset) const { return RawAccess<>::load_at(as_oop(), offset); } inline void oopDesc::int_field_put(int offset, jint value) { HeapAccess<>::store_at(as_oop(), offset, value); } inline jlong oopDesc::long_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } diff --git a/src/hotspot/share/oops/symbol.hpp b/src/hotspot/share/oops/symbol.hpp index c70b5e6f31d..7438045d1f2 100644 --- a/src/hotspot/share/oops/symbol.hpp +++ b/src/hotspot/share/oops/symbol.hpp @@ -45,8 +45,8 @@ // saved in persistent storage. This does not include the pointer // in the SymbolTable bucket (the _literal field in HashtableEntry) // that points to the Symbol. All other stores of a Symbol* -// to a field of a persistent variable (e.g., the _name filed in -// fieldDescriptor or _ptr in a CPSlot) is reference counted. +// to a field of a persistent variable (e.g., the _name field in +// fieldDescriptor or symbol in a constant pool) is reference counted. // // 1) The lookup of a "name" in the SymbolTable either creates a Symbol F for // "name" and returns a pointer to F or finds a pre-existing Symbol F for diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 7abd906f54a..d38c8a4b548 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -803,13 +803,6 @@ void CallGenerator::do_late_inline_helper() { C->set_default_node_notes(entry_nn); } - // Virtual call involves a receiver null check which can be made implicit. - if (is_virtual_late_inline()) { - GraphKit kit(jvms); - kit.null_check_receiver(); - jvms = kit.transfer_exceptions_into_jvms(); - } - // Now perform the inlining using the synthesized JVMState JVMState* new_jvms = inline_cg()->generate(jvms); if (new_jvms == NULL) return; // no change diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index 7692f385a5f..165153a222d 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -369,6 +369,7 @@ class LibraryCallKit : public GraphKit { }; bool arch_supports_vector(int op, int num_elem, BasicType type, VectorMaskUseType mask_use_type, bool has_scalar_args = false); + bool arch_supports_vector_rotate(int opc, int num_elem, BasicType elem_bt, bool has_scalar_args = false); void clear_upper_avx() { #ifdef X86 diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index af55530d54b..8700203c81e 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -240,8 +240,13 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exc if (VerifyLoopOptimizations && PrintOpto) { tty->print_cr("dominating test"); } // prevdom is the dominating projection of the dominating test. - assert( iff->is_If(), "" ); - assert(iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_RangeCheck, "Check this code when new subtype is added"); + assert(iff->is_If(), "must be"); + assert(iff->Opcode() == Op_If || + iff->Opcode() == Op_CountedLoopEnd || + iff->Opcode() == Op_LongCountedLoopEnd || + iff->Opcode() == Op_RangeCheck, + "Check this code when new subtype is added"); + int pop = prevdom->Opcode(); assert( pop == Op_IfFalse || pop == Op_IfTrue, "" ); if (flip) { diff --git a/src/hotspot/share/opto/macroArrayCopy.cpp b/src/hotspot/share/opto/macroArrayCopy.cpp index 22ca618ca76..1bb78199315 100644 --- a/src/hotspot/share/opto/macroArrayCopy.cpp +++ b/src/hotspot/share/opto/macroArrayCopy.cpp @@ -912,7 +912,9 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode* } _igvn.replace_node(_callprojs->fallthrough_memproj, out_mem); - _igvn.replace_node(_callprojs->fallthrough_ioproj, *io); + if (_callprojs->fallthrough_ioproj != NULL) { + _igvn.replace_node(_callprojs->fallthrough_ioproj, *io); + } _igvn.replace_node(_callprojs->fallthrough_catchproj, *ctrl); #ifdef ASSERT @@ -1185,8 +1187,14 @@ MergeMemNode* PhaseMacroExpand::generate_slow_arraycopy(ArrayCopyNode *ac, } transform_later(out_mem); - *io = _callprojs->fallthrough_ioproj->clone(); - transform_later(*io); + // When src is negative and arraycopy is before an infinite loop,_callprojs.fallthrough_ioproj + // could be NULL. Skip clone and update NULL fallthrough_ioproj. + if (_callprojs->fallthrough_ioproj != NULL) { + *io = _callprojs->fallthrough_ioproj->clone(); + transform_later(*io); + } else { + *io = NULL; + } return out_mem; } @@ -1501,7 +1509,9 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) { } _igvn.replace_node(_callprojs->fallthrough_memproj, merge_mem); - _igvn.replace_node(_callprojs->fallthrough_ioproj, io); + if (_callprojs->fallthrough_ioproj != NULL) { + _igvn.replace_node(_callprojs->fallthrough_ioproj, io); + } _igvn.replace_node(_callprojs->fallthrough_catchproj, ctrl); return; } diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 60977b023af..7850e19f16d 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2488,9 +2488,8 @@ void SuperWord::output() { } else if (VectorNode::is_scalar_rotate(n)) { Node* in1 = low_adr->in(1); Node* in2 = p->at(0)->in(2); - assert(in2->bottom_type()->isa_int(), "Shift must always be an int value"); // If rotation count is non-constant or greater than 8bit value create a vector. - if (!in2->is_Con() || -0x80 > in2->get_int() || in2->get_int() >= 0x80) { + if (!in2->is_Con() || !Matcher::supports_vector_constant_rotates(in2->get_int())) { in2 = vector_opd(p, 2); } vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n)); diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index d1a8ede4f5f..0e63e4aaa0b 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -59,6 +59,48 @@ static bool check_vbox(const TypeInstPtr* vbox_type) { } #endif +bool LibraryCallKit::arch_supports_vector_rotate(int opc, int num_elem, BasicType elem_bt, bool has_scalar_args) { + bool is_supported = true; + // has_scalar_args flag is true only for non-constant scalar shift count, + // since in this case shift needs to be broadcasted. + if (!Matcher::match_rule_supported_vector(opc, num_elem, elem_bt) || + (has_scalar_args && + !arch_supports_vector(VectorNode::replicate_opcode(elem_bt), num_elem, elem_bt, VecMaskNotUsed))) { + is_supported = false; + } + + int lshiftopc, rshiftopc; + switch(elem_bt) { + case T_BYTE: + lshiftopc = Op_LShiftI; + rshiftopc = Op_URShiftB; + break; + case T_SHORT: + lshiftopc = Op_LShiftI; + rshiftopc = Op_URShiftS; + break; + case T_INT: + lshiftopc = Op_LShiftI; + rshiftopc = Op_URShiftI; + break; + case T_LONG: + lshiftopc = Op_LShiftL; + rshiftopc = Op_URShiftL; + break; + default: + assert(false, "Unexpected type"); + } + int lshiftvopc = VectorNode::opcode(lshiftopc, elem_bt); + int rshiftvopc = VectorNode::opcode(rshiftopc, elem_bt); + if (!is_supported && + arch_supports_vector(lshiftvopc, num_elem, elem_bt, VecMaskNotUsed, has_scalar_args) && + arch_supports_vector(rshiftvopc, num_elem, elem_bt, VecMaskNotUsed, has_scalar_args) && + arch_supports_vector(Op_OrV, num_elem, elem_bt, VecMaskNotUsed)) { + is_supported = true; + } + return is_supported; +} + Node* GraphKit::box_vector(Node* vector, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool deoptimize_on_exception) { assert(EnableVectorSupport, ""); @@ -112,17 +154,29 @@ bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type return false; } - // Check that architecture supports this op-size-type combination. - if (!Matcher::match_rule_supported_vector(sopc, num_elem, type)) { + if (VectorNode::is_vector_rotate(sopc)) { + if(!arch_supports_vector_rotate(sopc, num_elem, type, has_scalar_args)) { #ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support it", - NodeClassNames[sopc], type2name(type), num_elem); - } + if (C->print_intrinsics()) { + tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support variable vector shifts", + NodeClassNames[sopc], type2name(type), num_elem); + } #endif - return false; + return false; + } } else { - assert(Matcher::match_rule_supported(sopc), "must be supported"); + // Check that architecture supports this op-size-type combination. + if (!Matcher::match_rule_supported_vector(sopc, num_elem, type)) { +#ifndef PRODUCT + if (C->print_intrinsics()) { + tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support it", + NodeClassNames[sopc], type2name(type), num_elem); + } +#endif + return false; + } else { + assert(Matcher::match_rule_supported(sopc), "must be supported"); + } } if (num_elem == 1) { @@ -1500,7 +1554,9 @@ bool LibraryCallKit::inline_vector_broadcast_int() { BasicType elem_bt = elem_type->basic_type(); int num_elem = vlen->get_con(); int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt); - if (opc == 0 || !VectorNode::is_shift_opcode(opc)) { + bool is_shift = VectorNode::is_shift_opcode(opc); + bool is_rotate = VectorNode::is_rotate_opcode(opc); + if (opc == 0 || (!is_shift && !is_rotate)) { if (C->print_intrinsics()) { tty->print_cr(" ** operation not supported: op=%d bt=%s", opr->get_con(), type2name(elem_bt)); } @@ -1513,10 +1569,16 @@ bool LibraryCallKit::inline_vector_broadcast_int() { } return false; // operation not supported } + Node* cnt = argument(5); ciKlass* vbox_klass = vector_klass->const_oop()->as_instance()->java_lang_Class_klass(); const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass); + const TypeInt* cnt_type = cnt->bottom_type()->isa_int(); - if (!arch_supports_vector(sopc, num_elem, elem_bt, VecMaskNotUsed, true /*has_scalar_args*/)) { + // If CPU supports vector constant rotate instructions pass it directly + bool is_const_rotate = is_rotate && cnt_type && cnt_type->is_con() && + Matcher::supports_vector_constant_rotates(cnt_type->get_con()); + bool has_scalar_args = is_rotate ? !is_const_rotate : true; + if (!arch_supports_vector(sopc, num_elem, elem_bt, VecMaskNotUsed, has_scalar_args)) { if (C->print_intrinsics()) { tty->print_cr(" ** not supported: arity=0 op=int/%d vlen=%d etype=%s ismask=no", sopc, num_elem, type2name(elem_bt)); @@ -1524,7 +1586,20 @@ bool LibraryCallKit::inline_vector_broadcast_int() { return false; // not supported } Node* opd1 = unbox_vector(argument(4), vbox_type, elem_bt, num_elem); - Node* opd2 = vector_shift_count(argument(5), opc, elem_bt, num_elem); + Node* opd2 = NULL; + if (is_shift) { + opd2 = vector_shift_count(cnt, opc, elem_bt, num_elem); + } else { + assert(is_rotate, "unexpected operation"); + if (!is_const_rotate) { + const Type * type_bt = Type::get_const_basic_type(elem_bt); + cnt = elem_bt == T_LONG ? gvn().transform(new ConvI2LNode(cnt)) : cnt; + opd2 = gvn().transform(VectorNode::scalar2vector(cnt, num_elem, type_bt)); + } else { + // Constant shift value. + opd2 = cnt; + } + } if (opd1 == NULL || opd2 == NULL) { return false; } diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index b51b0a51680..e9193d784ad 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -27,6 +27,7 @@ #include "opto/mulnode.hpp" #include "opto/subnode.hpp" #include "opto/vectornode.hpp" +#include "opto/convertnode.hpp" #include "utilities/powerOfTwo.hpp" #include "utilities/globalDefinitions.hpp" @@ -142,9 +143,9 @@ int VectorNode::opcode(int sopc, BasicType bt) { case Op_RoundDoubleMode: return (bt == T_DOUBLE ? Op_RoundDoubleModeV : 0); case Op_RotateLeft: - return (bt == T_LONG || bt == T_INT ? Op_RotateLeftV : 0); + return (is_integral_type(bt) ? Op_RotateLeftV : 0); case Op_RotateRight: - return (bt == T_LONG || bt == T_INT ? Op_RotateRightV : 0); + return (is_integral_type(bt) ? Op_RotateRightV : 0); case Op_SqrtF: return (bt == T_FLOAT ? Op_SqrtVF : 0); case Op_SqrtD: @@ -261,7 +262,7 @@ bool VectorNode::implemented(int opc, uint vlen, BasicType bt) { // For rotate operation we will do a lazy de-generation into // OrV/LShiftV/URShiftV pattern if the target does not support // vector rotation instruction. - if (vopc == Op_RotateLeftV || vopc == Op_RotateRightV) { + if (VectorNode::is_vector_rotate(vopc)) { return is_vector_rotate_supported(vopc, vlen, bt); } return vopc > 0 && Matcher::match_rule_supported_vector(vopc, vlen, bt); @@ -295,15 +296,8 @@ bool VectorNode::is_roundopD(Node* n) { return false; } -bool VectorNode::is_scalar_rotate(Node* n) { - if (n->Opcode() == Op_RotateLeft || n->Opcode() == Op_RotateRight) { - return true; - } - return false; -} - bool VectorNode::is_vector_rotate_supported(int vopc, uint vlen, BasicType bt) { - assert(vopc == Op_RotateLeftV || vopc == Op_RotateRightV, "wrong opcode"); + assert(VectorNode::is_vector_rotate(vopc), "wrong opcode"); // If target defines vector rotation patterns then no // need for degeneration. @@ -311,6 +305,14 @@ bool VectorNode::is_vector_rotate_supported(int vopc, uint vlen, BasicType bt) { return true; } + // If target does not support variable shift operations then no point + // in creating a rotate vector node since it will not be disintegratable. + // Adding a pessimistic check to avoid complex pattern mathing which + // may not be full proof. + if (!Matcher::supports_vector_variable_shifts()) { + return false; + } + // Validate existence of nodes created in case of rotate degeneration. switch (bt) { case T_INT: @@ -347,6 +349,23 @@ bool VectorNode::is_shift(Node* n) { return is_shift_opcode(n->Opcode()); } +bool VectorNode::is_rotate_opcode(int opc) { + switch (opc) { + case Op_RotateRight: + case Op_RotateLeft: + return true; + default: + return false; + } +} + +bool VectorNode::is_scalar_rotate(Node* n) { + if (is_rotate_opcode(n->Opcode())) { + return true; + } + return false; +} + bool VectorNode::is_vshift_cnt(Node* n) { switch (n->Opcode()) { case Op_LShiftCntV: @@ -578,6 +597,16 @@ VectorNode* VectorNode::shift_count(int opc, Node* cnt, uint vlen, BasicType bt) } } +bool VectorNode::is_vector_rotate(int opc) { + switch (opc) { + case Op_RotateLeftV: + case Op_RotateRightV: + return true; + default: + return false; + } +} + bool VectorNode::is_vector_shift(int opc) { assert(opc > _last_machine_leaf && opc < _last_opcode, "invalid opcode"); switch (opc) { @@ -1131,33 +1160,79 @@ MacroLogicVNode* MacroLogicVNode::make(PhaseGVN& gvn, Node* in1, Node* in2, Node Node* VectorNode::degenerate_vector_rotate(Node* src, Node* cnt, bool is_rotate_left, int vlen, BasicType bt, PhaseGVN* phase) { - assert(bt == T_INT || bt == T_LONG, "sanity"); + assert(is_integral_type(bt), "sanity"); const TypeVect* vt = TypeVect::make(bt, vlen); - int shift_mask = (bt == T_INT) ? 0x1F : 0x3F; - int shiftLOpc = (bt == T_INT) ? Op_LShiftI : Op_LShiftL; - int shiftROpc = (bt == T_INT) ? Op_URShiftI: Op_URShiftL; + int shift_mask = (type2aelembytes(bt) * 8) - 1; + int shiftLOpc = (bt == T_LONG) ? Op_LShiftL : Op_LShiftI; + auto urshiftopc = [=]() { + switch(bt) { + case T_INT: return Op_URShiftI; + case T_LONG: return Op_URShiftL; + case T_BYTE: return Op_URShiftB; + case T_SHORT: return Op_URShiftS; + default: return (Opcodes)0; + } + }; + int shiftROpc = urshiftopc(); // Compute shift values for right rotation and // later swap them in case of left rotation. Node* shiftRCnt = NULL; Node* shiftLCnt = NULL; - if (cnt->is_Con() && cnt->bottom_type()->isa_int()) { - // Constant shift case. - int shift = cnt->get_int() & shift_mask; + const TypeInt* cnt_type = cnt->bottom_type()->isa_int(); + bool is_binary_vector_op = false; + if (cnt_type && cnt_type->is_con()) { + // Constant shift. + int shift = cnt_type->get_con() & shift_mask; shiftRCnt = phase->intcon(shift); shiftLCnt = phase->intcon(shift_mask + 1 - shift); - } else { - // Variable shift case. - assert(VectorNode::is_invariant_vector(cnt), "Broadcast expected"); + } else if (VectorNode::is_invariant_vector(cnt)) { + // Scalar variable shift, handle replicates generated by auto vectorizer. cnt = cnt->in(1); if (bt == T_LONG) { // Shift count vector for Rotate vector has long elements too. - assert(cnt->Opcode() == Op_ConvI2L, "ConvI2L expected"); - cnt = cnt->in(1); + if (cnt->Opcode() == Op_ConvI2L) { + cnt = cnt->in(1); + } else { + assert(cnt->bottom_type()->isa_long() && + cnt->bottom_type()->is_long()->is_con(), "Long constant expected"); + cnt = phase->transform(new ConvL2INode(cnt)); + } } shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(shift_mask))); shiftLCnt = phase->transform(new SubINode(phase->intcon(shift_mask + 1), shiftRCnt)); + } else { + // Variable vector rotate count. + assert(Matcher::supports_vector_variable_shifts(), ""); + + int subVopc = 0; + int addVopc = 0; + Node* shift_mask_node = NULL; + Node* const_one_node = NULL; + + assert(cnt->bottom_type()->isa_vect(), "Unexpected shift"); + const Type* elem_ty = Type::get_const_basic_type(bt); + + if (bt == T_LONG) { + shift_mask_node = phase->longcon(shift_mask); + const_one_node = phase->longcon(1L); + subVopc = VectorNode::opcode(Op_SubL, bt); + addVopc = VectorNode::opcode(Op_AddL, bt); + } else { + shift_mask_node = phase->intcon(shift_mask); + const_one_node = phase->intcon(1); + subVopc = VectorNode::opcode(Op_SubI, bt); + addVopc = VectorNode::opcode(Op_AddI, bt); + } + Node* vector_mask = phase->transform(VectorNode::scalar2vector(shift_mask_node, vlen, elem_ty)); + Node* vector_one = phase->transform(VectorNode::scalar2vector(const_one_node, vlen, elem_ty)); + + shiftRCnt = cnt; + shiftRCnt = phase->transform(VectorNode::make(Op_AndV, shiftRCnt, vector_mask, vt)); + vector_mask = phase->transform(VectorNode::make(addVopc, vector_one, vector_mask, vt)); + shiftLCnt = phase->transform(VectorNode::make(subVopc, vector_mask, shiftRCnt, vt)); + is_binary_vector_op = true; } // Swap the computed left and right shift counts. @@ -1165,8 +1240,10 @@ Node* VectorNode::degenerate_vector_rotate(Node* src, Node* cnt, bool is_rotate_ swap(shiftRCnt,shiftLCnt); } - shiftLCnt = phase->transform(new LShiftCntVNode(shiftLCnt, vt)); - shiftRCnt = phase->transform(new RShiftCntVNode(shiftRCnt, vt)); + if (!is_binary_vector_op) { + shiftLCnt = phase->transform(new LShiftCntVNode(shiftLCnt, vt)); + shiftRCnt = phase->transform(new RShiftCntVNode(shiftRCnt, vt)); + } return new OrVNode(phase->transform(VectorNode::make(shiftLOpc, src, shiftLCnt, vlen, bt)), phase->transform(VectorNode::make(shiftROpc, src, shiftRCnt, vlen, bt)), diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 7ba0149777f..e3ba3dd91ef 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -76,6 +76,7 @@ class VectorNode : public TypeNode { static VectorNode* make(int vopc, Node* n1, Node* n2, Node* n3, const TypeVect* vt); static bool is_shift_opcode(int opc); + static bool is_rotate_opcode(int opc); static int opcode(int opc, BasicType bt); static int replicate_opcode(BasicType bt); @@ -87,7 +88,7 @@ class VectorNode : public TypeNode { static bool is_muladds2i(Node* n); static bool is_roundopD(Node* n); static bool is_scalar_rotate(Node* n); - static bool is_vector_rotate_supported(int vopc, uint vlen, BasicType bt); + static bool is_vector_rotate_supported(int opc, uint vlen, BasicType bt); static bool is_invariant_vector(Node* n); static bool is_all_ones_vector(Node* n); static bool is_vector_bitwise_not_pattern(Node* n); @@ -99,6 +100,7 @@ class VectorNode : public TypeNode { static bool is_vector_shift(int opc); static bool is_vector_shift_count(int opc); + static bool is_vector_rotate(int opc); static bool is_vector_shift(Node* n) { return is_vector_shift(n->Opcode()); diff --git a/src/hotspot/share/prims/jvmtiRawMonitor.cpp b/src/hotspot/share/prims/jvmtiRawMonitor.cpp index dde169ea1ad..3946dc4f40b 100644 --- a/src/hotspot/share/prims/jvmtiRawMonitor.cpp +++ b/src/hotspot/share/prims/jvmtiRawMonitor.cpp @@ -332,7 +332,7 @@ void JvmtiRawMonitor::raw_enter(Thread* self) { for (;;) { ExitOnSuspend eos(this); { - ThreadBlockInVMPreprocess tbivmp(jt, eos); + ThreadBlockInVMPreprocess tbivmp(jt, eos, true /* allow_suspend */); simple_enter(jt); } if (!eos.monitor_exited()) { @@ -384,7 +384,7 @@ int JvmtiRawMonitor::raw_wait(jlong millis, Thread* self) { for (;;) { ExitOnSuspend eos(this); { - ThreadBlockInVMPreprocess tbivmp(jt, eos); + ThreadBlockInVMPreprocess tbivmp(jt, eos, true /* allow_suspend */); simple_enter(jt); } if (!eos.monitor_exited()) { diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index be578539f4e..0b59f632408 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -374,6 +374,26 @@ int VectorSupport::vop2ideal(jint id, BasicType bt) { } break; } + case VECTOR_OP_LROTATE: { + switch (bt) { + case T_BYTE: // fall-through + case T_SHORT: // fall-through + case T_INT: // fall-through + case T_LONG: return Op_RotateLeft; + default: fatal("LROTATE: %s", type2name(bt)); + } + break; + } + case VECTOR_OP_RROTATE: { + switch (bt) { + case T_BYTE: // fall-through + case T_SHORT: // fall-through + case T_INT: // fall-through + case T_LONG: return Op_RotateRight; + default: fatal("RROTATE: %s", type2name(bt)); + } + break; + } case VECTOR_OP_MASK_LASTTRUE: { switch (bt) { case T_BYTE: // fall-through diff --git a/src/hotspot/share/prims/vectorSupport.hpp b/src/hotspot/share/prims/vectorSupport.hpp index 7a05fb47c9f..ac436a87976 100644 --- a/src/hotspot/share/prims/vectorSupport.hpp +++ b/src/hotspot/share/prims/vectorSupport.hpp @@ -83,6 +83,10 @@ class VectorSupport : AllStatic { VECTOR_OP_MASK_FIRSTTRUE = 20, VECTOR_OP_MASK_LASTTRUE = 21, + // Rotate operations + VECTOR_OP_LROTATE = 22, + VECTOR_OP_RROTATE = 23, + // Vector Math Library VECTOR_OP_TAN = 101, VECTOR_OP_TANH = 102, diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 3cc3a5bd1ba..b8c4dc9ccba 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -998,7 +998,7 @@ bool WhiteBox::validate_cgroup(const char* proc_cgroups, const char* proc_self_cgroup, const char* proc_self_mountinfo, u1* cg_flags) { - CgroupInfo cg_infos[4]; + CgroupInfo cg_infos[CG_INFO_LENGTH]; return CgroupSubsystemFactory::determine_type(cg_infos, proc_cgroups, proc_self_cgroup, proc_self_mountinfo, cg_flags); @@ -2026,12 +2026,20 @@ WB_ENTRY(jboolean, WB_IsShared(JNIEnv* env, jobject wb, jobject obj)) return Universe::heap()->is_archived_object(obj_oop); WB_END +WB_ENTRY(jboolean, WB_IsSharedInternedString(JNIEnv* env, jobject wb, jobject str)) + ResourceMark rm(THREAD); + oop str_oop = JNIHandles::resolve(str); + int length; + jchar* chars = java_lang_String::as_unicode_string(str_oop, length, CHECK_(false)); + return StringTable::lookup_shared(chars, length) == str_oop; +WB_END + WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz)) return (jboolean)MetaspaceShared::is_in_shared_metaspace(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); WB_END -WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env)) - return !HeapShared::closed_regions_mapped(); +WB_ENTRY(jboolean, WB_AreSharedStringsMapped(JNIEnv* env)) + return HeapShared::closed_regions_mapped(); WB_END WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz)) @@ -2721,8 +2729,9 @@ static JNINativeMethod methods[] = { (void*)&WB_GetDefaultArchivePath}, {CC"isSharingEnabled", CC"()Z", (void*)&WB_IsSharingEnabled}, {CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared }, + {CC"isSharedInternedString", CC"(Ljava/lang/String;)Z", (void*)&WB_IsSharedInternedString }, {CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass }, - {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored }, + {CC"areSharedStringsMapped", CC"()Z", (void*)&WB_AreSharedStringsMapped }, {CC"getResolvedReferences", CC"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)&WB_GetResolvedReferences}, {CC"linkClass", CC"(Ljava/lang/Class;)V", (void*)&WB_LinkClass}, {CC"areOpenArchiveHeapObjectsMapped", CC"()Z", (void*)&WB_AreOpenArchiveHeapObjectsMapped}, diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp index d7f40f39f2d..3315832e772 100644 --- a/src/hotspot/share/runtime/init.cpp +++ b/src/hotspot/share/runtime/init.cpp @@ -56,7 +56,6 @@ void check_ThreadShadow(); void eventlog_init(); void mutex_init(); void universe_oopstorage_init(); -void chunkpool_init(); void perfMemory_init(); void SuspendibleThreadSet_init(); @@ -104,7 +103,6 @@ void vm_init_globals() { eventlog_init(); mutex_init(); universe_oopstorage_init(); - chunkpool_init(); perfMemory_init(); SuspendibleThreadSet_init(); } diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp index 03bcc5c6892..0701881ccb7 100644 --- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp +++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp @@ -239,13 +239,13 @@ class ThreadToNativeFromVM : public ThreadStateTransition { // SafepointMechanism::process_if_requested when returning to the VM. This allows us // to perform an "undo" action if we might block processing a safepoint/handshake operation // (such as thread suspension). -template +template class ThreadBlockInVMPreprocess : public ThreadStateTransition { private: PRE_PROC& _pr; bool _allow_suspend; public: - ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr, bool allow_suspend = true) + ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr = emptyOp, bool allow_suspend = false) : ThreadStateTransition(thread), _pr(pr), _allow_suspend(allow_suspend) { assert(thread->thread_state() == _thread_in_vm, "coming from wrong thread state"); thread->check_possible_safepoint(); @@ -266,33 +266,12 @@ class ThreadBlockInVMPreprocess : public ThreadStateTransition { _thread->set_thread_state(_thread_in_vm); } -}; -class InFlightMutexRelease { - private: - Mutex** _in_flight_mutex_addr; - public: - InFlightMutexRelease(Mutex** in_flight_mutex_addr) : _in_flight_mutex_addr(in_flight_mutex_addr) {} - void operator()(JavaThread* current) { - if (_in_flight_mutex_addr != NULL && *_in_flight_mutex_addr != NULL) { - (*_in_flight_mutex_addr)->release_for_safepoint(); - *_in_flight_mutex_addr = NULL; - } - } + static void emptyOp(JavaThread* current) {} }; -// Parameter in_flight_mutex_addr is only used by class Mutex to avoid certain deadlock -// scenarios while making transitions that might block for a safepoint or handshake. -// It's the address of a pointer to the mutex we are trying to acquire. This will be used to -// access and release said mutex when transitioning back from blocked to vm (destructor) in -// case we need to stop for a safepoint or handshake. -class ThreadBlockInVM { - InFlightMutexRelease _ifmr; - ThreadBlockInVMPreprocess _tbivmpp; - public: - ThreadBlockInVM(JavaThread* thread, Mutex** in_flight_mutex_addr = NULL) - : _ifmr(in_flight_mutex_addr), _tbivmpp(thread, _ifmr, /* allow_suspend= */ false) {} -}; +typedef ThreadBlockInVMPreprocess<> ThreadBlockInVM; + // Debug class instantiated in JRT_ENTRY macro. // Can be used to verify properties on enter/exit of the VM. diff --git a/src/hotspot/share/runtime/mutex.cpp b/src/hotspot/share/runtime/mutex.cpp index 7d14f9ad81f..f56216a3018 100644 --- a/src/hotspot/share/runtime/mutex.cpp +++ b/src/hotspot/share/runtime/mutex.cpp @@ -33,6 +33,20 @@ #include "utilities/events.hpp" #include "utilities/macros.hpp" +class InFlightMutexRelease { + private: + Mutex* _in_flight_mutex; + public: + InFlightMutexRelease(Mutex* in_flight_mutex) : _in_flight_mutex(in_flight_mutex) { + assert(in_flight_mutex != NULL, "must be"); + } + void operator()(JavaThread* current) { + _in_flight_mutex->release_for_safepoint(); + _in_flight_mutex = NULL; + } + bool not_released() { return _in_flight_mutex != NULL; } +}; + #ifdef ASSERT void Mutex::check_block_state(Thread* thread) { if (!_allow_vm_block && thread->is_VM_thread()) { @@ -72,7 +86,6 @@ void Mutex::check_no_safepoint_state(Thread* thread) { #endif // ASSERT void Mutex::lock_contended(Thread* self) { - Mutex *in_flight_mutex = NULL; DEBUG_ONLY(int retry_cnt = 0;) bool is_active_Java_thread = self->is_active_Java_thread(); do { @@ -84,13 +97,14 @@ void Mutex::lock_contended(Thread* self) { // Is it a JavaThread participating in the safepoint protocol. if (is_active_Java_thread) { + InFlightMutexRelease ifmr(this); assert(rank() > Mutex::special, "Potential deadlock with special or lesser rank mutex"); - { ThreadBlockInVM tbivmdc(JavaThread::cast(self), &in_flight_mutex); - in_flight_mutex = this; // save for ~ThreadBlockInVM + { + ThreadBlockInVMPreprocess tbivmdc(JavaThread::cast(self), ifmr); _lock.lock(); } - if (in_flight_mutex != NULL) { - // Not unlocked by ~ThreadBlockInVM + if (ifmr.not_released()) { + // Not unlocked by ~ThreadBlockInVMPreprocess break; } } else { @@ -234,18 +248,17 @@ bool Monitor::wait(int64_t timeout) { check_safepoint_state(self); int wait_status; - Mutex* in_flight_mutex = NULL; + InFlightMutexRelease ifmr(this); { - ThreadBlockInVM tbivmdc(self, &in_flight_mutex); + ThreadBlockInVMPreprocess tbivmdc(self, ifmr); OSThreadWaitState osts(self->osthread(), false /* not Object.wait() */); wait_status = _lock.wait(timeout); - in_flight_mutex = this; // save for ~ThreadBlockInVM } - if (in_flight_mutex != NULL) { - // Not unlocked by ~ThreadBlockInVM + if (ifmr.not_released()) { + // Not unlocked by ~ThreadBlockInVMPreprocess assert_owner(NULL); // Conceptually reestablish ownership of the lock. set_owner(self); diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index ab7ad5b3469..75952da1e86 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -43,6 +43,7 @@ Mutex* Patching_lock = NULL; Mutex* CompiledMethod_lock = NULL; Monitor* SystemDictionary_lock = NULL; Mutex* SharedDictionary_lock = NULL; +Monitor* ClassInitError_lock = NULL; Mutex* Module_lock = NULL; Mutex* CompiledIC_lock = NULL; Mutex* InlineCacheBuffer_lock = NULL; @@ -256,6 +257,7 @@ void mutex_init() { def(SystemDictionary_lock , PaddedMonitor, leaf, true, _safepoint_check_always); def(SharedDictionary_lock , PaddedMutex , leaf, true, _safepoint_check_always); + def(ClassInitError_lock , PaddedMonitor, leaf+1, true, _safepoint_check_always); def(Module_lock , PaddedMutex , leaf+2, false, _safepoint_check_always); def(InlineCacheBuffer_lock , PaddedMutex , leaf, true, _safepoint_check_never); def(VMStatistic_lock , PaddedMutex , leaf, false, _safepoint_check_always); diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index 5a85427a6b3..cec0728e1cb 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -35,6 +35,7 @@ extern Mutex* Patching_lock; // a lock used to guard code pa extern Mutex* CompiledMethod_lock; // a lock used to guard a compiled method and OSR queues extern Monitor* SystemDictionary_lock; // a lock on the system dictionary extern Mutex* SharedDictionary_lock; // a lock on the CDS shared dictionary +extern Monitor* ClassInitError_lock; // a lock on the class initialization error table extern Mutex* Module_lock; // a lock on module and package related data structures extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access extern Mutex* InlineCacheBuffer_lock; // a lock used to guard the InlineCacheBuffer diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 42f9c668d25..e56b18a84c9 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -430,7 +430,7 @@ bool ObjectMonitor::enter(JavaThread* current) { for (;;) { ExitOnSuspend eos(this); { - ThreadBlockInVMPreprocess tbivs(current, eos); + ThreadBlockInVMPreprocess tbivs(current, eos, true /* allow_suspend */); EnterI(current); current->set_current_pending_monitor(NULL); // We can go to a safepoint at the end of this block. If we @@ -975,7 +975,7 @@ void ObjectMonitor::ReenterI(JavaThread* current, ObjectWaiter* currentNode) { { ClearSuccOnSuspend csos(this); - ThreadBlockInVMPreprocess tbivs(current, csos); + ThreadBlockInVMPreprocess tbivs(current, csos, true /* allow_suspend */); current->_ParkEvent->park(); } } @@ -1536,7 +1536,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { { ClearSuccOnSuspend csos(this); - ThreadBlockInVMPreprocess tbivs(current, csos); + ThreadBlockInVMPreprocess tbivs(current, csos, true /* allow_suspend */); if (interrupted || HAS_PENDING_EXCEPTION) { // Intentionally empty } else if (node._notified == 0) { diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 7d18f438b70..96bacaac99c 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -855,7 +855,7 @@ void JavaThread::collect_counters(jlong* array, int length) { for (int i = 0; i < length; i++) { array[i] = _jvmci_old_thread_counters[i]; } - for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) { + for (JavaThread* tp : ThreadsListHandle()) { if (jvmci_counters_include(tp)) { for (int i = 0; i < length; i++) { array[i] += tp->_jvmci_counters[i]; @@ -916,7 +916,7 @@ class VM_JVMCIResizeCounters : public VM_Operation { } // Now resize each threads array - for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) { + for (JavaThread* tp : ThreadsListHandle()) { if (!tp->resize_counters(JVMCICounterSize, _new_size)) { _failed = true; break; diff --git a/src/hotspot/share/runtime/threadSMR.hpp b/src/hotspot/share/runtime/threadSMR.hpp index 3dde3892ad5..0c8e92c12c1 100644 --- a/src/hotspot/share/runtime/threadSMR.hpp +++ b/src/hotspot/share/runtime/threadSMR.hpp @@ -328,6 +328,10 @@ class ThreadsListHandle : public StackObj { return _list_ptr.list(); } + using Iterator = ThreadsList::Iterator; + inline Iterator begin(); + inline Iterator end(); + template void threads_do(T *cl) const { return list()->threads_do(cl); diff --git a/src/hotspot/share/runtime/threadSMR.inline.hpp b/src/hotspot/share/runtime/threadSMR.inline.hpp index 993ac001a22..90486d1ac04 100644 --- a/src/hotspot/share/runtime/threadSMR.inline.hpp +++ b/src/hotspot/share/runtime/threadSMR.inline.hpp @@ -107,6 +107,9 @@ inline void ThreadsList::threads_do(T *cl) const { } } +ThreadsListHandle::Iterator ThreadsListHandle::begin() { return list()->begin(); } +ThreadsListHandle::Iterator ThreadsListHandle::end() { return list()->end(); } + // These three inlines are private to ThreadsSMRSupport, but // they are called by public inline update_tlh_stats() below: diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp index caf17d3a28d..ed406b1c77d 100644 --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -60,8 +60,8 @@ void VMOperationTimeoutTask::task() { if (is_armed()) { jlong delay = nanos_to_millis(os::javaTimeNanos() - _arm_time); if (delay > AbortVMOnVMOperationTimeoutDelay) { - fatal("VM operation took too long: " JLONG_FORMAT " ms elapsed since VM-op start (timeout: " INTX_FORMAT " ms)", - delay, AbortVMOnVMOperationTimeoutDelay); + fatal("%s VM operation took too long: " JLONG_FORMAT " ms elapsed since VM-op start (timeout: " INTX_FORMAT " ms)", + _vm_op_name, delay, AbortVMOnVMOperationTimeoutDelay); } } } @@ -70,13 +70,27 @@ bool VMOperationTimeoutTask::is_armed() { return Atomic::load_acquire(&_armed) != 0; } -void VMOperationTimeoutTask::arm() { +void VMOperationTimeoutTask::arm(const char* vm_op_name) { + _vm_op_name = vm_op_name; _arm_time = os::javaTimeNanos(); Atomic::release_store_fence(&_armed, 1); } void VMOperationTimeoutTask::disarm() { Atomic::release_store_fence(&_armed, 0); + + // The two stores to `_armed` are counted in VM-op, but they should be + // insignificant compared to the actual VM-op duration. + jlong vm_op_duration = nanos_to_millis(os::javaTimeNanos() - _arm_time); + + // Repeat the timeout-check logic on the VM thread, because + // VMOperationTimeoutTask might miss the arm-disarm window depending on + // the scheduling. + if (vm_op_duration > AbortVMOnVMOperationTimeoutDelay) { + fatal("%s VM operation took too long: completed in " JLONG_FORMAT " ms (timeout: " INTX_FORMAT " ms)", + _vm_op_name, vm_op_duration, AbortVMOnVMOperationTimeoutDelay); + } + _vm_op_name = nullptr; } //------------------------------------------------------------------------------------------------------------------ @@ -403,11 +417,12 @@ void VMThread::inner_execute(VM_Operation* op) { _cur_vm_operation->name()); bool end_safepoint = false; + bool has_timeout_task = (_timeout_task != nullptr); if (_cur_vm_operation->evaluate_at_safepoint() && !SafepointSynchronize::is_at_safepoint()) { SafepointSynchronize::begin(); - if (_timeout_task != NULL) { - _timeout_task->arm(); + if (has_timeout_task) { + _timeout_task->arm(_cur_vm_operation->name()); } end_safepoint = true; } @@ -415,7 +430,7 @@ void VMThread::inner_execute(VM_Operation* op) { evaluate_operation(_cur_vm_operation); if (end_safepoint) { - if (_timeout_task != NULL) { + if (has_timeout_task) { _timeout_task->disarm(); } SafepointSynchronize::end(); diff --git a/src/hotspot/share/runtime/vmThread.hpp b/src/hotspot/share/runtime/vmThread.hpp index e37189d586e..dd1965271e6 100644 --- a/src/hotspot/share/runtime/vmThread.hpp +++ b/src/hotspot/share/runtime/vmThread.hpp @@ -39,15 +39,15 @@ class VMOperationTimeoutTask : public PeriodicTask { private: volatile int _armed; jlong _arm_time; - + const char* _vm_op_name; public: VMOperationTimeoutTask(size_t interval_time) : - PeriodicTask(interval_time), _armed(0), _arm_time(0) {} + PeriodicTask(interval_time), _armed(0), _arm_time(0), _vm_op_name(nullptr) {} virtual void task(); bool is_armed(); - void arm(); + void arm(const char* vm_op_name); void disarm(); }; diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp index c1fa3481402..40a1906c1d8 100644 --- a/src/hotspot/share/services/heapDumper.cpp +++ b/src/hotspot/share/services/heapDumper.cpp @@ -1305,7 +1305,7 @@ class SymbolTableDumper : public SymbolClosure { void SymbolTableDumper::do_symbol(Symbol** p) { ResourceMark rm; - Symbol* sym = load_symbol(p); + Symbol* sym = *p; int len = sym->utf8_length(); if (len > 0) { char* s = sym->as_utf8(); diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java index 12cb4b04444..f47c49256bd 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java @@ -149,6 +149,11 @@ public long getMemorySoftLimit() { return subsystem.getMemorySoftLimit(); } + @Override + public long getPidsMax() { + return subsystem.getPidsMax(); + } + @Override public long getBlkIOServiceCount() { return subsystem.getBlkIOServiceCount(); diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java index 5013e9c378c..952de13e9f2 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java @@ -36,5 +36,13 @@ public interface CgroupSubsystem extends Metrics { * has determined that no limit is being imposed. */ public static final long LONG_RETVAL_UNLIMITED = -1; + public static final String MAX_VAL = "max"; + + public static long limitFromString(String strVal) { + if (strVal == null || MAX_VAL.equals(strVal)) { + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; + } + return Long.parseLong(strVal); + } } diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java index 931d0896079..94700af94f8 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java @@ -51,6 +51,7 @@ public class CgroupSubsystemFactory { private static final String CPUSET_CTRL = "cpuset"; private static final String BLKIO_CTRL = "blkio"; private static final String MEMORY_CTRL = "memory"; + private static final String PIDS_CTRL = "pids"; /* * From https://www.kernel.org/doc/Documentation/filesystems/proc.txt @@ -149,6 +150,7 @@ public static Optional determineType(String mountInfo, case CPUSET_CTRL: infos.put(CPUSET_CTRL, info); break; case MEMORY_CTRL: infos.put(MEMORY_CTRL, info); break; case BLKIO_CTRL: infos.put(BLKIO_CTRL, info); break; + case PIDS_CTRL: infos.put(PIDS_CTRL, info); break; } } @@ -194,9 +196,10 @@ public static Optional determineType(String mountInfo, if (isCgroupsV2) { action = (tokens -> setCgroupV2Path(infos, tokens)); } - selfCgroupLines.map(line -> line.split(":")) - .filter(tokens -> (tokens.length >= 3)) - .forEach(action); + // The limit value of 3 is because /proc/self/cgroup contains three + // colon-separated tokens per line. The last token, cgroup path, might + // contain a ':'. + selfCgroupLines.map(line -> line.split(":", 3)).forEach(action); } CgroupTypeResult result = new CgroupTypeResult(isCgroupsV2, @@ -251,6 +254,7 @@ private static void setCgroupV1Path(Map infos, case CPUACCT_CTRL: case CPU_CTRL: case BLKIO_CTRL: + case PIDS_CTRL: CgroupInfo info = infos.get(cName); info.setCgroupPath(cgroupPath); break; @@ -302,6 +306,7 @@ private static boolean amendCgroupInfos(String mntInfoLine, case MEMORY_CTRL: // fall-through case CPU_CTRL: case CPUACCT_CTRL: + case PIDS_CTRL: case BLKIO_CTRL: { CgroupInfo info = infos.get(controllerName); assert info.getMountPoint() == null; diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java index d10cfe091cf..0d293e09c53 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -38,6 +38,7 @@ public class CgroupV1Subsystem implements CgroupSubsystem, CgroupV1Metrics { private CgroupV1SubsystemController cpuacct; private CgroupV1SubsystemController cpuset; private CgroupV1SubsystemController blkio; + private CgroupV1SubsystemController pids; private static volatile CgroupV1Subsystem INSTANCE; @@ -126,6 +127,15 @@ private static CgroupV1Subsystem initSubSystem(Map infos) { } break; } + case "pids": { + if (info.getMountRoot() != null && info.getMountPoint() != null) { + CgroupV1SubsystemController controller = new CgroupV1SubsystemController(info.getMountRoot(), info.getMountPoint()); + controller.setPath(info.getCgroupPath()); + subsystem.setPidsController(controller); + anyActiveControllers = true; + } + break; + } default: throw new AssertionError("Unrecognized controller in infos: " + info.getName()); } @@ -170,6 +180,10 @@ private void setBlkIOController(CgroupV1SubsystemController blkio) { this.blkio = blkio; } + private void setPidsController(CgroupV1SubsystemController pids) { + this.pids = pids; + } + private static long getLongValue(CgroupSubsystemController controller, String parm) { return CgroupSubsystemController.getLongValue(controller, @@ -394,6 +408,13 @@ public long getMemorySoftLimit() { return CgroupV1SubsystemController.longValOrUnlimited(getLongValue(memory, "memory.soft_limit_in_bytes")); } + /***************************************************************** + * pids subsystem + ****************************************************************/ + public long getPidsMax() { + String pidsMaxStr = CgroupSubsystemController.getStringValue(pids, "pids.max"); + return CgroupSubsystem.limitFromString(pidsMaxStr); + } /***************************************************************** * BlKIO Subsystem diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java index 2d4e2bc78e4..5ffd22fb828 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Red Hat Inc. + * Copyright (c) 2020, 2021, Red Hat Inc. * 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,7 +45,6 @@ public class CgroupV2Subsystem implements CgroupSubsystem { private final CgroupSubsystemController unified; private static final String PROVIDER_NAME = "cgroupv2"; private static final int PER_CPU_SHARES = 1024; - private static final String MAX_VAL = "max"; private static final Object EMPTY_STR = ""; private static final long NO_SWAP = 0; @@ -149,14 +148,7 @@ private long getFromCpuMax(int tokenIdx) { return CgroupSubsystem.LONG_RETVAL_UNLIMITED; } String quota = tokens[tokenIdx]; - return limitFromString(quota); - } - - private long limitFromString(String strVal) { - if (strVal == null || MAX_VAL.equals(strVal)) { - return CgroupSubsystem.LONG_RETVAL_UNLIMITED; - } - return Long.parseLong(strVal); + return CgroupSubsystem.limitFromString(quota); } @Override @@ -251,7 +243,7 @@ public long getMemoryFailCount() { @Override public long getMemoryLimit() { String strVal = CgroupSubsystemController.getStringValue(unified, "memory.max"); - return limitFromString(strVal); + return CgroupSubsystem.limitFromString(strVal); } @Override @@ -279,7 +271,7 @@ public long getMemoryAndSwapLimit() { if (strVal == null) { return getMemoryLimit(); } - long swapLimit = limitFromString(strVal); + long swapLimit = CgroupSubsystem.limitFromString(strVal); if (swapLimit >= 0) { long memoryLimit = getMemoryLimit(); assert memoryLimit >= 0; @@ -310,7 +302,13 @@ public long getMemoryAndSwapUsage() { @Override public long getMemorySoftLimit() { String softLimitStr = CgroupSubsystemController.getStringValue(unified, "memory.low"); - return limitFromString(softLimitStr); + return CgroupSubsystem.limitFromString(softLimitStr); + } + + @Override + public long getPidsMax() { + String pidsMaxStr = CgroupSubsystemController.getStringValue(unified, "pids.max"); + return CgroupSubsystem.limitFromString(pidsMaxStr); } @Override diff --git a/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java b/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java index b7231649413..93eede032f1 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java @@ -201,8 +201,7 @@ private static int getNumOfUnit(String mode, int offset, int blockSize) if (mode.length() > offset) { int numInt; try { - Integer num = Integer.valueOf(mode.substring(offset)); - numInt = num.intValue(); + numInt = Integer.parseInt(mode.substring(offset)); result = numInt >> 3; } catch (NumberFormatException e) { throw new NoSuchAlgorithmException diff --git a/src/java.base/share/classes/java/io/BufferedInputStream.java b/src/java.base/share/classes/java/io/BufferedInputStream.java index 2131312aca1..5a4d379311e 100644 --- a/src/java.base/share/classes/java/io/BufferedInputStream.java +++ b/src/java.base/share/classes/java/io/BufferedInputStream.java @@ -328,7 +328,7 @@ private int read1(byte[] b, int off, int len) throws IOException { * invoking its {@link #close()} method, * or an I/O error occurs. */ - public synchronized int read(byte b[], int off, int len) + public synchronized int read(byte[] b, int off, int len) throws IOException { getBufIfOpen(); // Check for closed stream diff --git a/src/java.base/share/classes/java/io/BufferedOutputStream.java b/src/java.base/share/classes/java/io/BufferedOutputStream.java index b9aa659dbf7..b3e0797f84c 100644 --- a/src/java.base/share/classes/java/io/BufferedOutputStream.java +++ b/src/java.base/share/classes/java/io/BufferedOutputStream.java @@ -114,7 +114,7 @@ public synchronized void write(int b) throws IOException { * @throws IOException if an I/O error occurs. */ @Override - public synchronized void write(byte b[], int off, int len) throws IOException { + public synchronized void write(byte[] b, int off, int len) throws IOException { if (len >= buf.length) { /* If the request length exceeds the size of the output buffer, flush the output buffer and then write the data directly. diff --git a/src/java.base/share/classes/java/io/BufferedWriter.java b/src/java.base/share/classes/java/io/BufferedWriter.java index efd9f0002a1..99aaed6e1f1 100644 --- a/src/java.base/share/classes/java/io/BufferedWriter.java +++ b/src/java.base/share/classes/java/io/BufferedWriter.java @@ -166,7 +166,7 @@ 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 { + public void write(char[] cbuf, int off, int len) throws IOException { synchronized (lock) { ensureOpen(); if ((off < 0) || (off > cbuf.length) || (len < 0) || diff --git a/src/java.base/share/classes/java/io/ByteArrayInputStream.java b/src/java.base/share/classes/java/io/ByteArrayInputStream.java index 39401d6d452..1612104ac47 100644 --- a/src/java.base/share/classes/java/io/ByteArrayInputStream.java +++ b/src/java.base/share/classes/java/io/ByteArrayInputStream.java @@ -102,7 +102,7 @@ public class ByteArrayInputStream extends InputStream { * * @param buf the input buffer. */ - public ByteArrayInputStream(byte buf[]) { + public ByteArrayInputStream(byte[] buf) { this.buf = buf; this.pos = 0; this.count = buf.length; @@ -122,7 +122,7 @@ public ByteArrayInputStream(byte buf[]) { * @param offset the offset in the buffer of the first byte to read. * @param length the maximum number of bytes to read from the buffer. */ - public ByteArrayInputStream(byte buf[], int offset, int length) { + public ByteArrayInputStream(byte[] buf, int offset, int length) { this.buf = buf; this.pos = offset; this.count = Math.min(offset + length, buf.length); @@ -173,7 +173,7 @@ public synchronized int read() { * {@code len} is negative, or {@code len} is greater than * {@code b.length - off} */ - public synchronized int read(byte b[], int off, int len) { + public synchronized int read(byte[] b, int off, int len) { Objects.checkFromIndexSize(off, len, b.length); if (pos >= count) { diff --git a/src/java.base/share/classes/java/io/ByteArrayOutputStream.java b/src/java.base/share/classes/java/io/ByteArrayOutputStream.java index bc29c5c69b7..9e4f3d9a3ad 100644 --- a/src/java.base/share/classes/java/io/ByteArrayOutputStream.java +++ b/src/java.base/share/classes/java/io/ByteArrayOutputStream.java @@ -125,7 +125,7 @@ public synchronized void write(int b) { * {@code len} is negative, or {@code len} is greater than * {@code b.length - off} */ - public synchronized void write(byte b[], int off, int len) { + public synchronized void write(byte[] b, int off, int len) { Objects.checkFromIndexSize(off, len, b.length); ensureCapacity(count + len); System.arraycopy(b, off, buf, count, len); @@ -144,7 +144,7 @@ public synchronized void write(byte b[], int off, int len) { * @throws NullPointerException if {@code b} is {@code null}. * @since 11 */ - public void writeBytes(byte b[]) { + public void writeBytes(byte[] b) { write(b, 0, b.length); } diff --git a/src/java.base/share/classes/java/io/CharArrayWriter.java b/src/java.base/share/classes/java/io/CharArrayWriter.java index 5cdf8cd9551..a6091388c0a 100644 --- a/src/java.base/share/classes/java/io/CharArrayWriter.java +++ b/src/java.base/share/classes/java/io/CharArrayWriter.java @@ -96,7 +96,7 @@ public void write(int c) { * or {@code off + len} is negative or greater than the length * of the given array */ - public void write(char c[], int off, int len) { + public void write(char[] c, int off, int len) { if ((off < 0) || (off > c.length) || (len < 0) || ((off + len) > c.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java index d3c1f610f1f..ebc2b56e8be 100644 --- a/src/java.base/share/classes/java/io/Console.java +++ b/src/java.base/share/classes/java/io/Console.java @@ -475,7 +475,7 @@ public boolean ready() throws IOException { return in.ready(); } - public int read(char cbuf[], int offset, int length) + public int read(char[] cbuf, int offset, int length) throws IOException { int off = offset; diff --git a/src/java.base/share/classes/java/io/DataInput.java b/src/java.base/share/classes/java/io/DataInput.java index 5e438ea0dd6..b8088ff78da 100644 --- a/src/java.base/share/classes/java/io/DataInput.java +++ b/src/java.base/share/classes/java/io/DataInput.java @@ -196,7 +196,7 @@ public interface DataInput { * all the bytes. * @throws IOException if an I/O error occurs. */ - void readFully(byte b[]) throws IOException; + void readFully(byte[] b) throws IOException; /** * @@ -246,7 +246,7 @@ public interface DataInput { * all the bytes. * @throws IOException if an I/O error occurs. */ - void readFully(byte b[], int off, int len) throws IOException; + void readFully(byte[] b, int off, int len) throws IOException; /** * Makes an attempt to skip over diff --git a/src/java.base/share/classes/java/io/DataInputStream.java b/src/java.base/share/classes/java/io/DataInputStream.java index c8f49caa7fc..5941c50be9e 100644 --- a/src/java.base/share/classes/java/io/DataInputStream.java +++ b/src/java.base/share/classes/java/io/DataInputStream.java @@ -98,7 +98,7 @@ public DataInputStream(InputStream in) { * @see java.io.FilterInputStream#in * @see java.io.InputStream#read(byte[], int, int) */ - public final int read(byte b[]) throws IOException { + public final int read(byte[] b) throws IOException { return in.read(b, 0, b.length); } @@ -147,7 +147,7 @@ public final int read(byte b[]) throws IOException { * @see java.io.FilterInputStream#in * @see java.io.InputStream#read(byte[], int, int) */ - public final int read(byte b[], int off, int len) throws IOException { + public final int read(byte[] b, int off, int len) throws IOException { return in.read(b, off, len); } @@ -168,7 +168,7 @@ public final int read(byte b[], int off, int len) throws IOException { * another I/O error occurs. * @see java.io.FilterInputStream#in */ - public final void readFully(byte b[]) throws IOException { + public final void readFully(byte[] b) throws IOException { readFully(b, 0, b.length); } @@ -194,7 +194,7 @@ public final void readFully(byte b[]) throws IOException { * another I/O error occurs. * @see java.io.FilterInputStream#in */ - public final void readFully(byte b[], int off, int len) throws IOException { + public final void readFully(byte[] b, int off, int len) throws IOException { Objects.checkFromIndexSize(off, len, b.length); int n = 0; while (n < len) { diff --git a/src/java.base/share/classes/java/io/DataOutput.java b/src/java.base/share/classes/java/io/DataOutput.java index 2e22127b711..2706e2692c2 100644 --- a/src/java.base/share/classes/java/io/DataOutput.java +++ b/src/java.base/share/classes/java/io/DataOutput.java @@ -71,7 +71,7 @@ public interface DataOutput { * @param b the data. * @throws IOException if an I/O error occurs. */ - void write(byte b[]) throws IOException; + void write(byte[] b) throws IOException; /** * Writes {@code len} bytes from array @@ -93,7 +93,7 @@ public interface DataOutput { * @param len the number of bytes to write. * @throws IOException if an I/O error occurs. */ - void write(byte b[], int off, int len) throws IOException; + void write(byte[] b, int off, int len) throws IOException; /** * Writes a {@code boolean} value to this output stream. diff --git a/src/java.base/share/classes/java/io/DataOutputStream.java b/src/java.base/share/classes/java/io/DataOutputStream.java index 97e5c1f3c3e..f22b8617402 100644 --- a/src/java.base/share/classes/java/io/DataOutputStream.java +++ b/src/java.base/share/classes/java/io/DataOutputStream.java @@ -106,7 +106,7 @@ public synchronized void write(int b) throws IOException { * @throws IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ - public synchronized void write(byte b[], int off, int len) + public synchronized void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); diff --git a/src/java.base/share/classes/java/io/FileInputStream.java b/src/java.base/share/classes/java/io/FileInputStream.java index 1d078142512..8f65ad6238c 100644 --- a/src/java.base/share/classes/java/io/FileInputStream.java +++ b/src/java.base/share/classes/java/io/FileInputStream.java @@ -237,7 +237,7 @@ public int read() throws IOException { * @param len the number of bytes that are written * @throws IOException If an I/O error has occurred. */ - private native int readBytes(byte b[], int off, int len) throws IOException; + private native int readBytes(byte[] b, int off, int len) throws IOException; /** * Reads up to {@code b.length} bytes of data from this input @@ -250,7 +250,7 @@ public int read() throws IOException { * the file has been reached. * @throws IOException if an I/O error occurs. */ - public int read(byte b[]) throws IOException { + public int read(byte[] b) throws IOException { return readBytes(b, 0, b.length); } @@ -272,7 +272,7 @@ public int read(byte b[]) throws IOException { * {@code b.length - off} * @throws IOException if an I/O error occurs. */ - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { return readBytes(b, off, len); } @@ -354,6 +354,24 @@ public byte[] readNBytes(int len) throws IOException { return (capacity == nread) ? buf : Arrays.copyOf(buf, nread); } + /** + * {@inheritDoc} + */ + public long transferTo(OutputStream out) throws IOException { + long transferred = 0L; + if (out instanceof FileOutputStream fos) { + FileChannel fc = getChannel(); + long pos = fc.position(); + transferred = fc.transferTo(pos, Long.MAX_VALUE, fos.getChannel()); + long newPos = pos + transferred; + fc.position(newPos); + if (newPos >= fc.size()) { + return transferred; + } + } + return transferred + super.transferTo(out); + } + private long length() throws IOException { return length0(); } diff --git a/src/java.base/share/classes/java/io/FileOutputStream.java b/src/java.base/share/classes/java/io/FileOutputStream.java index 2e71b2bf700..ed5c2409d40 100644 --- a/src/java.base/share/classes/java/io/FileOutputStream.java +++ b/src/java.base/share/classes/java/io/FileOutputStream.java @@ -322,7 +322,7 @@ public void write(int b) throws IOException { * end of file * @throws IOException If an I/O error has occurred. */ - private native void writeBytes(byte b[], int off, int len, boolean append) + private native void writeBytes(byte[] b, int off, int len, boolean append) throws IOException; /** @@ -332,7 +332,7 @@ private native void writeBytes(byte b[], int off, int len, boolean append) * @param b the data. * @throws IOException if an I/O error occurs. */ - public void write(byte b[]) throws IOException { + public void write(byte[] b) throws IOException { writeBytes(b, 0, b.length, fdAccess.getAppend(fd)); } @@ -345,7 +345,7 @@ public void write(byte b[]) throws IOException { * @param len the number of bytes to write. * @throws IOException if an I/O error occurs. */ - public void write(byte b[], int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { writeBytes(b, off, len, fdAccess.getAppend(fd)); } diff --git a/src/java.base/share/classes/java/io/FilterInputStream.java b/src/java.base/share/classes/java/io/FilterInputStream.java index ef207a817e1..549e25e9c30 100644 --- a/src/java.base/share/classes/java/io/FilterInputStream.java +++ b/src/java.base/share/classes/java/io/FilterInputStream.java @@ -102,7 +102,7 @@ public int read() throws IOException { * @throws IOException if an I/O error occurs. * @see java.io.FilterInputStream#read(byte[], int, int) */ - public int read(byte b[]) throws IOException { + public int read(byte[] b) throws IOException { return read(b, 0, b.length); } @@ -128,7 +128,7 @@ public int read(byte b[]) throws IOException { * @throws IOException if an I/O error occurs. * @see java.io.FilterInputStream#in */ - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { return in.read(b, off, len); } diff --git a/src/java.base/share/classes/java/io/FilterOutputStream.java b/src/java.base/share/classes/java/io/FilterOutputStream.java index 3371a7ff882..93d76d39483 100644 --- a/src/java.base/share/classes/java/io/FilterOutputStream.java +++ b/src/java.base/share/classes/java/io/FilterOutputStream.java @@ -104,7 +104,7 @@ public void write(int b) throws IOException { * @see java.io.FilterOutputStream#write(byte[], int, int) */ @Override - public void write(byte b[]) throws IOException { + public void write(byte[] b) throws IOException { write(b, 0, b.length); } @@ -129,7 +129,7 @@ public void write(byte b[]) throws IOException { * @see java.io.FilterOutputStream#write(int) */ @Override - public void write(byte b[], int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { if ((off | len | (b.length - (len + off)) | (off + len)) < 0) throw new IndexOutOfBoundsException(); diff --git a/src/java.base/share/classes/java/io/FilterWriter.java b/src/java.base/share/classes/java/io/FilterWriter.java index c5dd6db8d02..023372d44f8 100644 --- a/src/java.base/share/classes/java/io/FilterWriter.java +++ b/src/java.base/share/classes/java/io/FilterWriter.java @@ -79,7 +79,7 @@ public void write(int c) throws IOException { * * @throws IOException If an I/O error occurs */ - public void write(char cbuf[], int off, int len) throws IOException { + public void write(char[] cbuf, int off, int len) throws IOException { out.write(cbuf, off, len); } diff --git a/src/java.base/share/classes/java/io/InputStream.java b/src/java.base/share/classes/java/io/InputStream.java index 075a595f132..b8867e8935c 100644 --- a/src/java.base/share/classes/java/io/InputStream.java +++ b/src/java.base/share/classes/java/io/InputStream.java @@ -214,7 +214,7 @@ public void close() throws IOException { * @throws NullPointerException if {@code b} is {@code null}. * @see java.io.InputStream#read(byte[], int, int) */ - public int read(byte b[]) throws IOException { + public int read(byte[] b) throws IOException { return read(b, 0, b.length); } @@ -275,7 +275,7 @@ public int read(byte b[]) throws IOException { * {@code b.length - off} * @see java.io.InputStream#read() */ - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { Objects.checkFromIndexSize(off, len, b.length); if (len == 0) { return 0; diff --git a/src/java.base/share/classes/java/io/LineNumberInputStream.java b/src/java.base/share/classes/java/io/LineNumberInputStream.java index a293d7ad043..eb04f499a5a 100644 --- a/src/java.base/share/classes/java/io/LineNumberInputStream.java +++ b/src/java.base/share/classes/java/io/LineNumberInputStream.java @@ -126,7 +126,7 @@ public int read() throws IOException { * @throws IOException if an I/O error occurs. * @see java.io.LineNumberInputStream#read() */ - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || diff --git a/src/java.base/share/classes/java/io/LineNumberReader.java b/src/java.base/share/classes/java/io/LineNumberReader.java index 7b3f749a6cf..a0d9df506ba 100644 --- a/src/java.base/share/classes/java/io/LineNumberReader.java +++ b/src/java.base/share/classes/java/io/LineNumberReader.java @@ -187,7 +187,7 @@ public int read() throws IOException { * @throws IOException {@inheritDoc} */ @SuppressWarnings("fallthrough") - public int read(char cbuf[], int off, int len) throws IOException { + public int read(char[] cbuf, int off, int len) throws IOException { synchronized (lock) { int n = super.read(cbuf, off, len); diff --git a/src/java.base/share/classes/java/io/ObjectInput.java b/src/java.base/share/classes/java/io/ObjectInput.java index c4098a2f458..fe80b377a0d 100644 --- a/src/java.base/share/classes/java/io/ObjectInput.java +++ b/src/java.base/share/classes/java/io/ObjectInput.java @@ -66,7 +66,7 @@ public Object readObject() * returned when the end of the stream is reached. * @throws IOException If an I/O error has occurred. */ - public int read(byte b[]) throws IOException; + public int read(byte[] b) throws IOException; /** * Reads into an array of bytes. This method will @@ -78,7 +78,7 @@ public Object readObject() * returned when the end of the stream is reached. * @throws IOException If an I/O error has occurred. */ - public int read(byte b[], int off, int len) throws IOException; + public int read(byte[] b, int off, int len) throws IOException; /** * Skips n bytes of input. diff --git a/src/java.base/share/classes/java/io/ObjectOutput.java b/src/java.base/share/classes/java/io/ObjectOutput.java index 8a825ade99d..bd4fde4beda 100644 --- a/src/java.base/share/classes/java/io/ObjectOutput.java +++ b/src/java.base/share/classes/java/io/ObjectOutput.java @@ -61,7 +61,7 @@ public void writeObject(Object obj) * @param b the data to be written * @throws IOException If an I/O error has occurred. */ - public void write(byte b[]) throws IOException; + public void write(byte[] b) throws IOException; /** * Writes a sub array of bytes. @@ -70,7 +70,7 @@ public void writeObject(Object obj) * @param len the number of bytes that are written * @throws IOException If an I/O error has occurred. */ - public void write(byte b[], int off, int len) throws IOException; + public void write(byte[] b, int off, int len) throws IOException; /** * Flushes the stream. This will write any buffered diff --git a/src/java.base/share/classes/java/io/OutputStream.java b/src/java.base/share/classes/java/io/OutputStream.java index bb96ddf3548..124a3e7365b 100644 --- a/src/java.base/share/classes/java/io/OutputStream.java +++ b/src/java.base/share/classes/java/io/OutputStream.java @@ -84,7 +84,7 @@ public void write(int b) throws IOException { } @Override - public void write(byte b[], int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { Objects.checkFromIndexSize(off, len, b.length); ensureOpen(); } @@ -123,7 +123,7 @@ public void close() { * @throws IOException if an I/O error occurs. * @see java.io.OutputStream#write(byte[], int, int) */ - public void write(byte b[]) throws IOException { + public void write(byte[] b) throws IOException { write(b, 0, b.length); } @@ -155,7 +155,7 @@ public void write(byte b[]) throws IOException { * an {@code IOException} is thrown if the output * stream is closed. */ - public void write(byte b[], int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { Objects.checkFromIndexSize(off, len, b.length); // len == 0 condition implicitly handled by loop bounds for (int i = 0 ; i < len ; i++) { diff --git a/src/java.base/share/classes/java/io/OutputStreamWriter.java b/src/java.base/share/classes/java/io/OutputStreamWriter.java index 62ea6881567..d513bcba2af 100644 --- a/src/java.base/share/classes/java/io/OutputStreamWriter.java +++ b/src/java.base/share/classes/java/io/OutputStreamWriter.java @@ -201,7 +201,7 @@ public void write(int c) throws IOException { * * @throws IOException If an I/O error occurs */ - public void write(char cbuf[], int off, int len) throws IOException { + public void write(char[] cbuf, int off, int len) throws IOException { se.write(cbuf, off, len); } diff --git a/src/java.base/share/classes/java/io/PipedInputStream.java b/src/java.base/share/classes/java/io/PipedInputStream.java index 5b35d78e4e7..88375166029 100644 --- a/src/java.base/share/classes/java/io/PipedInputStream.java +++ b/src/java.base/share/classes/java/io/PipedInputStream.java @@ -222,7 +222,7 @@ protected synchronized void receive(int b) throws IOException { * {@link #connect(java.io.PipedOutputStream) unconnected}, * closed,or if an I/O error occurs. */ - synchronized void receive(byte b[], int off, int len) throws IOException { + synchronized void receive(byte[] b, int off, int len) throws IOException { checkStateForReceive(); writeSide = Thread.currentThread(); int bytesToTransfer = len; @@ -364,7 +364,7 @@ public synchronized int read() throws IOException { * {@link #connect(java.io.PipedOutputStream) unconnected}, * closed, or if an I/O error occurs. */ - public synchronized int read(byte b[], int off, int len) throws IOException { + public synchronized int read(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { diff --git a/src/java.base/share/classes/java/io/PipedOutputStream.java b/src/java.base/share/classes/java/io/PipedOutputStream.java index 3ef14263d5e..67c3610a533 100644 --- a/src/java.base/share/classes/java/io/PipedOutputStream.java +++ b/src/java.base/share/classes/java/io/PipedOutputStream.java @@ -135,7 +135,7 @@ public void write(int b) throws IOException { * {@link #connect(java.io.PipedInputStream) unconnected}, * closed, or if an I/O error occurs. */ - public void write(byte b[], int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { var sink = this.sink; if (sink == null) { throw new IOException("Pipe not connected"); diff --git a/src/java.base/share/classes/java/io/PipedReader.java b/src/java.base/share/classes/java/io/PipedReader.java index 6dad73dd7c9..ea85089e0fa 100644 --- a/src/java.base/share/classes/java/io/PipedReader.java +++ b/src/java.base/share/classes/java/io/PipedReader.java @@ -202,7 +202,7 @@ synchronized void receive(int c) throws IOException { * Receives data into an array of characters. This method will * block until some input is available. */ - synchronized void receive(char c[], int off, int len) throws IOException { + synchronized void receive(char[] c, int off, int len) throws IOException { while (--len >= 0) { receive(c[off++]); } @@ -288,7 +288,7 @@ public synchronized int read() throws IOException { * {@link #connect(java.io.PipedWriter) unconnected}, closed, * or an I/O error occurs. */ - public synchronized int read(char cbuf[], int off, int len) throws IOException { + public synchronized int read(char[] cbuf, int off, int len) throws IOException { if (!connected) { throw new IOException("Pipe not connected"); } else if (closedByReader) { diff --git a/src/java.base/share/classes/java/io/PipedWriter.java b/src/java.base/share/classes/java/io/PipedWriter.java index eb09adc8ce6..a74a9c140b8 100644 --- a/src/java.base/share/classes/java/io/PipedWriter.java +++ b/src/java.base/share/classes/java/io/PipedWriter.java @@ -147,7 +147,7 @@ public void write(int c) throws IOException { * {@link #connect(java.io.PipedReader) unconnected}, closed * or an I/O error occurs. */ - public void write(char cbuf[], int off, int len) throws IOException { + public void write(char[] cbuf, int off, int len) throws IOException { if (sink == null) { throw new IOException("Pipe not connected"); } else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) { diff --git a/src/java.base/share/classes/java/io/PrintStream.java b/src/java.base/share/classes/java/io/PrintStream.java index f5d36e57466..163c860659a 100644 --- a/src/java.base/share/classes/java/io/PrintStream.java +++ b/src/java.base/share/classes/java/io/PrintStream.java @@ -561,7 +561,7 @@ public void write(int b) { * @param len Number of bytes to write */ @Override - public void write(byte buf[], int off, int len) { + public void write(byte[] buf, int off, int len) { try { synchronized (this) { ensureOpen(); @@ -612,7 +612,7 @@ public void write(byte buf[], int off, int len) { * @since 14 */ @Override - public void write(byte buf[]) throws IOException { + public void write(byte[] buf) throws IOException { this.write(buf, 0, buf.length); } @@ -634,7 +634,7 @@ public void write(byte buf[]) throws IOException { * * @since 14 */ - public void writeBytes(byte buf[]) { + public void writeBytes(byte[] buf) { this.write(buf, 0, buf.length); } @@ -845,7 +845,7 @@ public void print(double d) { * * @throws NullPointerException If {@code s} is {@code null} */ - public void print(char s[]) { + public void print(char[] s) { write(s); } diff --git a/src/java.base/share/classes/java/io/PrintWriter.java b/src/java.base/share/classes/java/io/PrintWriter.java index 67edd2c7bac..23e57cc2b2a 100644 --- a/src/java.base/share/classes/java/io/PrintWriter.java +++ b/src/java.base/share/classes/java/io/PrintWriter.java @@ -499,7 +499,7 @@ public void write(int c) { * cause the corresponding method of the underlying {@code Writer} * to throw an {@code IndexOutOfBoundsException} */ - public void write(char buf[], int off, int len) { + public void write(char[] buf, int off, int len) { try { synchronized (lock) { ensureOpen(); @@ -519,7 +519,7 @@ public void write(char buf[], int off, int len) { * Writer class because it must suppress I/O exceptions. * @param buf Array of characters to be written */ - public void write(char buf[]) { + public void write(char[] buf) { write(buf, 0, buf.length); } @@ -668,7 +668,7 @@ public void print(double d) { * * @throws NullPointerException If {@code s} is {@code null} */ - public void print(char s[]) { + public void print(char[] s) { write(s); } @@ -801,7 +801,7 @@ public void println(double x) { * * @param x the array of {@code char} values to be printed */ - public void println(char x[]) { + public void println(char[] x) { synchronized (lock) { print(x); println(); diff --git a/src/java.base/share/classes/java/io/RandomAccessFile.java b/src/java.base/share/classes/java/io/RandomAccessFile.java index 5443018ca8b..c1d3ce37370 100644 --- a/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -374,7 +374,7 @@ public int read() throws IOException { * @param len the number of bytes to read. * @throws IOException If an I/O error has occurred. */ - private native int readBytes(byte b[], int off, int len) throws IOException; + private native int readBytes(byte[] b, int off, int len) throws IOException; /** * Reads up to {@code len} bytes of data from this file into an @@ -401,7 +401,7 @@ public int read() throws IOException { * {@code len} is negative, or {@code len} is greater than * {@code b.length - off} */ - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { return readBytes(b, off, len); } @@ -424,7 +424,7 @@ public int read(byte b[], int off, int len) throws IOException { * or if some other I/O error occurs. * @throws NullPointerException If {@code b} is {@code null}. */ - public int read(byte b[]) throws IOException { + public int read(byte[] b) throws IOException { return readBytes(b, 0, b.length); } @@ -441,7 +441,7 @@ public int read(byte b[]) throws IOException { * all the bytes. * @throws IOException if an I/O error occurs. */ - public final void readFully(byte b[]) throws IOException { + public final void readFully(byte[] b) throws IOException { readFully(b, 0, b.length); } @@ -463,7 +463,7 @@ public final void readFully(byte b[]) throws IOException { * all the bytes. * @throws IOException if an I/O error occurs. */ - public final void readFully(byte b[], int off, int len) throws IOException { + public final void readFully(byte[] b, int off, int len) throws IOException { int n = 0; do { int count = this.read(b, off + n, len - n); @@ -532,7 +532,7 @@ public void write(int b) throws IOException { * @param len the number of bytes that are written * @throws IOException If an I/O error has occurred. */ - private native void writeBytes(byte b[], int off, int len) throws IOException; + private native void writeBytes(byte[] b, int off, int len) throws IOException; /** * Writes {@code b.length} bytes from the specified byte array @@ -541,7 +541,7 @@ public void write(int b) throws IOException { * @param b the data. * @throws IOException if an I/O error occurs. */ - public void write(byte b[]) throws IOException { + public void write(byte[] b) throws IOException { writeBytes(b, 0, b.length); } @@ -554,7 +554,7 @@ public void write(byte b[]) throws IOException { * @param len the number of bytes to write. * @throws IOException if an I/O error occurs. */ - public void write(byte b[], int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { writeBytes(b, off, len); } diff --git a/src/java.base/share/classes/java/io/SequenceInputStream.java b/src/java.base/share/classes/java/io/SequenceInputStream.java index 441b4ad970c..8eea5ab6098 100644 --- a/src/java.base/share/classes/java/io/SequenceInputStream.java +++ b/src/java.base/share/classes/java/io/SequenceInputStream.java @@ -184,7 +184,7 @@ public int read() throws IOException { * greater than {@code b.length - off} * @throws IOException if an I/O error occurs. */ - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { if (in == null) { return -1; } else if (b == null) { diff --git a/src/java.base/share/classes/java/io/StringBufferInputStream.java b/src/java.base/share/classes/java/io/StringBufferInputStream.java index 1665ae6b48b..75643e86c39 100644 --- a/src/java.base/share/classes/java/io/StringBufferInputStream.java +++ b/src/java.base/share/classes/java/io/StringBufferInputStream.java @@ -108,7 +108,7 @@ public synchronized int read() { * the stream has been reached. */ @SuppressWarnings("deprecation") - public synchronized int read(byte b[], int off, int len) { + public synchronized int read(byte[] b, int off, int len) { if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || diff --git a/src/java.base/share/classes/java/io/StringWriter.java b/src/java.base/share/classes/java/io/StringWriter.java index 30654230ca6..3491490cf99 100644 --- a/src/java.base/share/classes/java/io/StringWriter.java +++ b/src/java.base/share/classes/java/io/StringWriter.java @@ -89,7 +89,7 @@ public void write(int c) { * or {@code off + len} is negative or greater than the length * of the given array */ - public void write(char cbuf[], int off, int len) { + public void write(char[] cbuf, int off, int len) { if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); diff --git a/src/java.base/share/classes/java/io/Writer.java b/src/java.base/share/classes/java/io/Writer.java index 09a9bd975f3..03f5da835a3 100644 --- a/src/java.base/share/classes/java/io/Writer.java +++ b/src/java.base/share/classes/java/io/Writer.java @@ -209,7 +209,7 @@ public void write(int c) throws IOException { * @throws IOException * If an I/O error occurs */ - public void write(char cbuf[]) throws IOException { + public void write(char[] cbuf) throws IOException { write(cbuf, 0, cbuf.length); } @@ -234,7 +234,7 @@ public void write(char cbuf[]) throws IOException { * @throws IOException * If an I/O error occurs */ - public abstract void write(char cbuf[], int off, int len) throws IOException; + public abstract void write(char[] cbuf, int off, int len) throws IOException; /** * Writes a string. diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index d2aad947513..ff075f144ca 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -349,10 +349,11 @@ public void setLength(int newLength) { */ @Override public char charAt(int index) { + checkIndex(index, count); if (isLatin1()) { - return StringLatin1.charAt(value, index); + return (char)(value[index] & 0xff); } - return StringUTF16.charAt(value, index); + return StringUTF16.getChar(value, index); } /** diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java index 71026e534df..7d200e7edf5 100644 --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -1413,7 +1413,7 @@ public static Integer decode(String nm) throws NumberFormatException { int radix = 10; int index = 0; boolean negative = false; - Integer result; + int result; if (nm.isEmpty()) throw new NumberFormatException("Zero length string"); @@ -1443,15 +1443,15 @@ else if (nm.startsWith("0", index) && nm.length() > 1 + index) { throw new NumberFormatException("Sign character in wrong position"); try { - result = Integer.valueOf(nm.substring(index), radix); - result = negative ? Integer.valueOf(-result.intValue()) : result; + result = parseInt(nm, index, nm.length(), radix); + result = negative ? -result : result; } catch (NumberFormatException e) { // If number is Integer.MIN_VALUE, we'll end up here. The next line // handles this case, and causes any genuine format error to be // rethrown. String constant = negative ? ("-" + nm.substring(index)) : nm.substring(index); - result = Integer.valueOf(constant, radix); + result = parseInt(constant, radix); } return result; } diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java index 33ed47def1d..630b9e242b8 100644 --- a/src/java.base/share/classes/java/lang/Long.java +++ b/src/java.base/share/classes/java/lang/Long.java @@ -1254,7 +1254,7 @@ public static Long decode(String nm) throws NumberFormatException { int radix = 10; int index = 0; boolean negative = false; - Long result; + long result; if (nm.isEmpty()) throw new NumberFormatException("Zero length string"); @@ -1284,15 +1284,15 @@ else if (nm.startsWith("0", index) && nm.length() > 1 + index) { throw new NumberFormatException("Sign character in wrong position"); try { - result = Long.valueOf(nm.substring(index), radix); - result = negative ? Long.valueOf(-result.longValue()) : result; + result = parseLong(nm, index, nm.length(), radix); + result = negative ? -result : result; } catch (NumberFormatException e) { // If number is Long.MIN_VALUE, we'll end up here. The next line // handles this case, and causes any genuine format error to be // rethrown. String constant = negative ? ("-" + nm.substring(index)) : nm.substring(index); - result = Long.valueOf(constant, radix); + result = parseLong(constant, radix); } return result; } diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java index 4f69b67a058..02074573fc8 100644 --- a/src/java.base/share/classes/java/lang/Math.java +++ b/src/java.base/share/classes/java/lang/Math.java @@ -1247,7 +1247,7 @@ public static long unsignedMultiplyHigh(long x, long y) { /** * Returns the largest (closest to positive infinity) * {@code int} value that is less than or equal to the algebraic quotient. - * There is one special case, if the dividend is the + * There is one special case: if the dividend is * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1}, * then integer overflow occurs and * the result is equal to {@code Integer.MIN_VALUE}. @@ -1256,14 +1256,16 @@ public static long unsignedMultiplyHigh(long x, long y) { * (truncation). This operation instead acts under the round toward * negative infinity (floor) rounding mode. * The floor rounding mode gives different results from truncation - * when the exact result is negative. + * when the exact quotient is not an integer and is negative. *
    *
  • If the signs of the arguments are the same, the results of * {@code floorDiv} and the {@code /} operator are the same.
    * For example, {@code floorDiv(4, 3) == 1} and {@code (4 / 3) == 1}.
  • - *
  • If the signs of the arguments are different, the quotient is negative and - * {@code floorDiv} returns the integer less than or equal to the quotient - * and the {@code /} operator returns the integer closest to zero.
    + *
  • If the signs of the arguments are different, {@code floorDiv} + * returns the largest integer less than or equal to the quotient + * while the {@code /} operator returns the smallest integer greater + * than or equal to the quotient. + * They differ if and only if the quotient is not an integer.
    * For example, {@code floorDiv(-4, 3) == -2}, * whereas {@code (-4 / 3) == -1}. *
  • @@ -1290,7 +1292,7 @@ public static int floorDiv(int x, int y) { /** * Returns the largest (closest to positive infinity) * {@code long} value that is less than or equal to the algebraic quotient. - * There is one special case, if the dividend is the + * There is one special case: if the dividend is * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1}, * then integer overflow occurs and * the result is equal to {@code Long.MIN_VALUE}. @@ -1299,7 +1301,7 @@ public static int floorDiv(int x, int y) { * (truncation). This operation instead acts under the round toward * negative infinity (floor) rounding mode. * The floor rounding mode gives different results from truncation - * when the exact result is negative. + * when the exact result is not an integer and is negative. *

    * For examples, see {@link #floorDiv(int, int)}. * @@ -1319,7 +1321,7 @@ public static long floorDiv(long x, int y) { /** * Returns the largest (closest to positive infinity) * {@code long} value that is less than or equal to the algebraic quotient. - * There is one special case, if the dividend is the + * There is one special case: if the dividend is * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1}, * then integer overflow occurs and * the result is equal to {@code Long.MIN_VALUE}. @@ -1328,7 +1330,7 @@ public static long floorDiv(long x, int y) { * (truncation). This operation instead acts under the round toward * negative infinity (floor) rounding mode. * The floor rounding mode gives different results from truncation - * when the exact result is negative. + * when the exact result is not an integer and is negative. *

    * For examples, see {@link #floorDiv(int, int)}. * @@ -1353,40 +1355,34 @@ public static long floorDiv(long x, long y) { /** * Returns the floor modulus of the {@code int} arguments. *

    - * The floor modulus is {@code x - (floorDiv(x, y) * y)}, - * has the same sign as the divisor {@code y}, and + * The floor modulus is {@code r = x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y} or is zero, and * is in the range of {@code -abs(y) < r < +abs(y)}. * *

    * The relationship between {@code floorDiv} and {@code floorMod} is such that: *

      - *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x} + *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x}
    • *
    *

    - * The difference in values between {@code floorMod} and - * the {@code %} operator is due to the difference between - * {@code floorDiv} that returns the integer less than or equal to the quotient - * and the {@code /} operator that returns the integer closest to zero. + * The difference in values between {@code floorMod} and the {@code %} operator + * is due to the difference between {@code floorDiv} and the {@code /} + * operator, as detailed in {@linkplain #floorDiv(int, int)}. *

    * Examples: *

      - *
    • If the signs of the arguments are the same, the results - * of {@code floorMod} and the {@code %} operator are the same.
      + *
    • Regardless of the signs of the arguments, {@code floorMod}(x, y) + * is zero exactly when {@code x % y} is zero as well.
    • + *
    • If neither of {@code floorMod}(x, y) or {@code x % y} is zero, + * their results differ exactly when the signs of the arguments differ.
      *
        *
      • {@code floorMod(+4, +3) == +1};   and {@code (+4 % +3) == +1}
      • *
      • {@code floorMod(-4, -3) == -1};   and {@code (-4 % -3) == -1}
      • - *
      - *
    • If the signs of the arguments are different, the results - * differ from the {@code %} operator.
      - *
        *
      • {@code floorMod(+4, -3) == -2};   and {@code (+4 % -3) == +1}
      • *
      • {@code floorMod(-4, +3) == +2};   and {@code (-4 % +3) == -1}
      • *
      *
    • *
    - *

    - * If the signs of arguments are unknown and a positive modulus - * is needed it can be computed as {@code (floorMod(x, y) + abs(y)) % abs(y)}. * * @param x the dividend * @param y the divisor @@ -1398,7 +1394,7 @@ public static long floorDiv(long x, long y) { public static int floorMod(int x, int y) { int mod = x % y; // if the signs are different and modulo not zero, adjust result - if ((mod ^ y) < 0 && mod != 0) { + if ((x ^ y) < 0 && mod != 0) { mod += y; } return mod; @@ -1407,14 +1403,14 @@ public static int floorMod(int x, int y) { /** * Returns the floor modulus of the {@code long} and {@code int} arguments. *

    - * The floor modulus is {@code x - (floorDiv(x, y) * y)}, - * has the same sign as the divisor {@code y}, and + * The floor modulus is {@code r = x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y} or is zero, and * is in the range of {@code -abs(y) < r < +abs(y)}. * *

    * The relationship between {@code floorDiv} and {@code floorMod} is such that: *

      - *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x} + *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x}
    • *
    *

    * For examples, see {@link #floorMod(int, int)}. @@ -1434,14 +1430,14 @@ public static int floorMod(long x, int y) { /** * Returns the floor modulus of the {@code long} arguments. *

    - * The floor modulus is {@code x - (floorDiv(x, y) * y)}, - * has the same sign as the divisor {@code y}, and + * The floor modulus is {@code r = x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y} or is zero, and * is in the range of {@code -abs(y) < r < +abs(y)}. * *

    * The relationship between {@code floorDiv} and {@code floorMod} is such that: *

      - *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x} + *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x}
    • *
    *

    * For examples, see {@link #floorMod(int, int)}. diff --git a/src/java.base/share/classes/java/lang/Runtime.java b/src/java.base/share/classes/java/lang/Runtime.java index 3705705c92a..7948ebffb63 100644 --- a/src/java.base/share/classes/java/lang/Runtime.java +++ b/src/java.base/share/classes/java/lang/Runtime.java @@ -449,7 +449,7 @@ public Process exec(String command, String[] envp, File dir) * * @see ProcessBuilder */ - public Process exec(String cmdarray[]) throws IOException { + public Process exec(String[] cmdarray) throws IOException { return exec(cmdarray, null, null); } diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index 427fa7080ba..062e3fd3709 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -1051,10 +1051,10 @@ public static long unsignedMultiplyHigh(long x, long y) { /** * Returns the largest (closest to positive infinity) * {@code int} value that is less than or equal to the algebraic quotient. - * There is one special case, if the dividend is the + * There is one special case: if the dividend is * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1}, * then integer overflow occurs and - * the result is equal to the {@code Integer.MIN_VALUE}. + * the result is equal to {@code Integer.MIN_VALUE}. *

    * See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and * a comparison to the integer division {@code /} operator. @@ -1075,7 +1075,7 @@ public static int floorDiv(int x, int y) { /** * Returns the largest (closest to positive infinity) * {@code long} value that is less than or equal to the algebraic quotient. - * There is one special case, if the dividend is the + * There is one special case: if the dividend is * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1}, * then integer overflow occurs and * the result is equal to {@code Long.MIN_VALUE}. @@ -1099,10 +1099,10 @@ public static long floorDiv(long x, int y) { /** * Returns the largest (closest to positive infinity) * {@code long} value that is less than or equal to the algebraic quotient. - * There is one special case, if the dividend is the + * There is one special case: if the dividend is * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1}, * then integer overflow occurs and - * the result is equal to the {@code Long.MIN_VALUE}. + * the result is equal to {@code Long.MIN_VALUE}. *

    * See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and * a comparison to the integer division {@code /} operator. @@ -1123,13 +1123,14 @@ public static long floorDiv(long x, long y) { /** * Returns the floor modulus of the {@code int} arguments. *

    - * The floor modulus is {@code x - (floorDiv(x, y) * y)}, - * has the same sign as the divisor {@code y}, and + * The floor modulus is {@code r = x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y} or is zero, and * is in the range of {@code -abs(y) < r < +abs(y)}. + * *

    * The relationship between {@code floorDiv} and {@code floorMod} is such that: *

      - *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x} + *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x}
    • *
    *

    * See {@link Math#floorMod(int, int) Math.floorMod} for examples and @@ -1150,14 +1151,14 @@ public static int floorMod(int x, int y) { /** * Returns the floor modulus of the {@code long} and {@code int} arguments. *

    - * The floor modulus is {@code x - (floorDiv(x, y) * y)}, - * has the same sign as the divisor {@code y}, and + * The floor modulus is {@code r = x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y} or is zero, and * is in the range of {@code -abs(y) < r < +abs(y)}. * *

    * The relationship between {@code floorDiv} and {@code floorMod} is such that: *

      - *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x} + *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x}
    • *
    *

    * See {@link Math#floorMod(int, int) Math.floorMod} for examples and @@ -1178,13 +1179,14 @@ public static int floorMod(long x, int y) { /** * Returns the floor modulus of the {@code long} arguments. *

    - * The floor modulus is {@code x - (floorDiv(x, y) * y)}, - * has the same sign as the divisor {@code y}, and + * The floor modulus is {@code r = x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y} or is zero, and * is in the range of {@code -abs(y) < r < +abs(y)}. + * *

    * The relationship between {@code floorDiv} and {@code floorMod} is such that: *

      - *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x} + *
    • {@code floorDiv(x, y) * y + floorMod(x, y) == x}
    • *
    *

    * See {@link Math#floorMod(int, int) Math.floorMod} for examples and diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index d404be2e7b8..847d58e819a 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -272,7 +272,7 @@ public String(String original) { * @param value * The initial value of the string */ - public String(char value[]) { + public String(char[] value) { this(value, 0, value.length, null); } @@ -297,7 +297,7 @@ public String(char value[]) { * If {@code offset} is negative, {@code count} is negative, or * {@code offset} is greater than {@code value.length - count} */ - public String(char value[], int offset, int count) { + public String(char[] value, int offset, int count) { this(value, offset, count, rangeCheck(value, offset, count)); } @@ -394,7 +394,7 @@ public String(int[] codePoints, int offset, int count) { * @see #String(byte[]) */ @Deprecated(since="1.1") - public String(byte ascii[], int hibyte, int offset, int count) { + public String(byte[] ascii, int hibyte, int offset, int count) { checkBoundsOffCount(offset, count, ascii.length); if (count == 0) { this.value = "".value; @@ -446,7 +446,7 @@ public String(byte ascii[], int hibyte, int offset, int count) { * @see #String(byte[]) */ @Deprecated(since="1.1") - public String(byte ascii[], int hibyte) { + public String(byte[] ascii, int hibyte) { this(ascii, hibyte, 0, ascii.length); } @@ -1354,7 +1354,7 @@ private static byte[] encodeUTF8_UTF16(byte[] val, boolean doReplace) { * * @since 1.1 */ - public String(byte bytes[], String charsetName) + public String(byte[] bytes, String charsetName) throws UnsupportedEncodingException { this(bytes, 0, bytes.length, charsetName); } @@ -1379,7 +1379,7 @@ public String(byte bytes[], String charsetName) * * @since 1.6 */ - public String(byte bytes[], Charset charset) { + public String(byte[] bytes, Charset charset) { this(bytes, 0, bytes.length, charset); } @@ -1665,7 +1665,7 @@ public int offsetByCodePoints(int index, int codePointOffset) { *

  • {@code dstBegin+(srcEnd-srcBegin)} is larger than * {@code dst.length}
*/ - public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { + public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { checkBoundsBeginEnd(srcBegin, srcEnd, length()); checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length); if (isLatin1()) { @@ -1719,7 +1719,7 @@ public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { * */ @Deprecated(since="1.1") - public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) { + public void getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) { checkBoundsBeginEnd(srcBegin, srcEnd, length()); Objects.requireNonNull(dst); checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length); @@ -4221,7 +4221,7 @@ public static String valueOf(Object obj) { * @return a {@code String} that contains the characters of the * character array. */ - public static String valueOf(char data[]) { + public static String valueOf(char[] data) { return new String(data); } @@ -4245,7 +4245,7 @@ public static String valueOf(char data[]) { * {@code offset+count} is larger than * {@code data.length}. */ - public static String valueOf(char data[], int offset, int count) { + public static String valueOf(char[] data, int offset, int count) { return new String(data, offset, count); } @@ -4262,7 +4262,7 @@ public static String valueOf(char data[], int offset, int count) { * {@code offset+count} is larger than * {@code data.length}. */ - public static String copyValueOf(char data[], int offset, int count) { + public static String copyValueOf(char[] data, int offset, int count) { return new String(data, offset, count); } @@ -4273,7 +4273,7 @@ public static String copyValueOf(char data[], int offset, int count) { * @return a {@code String} that contains the characters of the * character array. */ - public static String copyValueOf(char data[]) { + public static String copyValueOf(char[] data) { return new String(data); } diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java b/src/java.base/share/classes/java/lang/StringBuffer.java index a4299192966..e2ca48fdaf6 100644 --- a/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/src/java.base/share/classes/java/lang/StringBuffer.java @@ -773,7 +773,7 @@ private void readObject(java.io.ObjectInputStream s) count = fields.get("count", 0); } - synchronized void getBytes(byte dst[], int dstBegin, byte coder) { + synchronized void getBytes(byte[] dst, int dstBegin, byte coder) { super.getBytes(dst, dstBegin, coder); } } diff --git a/src/java.base/share/classes/java/lang/StringLatin1.java b/src/java.base/share/classes/java/lang/StringLatin1.java index 63e906c1dc4..875d79b6f64 100644 --- a/src/java.base/share/classes/java/lang/StringLatin1.java +++ b/src/java.base/share/classes/java/lang/StringLatin1.java @@ -79,11 +79,11 @@ public static byte[] inflate(byte[] value, int off, int len) { return ret; } - public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) { + public static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) { inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); } - public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) { + public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte[] dst, int dstBegin) { System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); } diff --git a/src/java.base/share/classes/java/lang/StringUTF16.java b/src/java.base/share/classes/java/lang/StringUTF16.java index 6f3aff9e48e..29287aaa22c 100644 --- a/src/java.base/share/classes/java/lang/StringUTF16.java +++ b/src/java.base/share/classes/java/lang/StringUTF16.java @@ -247,7 +247,7 @@ static byte[] toBytesSupplementary(int cp) { } @IntrinsicCandidate - public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) { + public static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) { // We need a range check here because 'getChar' has no checks if (srcBegin < srcEnd) { checkBoundsOffCount(srcBegin, srcEnd - srcBegin, value); @@ -258,7 +258,7 @@ public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], } /* @see java.lang.String.getBytes(int, int, byte[], int) */ - public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) { + public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte[] dst, int dstBegin) { srcBegin <<= 1; srcEnd <<= 1; for (int i = srcBegin + (1 >> LO_BYTE_SHIFT); i < srcEnd; i += 2) { diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java index 33647db8f6b..17580d2aa84 100644 --- a/src/java.base/share/classes/java/lang/Thread.java +++ b/src/java.base/share/classes/java/lang/Thread.java @@ -1247,7 +1247,7 @@ public static int activeCount() { * if {@link java.lang.ThreadGroup#checkAccess} determines that * the current thread cannot access its thread group */ - public static int enumerate(Thread tarray[]) { + public static int enumerate(Thread[] tarray) { return currentThread().getThreadGroup().enumerate(tarray); } diff --git a/src/java.base/share/classes/java/lang/ThreadGroup.java b/src/java.base/share/classes/java/lang/ThreadGroup.java index d5a97717e9d..c6e532a7444 100644 --- a/src/java.base/share/classes/java/lang/ThreadGroup.java +++ b/src/java.base/share/classes/java/lang/ThreadGroup.java @@ -399,7 +399,7 @@ public int activeCount() { * * @since 1.0 */ - public int enumerate(Thread list[]) { + public int enumerate(Thread[] list) { checkAccess(); return enumerate(list, 0, true); } @@ -437,12 +437,12 @@ public int enumerate(Thread list[]) { * * @since 1.0 */ - public int enumerate(Thread list[], boolean recurse) { + public int enumerate(Thread[] list, boolean recurse) { checkAccess(); return enumerate(list, 0, recurse); } - private int enumerate(Thread list[], int n, boolean recurse) { + private int enumerate(Thread[] list, int n, boolean recurse) { int ngroupsSnapshot = 0; ThreadGroup[] groupsSnapshot = null; synchronized (this) { @@ -533,7 +533,7 @@ public int activeGroupCount() { * * @since 1.0 */ - public int enumerate(ThreadGroup list[]) { + public int enumerate(ThreadGroup[] list) { checkAccess(); return enumerate(list, 0, true); } @@ -571,12 +571,12 @@ public int enumerate(ThreadGroup list[]) { * * @since 1.0 */ - public int enumerate(ThreadGroup list[], boolean recurse) { + public int enumerate(ThreadGroup[] list, boolean recurse) { checkAccess(); return enumerate(list, 0, recurse); } - private int enumerate(ThreadGroup list[], int n, boolean recurse) { + private int enumerate(ThreadGroup[] list, int n, boolean recurse) { int ngroupsSnapshot = 0; ThreadGroup[] groupsSnapshot = null; synchronized (this) { diff --git a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java index 93ac7365624..a412dd753cc 100644 --- a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java +++ b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -2447,7 +2447,7 @@ public static ModuleDescriptor read(InputStream in, * Reads the binary form of a module declaration from an input stream as a * module descriptor. This method works exactly as specified by the 2-arg * {@link #read(InputStream,Supplier) read} method with the exception that - * a packager finder is not used to find additional packages when the + * a package finder is not used to find additional packages when the * module descriptor read from the stream does not indicate the set of * packages. * @@ -2516,7 +2516,7 @@ public static ModuleDescriptor read(ByteBuffer bb, * Reads the binary form of a module declaration from a byte buffer as a * module descriptor. This method works exactly as specified by the 2-arg * {@link #read(ByteBuffer,Supplier) read} method with the exception that a - * packager finder is not used to find additional packages when the module + * package finder is not used to find additional packages when the module * descriptor encoded in the buffer does not indicate the set of packages. * * @param bb diff --git a/src/java.base/share/classes/java/lang/ref/PhantomReference.java b/src/java.base/share/classes/java/lang/ref/PhantomReference.java index 1476f517de3..e64e7aaf3f2 100644 --- a/src/java.base/share/classes/java/lang/ref/PhantomReference.java +++ b/src/java.base/share/classes/java/lang/ref/PhantomReference.java @@ -72,8 +72,12 @@ public T get() { * do reference processing concurrently. */ @Override + boolean refersToImpl(T obj) { + return refersTo0(obj); + } + @IntrinsicCandidate - native final boolean refersTo0(Object o); + private native boolean refersTo0(Object o); /** * Creates a new phantom reference that refers to the given object and diff --git a/src/java.base/share/classes/java/lang/ref/Reference.java b/src/java.base/share/classes/java/lang/ref/Reference.java index c8b0307ba37..a5c2836e188 100644 --- a/src/java.base/share/classes/java/lang/ref/Reference.java +++ b/src/java.base/share/classes/java/lang/ref/Reference.java @@ -363,13 +363,20 @@ public T get() { * @since 16 */ public final boolean refersTo(T obj) { - return refersTo0(obj); + return refersToImpl(obj); } /* Implementation of refersTo(), overridden for phantom references. + * This method exists only to avoid making refersTo0() virtual. Making + * refersTo0() virtual has the undesirable effect of C2 often preferring + * to call the native implementation over the intrinsic. */ + boolean refersToImpl(T obj) { + return refersTo0(obj); + } + @IntrinsicCandidate - native boolean refersTo0(Object o); + private native boolean refersTo0(Object o); /** * Clears this reference object. Invoking this method will not cause this diff --git a/src/java.base/share/classes/java/math/BigInteger.java b/src/java.base/share/classes/java/math/BigInteger.java index 12f65d8a9d2..14f2ae6154c 100644 --- a/src/java.base/share/classes/java/math/BigInteger.java +++ b/src/java.base/share/classes/java/math/BigInteger.java @@ -1221,7 +1221,7 @@ private BigInteger(long val) { * Assumes that the input array will not be modified (the returned * BigInteger will reference the input array if feasible). */ - private static BigInteger valueOf(int val[]) { + private static BigInteger valueOf(int[] val) { return (val[0] > 0 ? new BigInteger(val, 1) : new BigInteger(val)); } @@ -4412,7 +4412,7 @@ public double doubleValue() { /** * Returns a copy of the input array stripped of any leading zero bytes. */ - private static int[] stripLeadingZeroInts(int val[]) { + private static int[] stripLeadingZeroInts(int[] val) { int vlen = val.length; int keep; @@ -4426,7 +4426,7 @@ private static int[] stripLeadingZeroInts(int val[]) { * Returns the input array stripped of any leading zero bytes. * Since the source is trusted the copying may be skipped. */ - private static int[] trustedStripLeadingZeroInts(int val[]) { + private static int[] trustedStripLeadingZeroInts(int[] val) { int vlen = val.length; int keep; @@ -4439,7 +4439,7 @@ private static int[] trustedStripLeadingZeroInts(int val[]) { /** * Returns a copy of the input array stripped of any leading zero bytes. */ - private static int[] stripLeadingZeroBytes(byte a[], int off, int len) { + private static int[] stripLeadingZeroBytes(byte[] a, int off, int len) { int indexBound = off + len; int keep; @@ -4465,7 +4465,7 @@ private static int[] stripLeadingZeroBytes(byte a[], int off, int len) { * Takes an array a representing a negative 2's-complement number and * returns the minimal (no leading zero bytes) unsigned whose value is -a. */ - private static int[] makePositive(byte a[], int off, int len) { + private static int[] makePositive(byte[] a, int off, int len) { int keep, k; int indexBound = off + len; @@ -4513,7 +4513,7 @@ private static int[] makePositive(byte a[], int off, int len) { * Takes an array a representing a negative 2's-complement number and * returns the minimal (no leading zero ints) unsigned whose value is -a. */ - private static int[] makePositive(int a[]) { + private static int[] makePositive(int[] a) { int keep, j; // Find first non-sign (0xffffffff) int of input diff --git a/src/java.base/share/classes/java/net/DatagramPacket.java b/src/java.base/share/classes/java/net/DatagramPacket.java index 7210cdb686a..55e0eae0fb6 100644 --- a/src/java.base/share/classes/java/net/DatagramPacket.java +++ b/src/java.base/share/classes/java/net/DatagramPacket.java @@ -80,7 +80,7 @@ class DatagramPacket { * * @since 1.2 */ - public DatagramPacket(byte buf[], int offset, int length) { + public DatagramPacket(byte[] buf, int offset, int length) { setData(buf, offset, length); } @@ -98,7 +98,7 @@ public DatagramPacket(byte buf[], int offset, int length) { * or if the length is greater than the length of the * packet's given buffer. */ - public DatagramPacket(byte buf[], int length) { + public DatagramPacket(byte[] buf, int length) { this (buf, 0, length); } @@ -124,7 +124,7 @@ public DatagramPacket(byte buf[], int length) { * * @since 1.2 */ - public DatagramPacket(byte buf[], int offset, int length, + public DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) { setData(buf, offset, length); setAddress(address); @@ -152,7 +152,7 @@ public DatagramPacket(byte buf[], int offset, int length, * * @since 1.4 */ - public DatagramPacket(byte buf[], int offset, int length, SocketAddress address) { + public DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) { setData(buf, offset, length); setSocketAddress(address); } @@ -174,7 +174,7 @@ public DatagramPacket(byte buf[], int offset, int length, SocketAddress address) * * @see java.net.InetAddress */ - public DatagramPacket(byte buf[], int length, + public DatagramPacket(byte[] buf, int length, InetAddress address, int port) { this(buf, 0, length, address, port); } @@ -198,7 +198,7 @@ public DatagramPacket(byte buf[], int length, * * @since 1.4 */ - public DatagramPacket(byte buf[], int length, SocketAddress address) { + public DatagramPacket(byte[] buf, int length, SocketAddress address) { this(buf, 0, length, address); } diff --git a/src/java.base/share/classes/java/net/Inet4Address.java b/src/java.base/share/classes/java/net/Inet4Address.java index 8f5b50db8b5..a504f4f398c 100644 --- a/src/java.base/share/classes/java/net/Inet4Address.java +++ b/src/java.base/share/classes/java/net/Inet4Address.java @@ -106,7 +106,7 @@ class Inet4Address extends InetAddress { holder().family = IPv4; } - Inet4Address(String hostName, byte addr[]) { + Inet4Address(String hostName, byte[] addr) { holder().hostName = hostName; holder().family = IPv4; if (addr != null) { diff --git a/src/java.base/share/classes/java/net/Inet6Address.java b/src/java.base/share/classes/java/net/Inet6Address.java index 98f0675dd7a..4943362a5fb 100644 --- a/src/java.base/share/classes/java/net/Inet6Address.java +++ b/src/java.base/share/classes/java/net/Inet6Address.java @@ -223,13 +223,13 @@ private Inet6AddressHolder( */ boolean scope_ifname_set; // false; - void setAddr(byte addr[]) { + void setAddr(byte[] addr) { if (addr.length == INADDRSZ) { // normal IPv6 address System.arraycopy(addr, 0, ipaddress, 0, INADDRSZ); } } - void init(byte addr[], int scope_id) { + void init(byte[] addr, int scope_id) { setAddr(addr); if (scope_id >= 0) { @@ -238,7 +238,7 @@ void init(byte addr[], int scope_id) { } } - void init(byte addr[], NetworkInterface nif) + void init(byte[] addr, NetworkInterface nif) throws UnknownHostException { setAddr(addr); @@ -377,27 +377,27 @@ boolean isMCOrgLocal() { /* checking of value for scope_id should be done by caller * scope_id must be >= 0, or -1 to indicate not being set */ - Inet6Address(String hostName, byte addr[], int scope_id) { + Inet6Address(String hostName, byte[] addr, int scope_id) { holder.init(hostName, IPv6); holder6 = new Inet6AddressHolder(); holder6.init(addr, scope_id); } - Inet6Address(String hostName, byte addr[]) { + Inet6Address(String hostName, byte[] addr) { holder6 = new Inet6AddressHolder(); try { initif (hostName, addr, null); } catch (UnknownHostException e) {} /* cant happen if ifname is null */ } - Inet6Address (String hostName, byte addr[], NetworkInterface nif) + Inet6Address (String hostName, byte[] addr, NetworkInterface nif) throws UnknownHostException { holder6 = new Inet6AddressHolder(); initif (hostName, addr, nif); } - Inet6Address (String hostName, byte addr[], String ifname) + Inet6Address (String hostName, byte[] addr, String ifname) throws UnknownHostException { holder6 = new Inet6AddressHolder(); @@ -474,7 +474,7 @@ public static Inet6Address getByAddress(String host, byte[] addr, throw new UnknownHostException("addr is of illegal length"); } - private void initstr(String hostName, byte addr[], String ifname) + private void initstr(String hostName, byte[] addr, String ifname) throws UnknownHostException { try { @@ -488,7 +488,7 @@ private void initstr(String hostName, byte addr[], String ifname) } } - private void initif(String hostName, byte addr[], NetworkInterface nif) + private void initif(String hostName, byte[] addr, NetworkInterface nif) throws UnknownHostException { int family = -1; diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java index 967d64ef63b..8788ea4fe86 100644 --- a/src/java.base/share/classes/java/net/Socket.java +++ b/src/java.base/share/classes/java/net/Socket.java @@ -962,7 +962,7 @@ public int read() throws IOException { return (n > 0) ? (a[0] & 0xff) : -1; } @Override - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { return in.read(b, off, len); } @Override @@ -1031,7 +1031,7 @@ public void write(int b) throws IOException { write(a, 0, 1); } @Override - public void write(byte b[], int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); } diff --git a/src/java.base/share/classes/java/net/URLConnection.java b/src/java.base/share/classes/java/net/URLConnection.java index c00fe946978..d2d74f155a9 100644 --- a/src/java.base/share/classes/java/net/URLConnection.java +++ b/src/java.base/share/classes/java/net/URLConnection.java @@ -1818,7 +1818,7 @@ else if (c[3] == 0x00 && c[1] == 0x61 && c[0] == 0x56 && * Returns -1, If EOF is reached before len bytes are read, returns 0 * otherwise */ - private static int readBytes(int c[], int len, InputStream is) + private static int readBytes(int[] c, int len, InputStream is) throws IOException { byte buf[] = new byte[len]; diff --git a/src/java.base/share/classes/java/net/URLStreamHandler.java b/src/java.base/share/classes/java/net/URLStreamHandler.java index 6b30d3cb43a..ba7627401a2 100644 --- a/src/java.base/share/classes/java/net/URLStreamHandler.java +++ b/src/java.base/share/classes/java/net/URLStreamHandler.java @@ -26,13 +26,8 @@ package java.net; import java.io.IOException; -import java.io.InputStream; -import java.io.File; -import java.io.OutputStream; -import java.util.Hashtable; import java.util.Objects; import sun.net.util.IPAddressUtil; -import sun.net.www.ParseUtil; /** * The abstract class {@code URLStreamHandler} is the common @@ -158,13 +153,12 @@ protected void parseURL(URL u, String spec, int start, int limit) { queryOnly = queryStart == start; if ((queryStart != -1) && (queryStart < limit)) { query = spec.substring(queryStart+1, limit); - if (limit > queryStart) - limit = queryStart; + limit = queryStart; spec = spec.substring(0, queryStart); } } - int i = 0; + int i; // Parse the authority part if any boolean isUNCName = (start <= limit - 4) && (spec.charAt(start) == '/') && @@ -249,7 +243,7 @@ protected void parseURL(URL u, String spec, int start, int limit) { start = i; // If the authority is defined then the path is defined by the // spec only; See RFC 2396 Section 5.2.4. - if (authority != null && !authority.isEmpty()) + if (!authority.isEmpty()) path = ""; } @@ -259,26 +253,27 @@ protected void parseURL(URL u, String spec, int start, int limit) { // Parse the file path if any if (start < limit) { + String specStr = spec.substring(start, limit); if (spec.charAt(start) == '/') { - path = spec.substring(start, limit); + path = specStr; } else if (path != null && !path.isEmpty()) { isRelPath = true; int ind = path.lastIndexOf('/'); - String separator = ""; - if (ind == -1 && authority != null) - separator = "/"; - path = path.substring(0, ind + 1) + separator + - spec.substring(start, limit); - + if (ind == -1 && authority != null) { + path = "/".concat(specStr); + } else { + path = path.substring(0, ind + 1).concat(specStr); + } } else { - path = spec.substring(start, limit); - path = (authority != null) ? "/" + path : path; + path = (authority != null) ? "/".concat(specStr) : specStr; } } else if (queryOnly && path != null) { int ind = path.lastIndexOf('/'); - if (ind < 0) - ind = 0; - path = path.substring(0, ind) + "/"; + if (ind < 0) { + path = "/"; + } else { + path = path.substring(0, ind + 1); + } } if (path == null) path = ""; @@ -299,7 +294,7 @@ protected void parseURL(URL u, String spec, int start, int limit) { */ if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 && (path.indexOf("/../", limit) != 0)) { - path = path.substring(0, limit) + path.substring(i + 3); + path = path.substring(0, limit).concat(path.substring(i + 3)); i = 0; } else { i = i + 3; diff --git a/src/java.base/share/classes/java/security/Security.java b/src/java.base/share/classes/java/security/Security.java index ff2bc942c03..e93c5e6af93 100644 --- a/src/java.base/share/classes/java/security/Security.java +++ b/src/java.base/share/classes/java/security/Security.java @@ -653,14 +653,7 @@ public static Provider[] getProviders(Map filter) { if (candidates == null || candidates.isEmpty()) return null; - Object[] candidatesArray = candidates.toArray(); - Provider[] result = new Provider[candidatesArray.length]; - - for (int i = 0; i < result.length; i++) { - result[i] = (Provider)candidatesArray[i]; - } - - return result; + return candidates.toArray(new Provider[0]); } // Map containing cached Spi Class objects of the specified type diff --git a/src/java.base/share/classes/java/text/ChoiceFormat.java b/src/java.base/share/classes/java/text/ChoiceFormat.java index 342931d1c45..dc1037e231b 100644 --- a/src/java.base/share/classes/java/text/ChoiceFormat.java +++ b/src/java.base/share/classes/java/text/ChoiceFormat.java @@ -350,7 +350,7 @@ public ChoiceFormat(double[] limits, String[] formats) { * @throws NullPointerException if {@code limits} or * {@code formats} is {@code null} */ - public void setChoices(double[] limits, String formats[]) { + public void setChoices(double[] limits, String[] formats) { if (limits.length != formats.length) { throw new IllegalArgumentException( "Array and limit arrays must be of the same length."); diff --git a/src/java.base/share/classes/java/text/DecimalFormat.java b/src/java.base/share/classes/java/text/DecimalFormat.java index bbb2b8fe085..01258bdfa09 100644 --- a/src/java.base/share/classes/java/text/DecimalFormat.java +++ b/src/java.base/share/classes/java/text/DecimalFormat.java @@ -2285,7 +2285,7 @@ private BigDecimal getBigDecimalMultiplier() { private final boolean subparse(String text, ParsePosition parsePosition, String positivePrefix, String negativePrefix, DigitList digits, boolean isExponent, - boolean status[]) { + boolean[] status) { int position = parsePosition.index; int oldStart = parsePosition.index; boolean gotPositive, gotNegative; @@ -2377,7 +2377,7 @@ private final boolean subparse(String text, ParsePosition parsePosition, */ int subparseNumber(String text, int position, DigitList digits, boolean checkExponent, - boolean isExponent, boolean status[]) { + boolean isExponent, boolean[] status) { // process digits or Inf, find decimal position status[STATUS_INFINITE] = false; if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0, diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java index 8d9e2dc6e60..8c7dbccc4a1 100644 --- a/src/java.base/share/classes/java/util/Arrays.java +++ b/src/java.base/share/classes/java/util/Arrays.java @@ -4265,7 +4265,7 @@ public E next() { * @return a content-based hash code for {@code a} * @since 1.5 */ - public static int hashCode(long a[]) { + public static int hashCode(long[] a) { if (a == null) return 0; @@ -4294,7 +4294,7 @@ public static int hashCode(long a[]) { * @return a content-based hash code for {@code a} * @since 1.5 */ - public static int hashCode(int a[]) { + public static int hashCode(int[] a) { if (a == null) return 0; @@ -4321,7 +4321,7 @@ public static int hashCode(int a[]) { * @return a content-based hash code for {@code a} * @since 1.5 */ - public static int hashCode(short a[]) { + public static int hashCode(short[] a) { if (a == null) return 0; @@ -4348,7 +4348,7 @@ public static int hashCode(short a[]) { * @return a content-based hash code for {@code a} * @since 1.5 */ - public static int hashCode(char a[]) { + public static int hashCode(char[] a) { if (a == null) return 0; @@ -4375,7 +4375,7 @@ public static int hashCode(char a[]) { * @return a content-based hash code for {@code a} * @since 1.5 */ - public static int hashCode(byte a[]) { + public static int hashCode(byte[] a) { if (a == null) return 0; @@ -4402,7 +4402,7 @@ public static int hashCode(byte a[]) { * @return a content-based hash code for {@code a} * @since 1.5 */ - public static int hashCode(boolean a[]) { + public static int hashCode(boolean[] a) { if (a == null) return 0; @@ -4429,7 +4429,7 @@ public static int hashCode(boolean a[]) { * @return a content-based hash code for {@code a} * @since 1.5 */ - public static int hashCode(float a[]) { + public static int hashCode(float[] a) { if (a == null) return 0; @@ -4456,7 +4456,7 @@ public static int hashCode(float a[]) { * @return a content-based hash code for {@code a} * @since 1.5 */ - public static int hashCode(double a[]) { + public static int hashCode(double[] a) { if (a == null) return 0; @@ -4489,7 +4489,7 @@ public static int hashCode(double a[]) { * @see #deepHashCode(Object[]) * @since 1.5 */ - public static int hashCode(Object a[]) { + public static int hashCode(Object[] a) { if (a == null) return 0; @@ -4530,7 +4530,7 @@ public static int hashCode(Object a[]) { * @see #hashCode(Object[]) * @since 1.5 */ - public static int deepHashCode(Object a[]) { + public static int deepHashCode(Object[] a) { if (a == null) return 0; diff --git a/src/java.base/share/classes/java/util/jar/JarVerifier.java b/src/java.base/share/classes/java/util/jar/JarVerifier.java index edf6ce238a4..5cd640b5e3f 100644 --- a/src/java.base/share/classes/java/util/jar/JarVerifier.java +++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java @@ -96,7 +96,7 @@ class JarVerifier { /** collect -DIGEST-MANIFEST values for deny list */ private List manifestDigests; - public JarVerifier(String name, byte rawBytes[]) { + public JarVerifier(String name, byte[] rawBytes) { manifestName = name; manifestRawBytes = rawBytes; sigFileSigners = new Hashtable<>(); @@ -466,7 +466,7 @@ public int read() throws IOException } } - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { ensureOpen(); if ((numLeft > 0) && (numLeft < len)) { len = (int)numLeft; diff --git a/src/java.base/share/classes/java/util/regex/Matcher.java b/src/java.base/share/classes/java/util/regex/Matcher.java index ea319ed4a25..440f22fcaab 100644 --- a/src/java.base/share/classes/java/util/regex/Matcher.java +++ b/src/java.base/share/classes/java/util/regex/Matcher.java @@ -289,7 +289,7 @@ private static class ImmutableMatchResult implements MatchResult { private final String text; ImmutableMatchResult(int first, int last, int groupCount, - int groups[], String text) + int[] groups, String text) { this.first = first; this.last = last; 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 f073fe8fb1b..8fc200ed1ae 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -33,7 +33,6 @@ import java.io.RandomAccessFile; import java.io.UncheckedIOException; import java.lang.ref.Cleaner.Cleanable; -import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.file.InvalidPathException; import java.nio.file.attribute.BasicFileAttributes; @@ -69,6 +68,7 @@ import jdk.internal.ref.CleanerFactory; import jdk.internal.vm.annotation.Stable; import sun.nio.cs.UTF_8; +import sun.nio.fs.DefaultFileSystemProvider; import sun.security.util.SignatureFileVerifier; import static java.util.zip.ZipConstants64.*; @@ -925,7 +925,7 @@ private long initDataOffset() throws IOException { return pos; } - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { synchronized (ZipFile.this) { ensureOpenOrZipException(); initDataOffset(); @@ -1255,14 +1255,19 @@ public boolean equals(Object obj) { } } private static final HashMap files = new HashMap<>(); - + /** + * Use the platform's default file system to avoid + * issues when the VM is configured to use a custom file system provider. + */ + private static final java.nio.file.FileSystem builtInFS = + DefaultFileSystemProvider.theFileSystem(); static Source get(File file, boolean toDelete, ZipCoder zc) throws IOException { final Key key; try { key = new Key(file, - Files.readAttributes(file.toPath(), BasicFileAttributes.class), - zc); + Files.readAttributes(builtInFS.getPath(file.getPath()), + BasicFileAttributes.class), zc); } catch (InvalidPathException ipe) { throw new IOException(ipe); } diff --git a/src/java.base/share/classes/java/util/zip/ZipUtils.java b/src/java.base/share/classes/java/util/zip/ZipUtils.java index b33d8b31d8c..b19178fb012 100644 --- a/src/java.base/share/classes/java/util/zip/ZipUtils.java +++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java @@ -165,7 +165,7 @@ static LocalDateTime javaEpochToLocalDateTime(long time) { * Fetches unsigned 16-bit value from byte array at specified offset. * The bytes are assumed to be in Intel (little-endian) byte order. */ - public static final int get16(byte b[], int off) { + public static final int get16(byte[] b, int off) { return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8); } @@ -173,7 +173,7 @@ public static final int get16(byte b[], int off) { * Fetches unsigned 32-bit value from byte array at specified offset. * The bytes are assumed to be in Intel (little-endian) byte order. */ - public static final long get32(byte b[], int off) { + public static final long get32(byte[] b, int off) { return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL; } @@ -181,7 +181,7 @@ public static final long get32(byte b[], int off) { * Fetches signed 64-bit value from byte array at specified offset. * The bytes are assumed to be in Intel (little-endian) byte order. */ - public static final long get64(byte b[], int off) { + public static final long get64(byte[] b, int off) { return get32(b, off) | (get32(b, off+4) << 32); } @@ -190,7 +190,7 @@ public static final long get64(byte b[], int off) { * The bytes are assumed to be in Intel (little-endian) byte order. * */ - public static final int get32S(byte b[], int off) { + public static final int get32S(byte[] b, int off) { return (get16(b, off) | (get16(b, off+2) << 16)); } diff --git a/src/java.base/share/classes/jdk/internal/misc/VM.java b/src/java.base/share/classes/jdk/internal/misc/VM.java index 0d5d3e41206..5ad27d8e7ee 100644 --- a/src/java.base/share/classes/jdk/internal/misc/VM.java +++ b/src/java.base/share/classes/jdk/internal/misc/VM.java @@ -272,8 +272,8 @@ public static void saveProperties(Map props) { s = props.get("java.class.version"); int index = s.indexOf('.'); try { - classFileMajorVersion = Integer.valueOf(s.substring(0, index)); - classFileMinorVersion = Integer.valueOf(s.substring(index+1, s.length())); + classFileMajorVersion = Integer.parseInt(s.substring(0, index)); + classFileMinorVersion = Integer.parseInt(s.substring(index + 1)); } catch (NumberFormatException e) { throw new InternalError(e); } diff --git a/src/java.base/share/classes/jdk/internal/platform/Metrics.java b/src/java.base/share/classes/jdk/internal/platform/Metrics.java index 119367db52b..b896adf8aed 100644 --- a/src/java.base/share/classes/jdk/internal/platform/Metrics.java +++ b/src/java.base/share/classes/jdk/internal/platform/Metrics.java @@ -352,6 +352,19 @@ public static Metrics systemMetrics() { */ public long getMemorySoftLimit(); + /***************************************************************** + * pids subsystem + ****************************************************************/ + + /** + * Returns the maximum number of tasks that may be created in the Isolation Group. + * + * @return The maximum number of tasks, -1 if the quota is unlimited or + * -2 if not supported. + * + */ + public long getPidsMax(); + /***************************************************************** * BlKIO Subsystem ****************************************************************/ diff --git a/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java b/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java index 936a302331b..2c984ef427c 100644 --- a/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java +++ b/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java @@ -70,6 +70,10 @@ public class VectorSupport { public static final int VECTOR_OP_MASK_FIRSTTRUE = 20; public static final int VECTOR_OP_MASK_LASTTRUE = 21; + // Rotate operations + public static final int VECTOR_OP_LROTATE = 22; + public static final int VECTOR_OP_RROTATE = 23; + // Math routines public static final int VECTOR_OP_TAN = 101; public static final int VECTOR_OP_TANH = 102; diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index b6f32b6bad0..82b73d01c6b 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -405,12 +405,23 @@ public static void printSystemMetrics() { limit = c.getMemoryAndSwapLimit(); ostream.println(formatLimitString(limit, INDENT + "Memory & Swap Limit: ", longRetvalNotSupported)); + limit = c.getPidsMax(); + ostream.println(formatLimitString(limit, INDENT + "Maximum Processes Limit: ", + longRetvalNotSupported, false)); ostream.println(""); } private static String formatLimitString(long limit, String prefix, long unavailable) { + return formatLimitString(limit, prefix, unavailable, true); + } + + private static String formatLimitString(long limit, String prefix, long unavailable, boolean scale) { if (limit >= 0) { - return prefix + SizePrefix.scaleValue(limit); + if (scale) { + return prefix + SizePrefix.scaleValue(limit); + } else { + return prefix + limit; + } } else if (limit == unavailable) { return prefix + "N/A"; } else { diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index f19d4226c12..a59206d0309 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -65,6 +65,9 @@ private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); + // Maximum direct transfer size + private static final int MAX_DIRECT_TRANSFER_SIZE; + // Used to make native read and write calls private final FileDispatcher nd; @@ -582,6 +585,15 @@ private long transferToTrustedChannel(long position, long count, if (!((target instanceof FileChannelImpl) || isSelChImpl)) return IOStatus.UNSUPPORTED; + if (target == this) { + long posThis = position(); + if (posThis - count + 1 <= position && + position - count + 1 <= posThis && + !nd.canTransferToFromOverlappedMap()) { + return IOStatus.UNSUPPORTED_CASE; + } + } + // Trusted target: Use a mapped buffer long remaining = count; while (remaining > 0L) { @@ -622,18 +634,18 @@ private long transferToTrustedChannel(long position, long count, return count - remaining; } - private long transferToArbitraryChannel(long position, int icount, + private long transferToArbitraryChannel(long position, long count, WritableByteChannel target) throws IOException { // Untrusted target: Use a newly-erased buffer - int c = Math.min(icount, TRANSFER_SIZE); + int c = (int)Math.min(count, TRANSFER_SIZE); ByteBuffer bb = ByteBuffer.allocate(c); long tw = 0; // Total bytes written long pos = position; try { - while (tw < icount) { - bb.limit(Math.min((int)(icount - tw), TRANSFER_SIZE)); + while (tw < count) { + bb.limit((int)Math.min(count - tw, TRANSFER_SIZE)); int nr = read(bb, pos); if (nr <= 0) break; @@ -672,22 +684,23 @@ public long transferTo(long position, long count, long sz = size(); if (position > sz) return 0; - int icount = (int)Math.min(count, Integer.MAX_VALUE); - if ((sz - position) < icount) - icount = (int)(sz - position); - long n; + if ((sz - position) < count) + count = sz - position; - // Attempt a direct transfer, if the kernel supports it + // Attempt a direct transfer, if the kernel supports it, limiting + // the number of bytes according to which platform + int icount = (int)Math.min(count, MAX_DIRECT_TRANSFER_SIZE); + long n; if ((n = transferToDirectly(position, icount, target)) >= 0) return n; // Attempt a mapped transfer, but only to trusted channel types - if ((n = transferToTrustedChannel(position, icount, target)) >= 0) + if ((n = transferToTrustedChannel(position, count, target)) >= 0) return n; // Slow path for untrusted targets - return transferToArbitraryChannel(position, icount, target); + return transferToArbitraryChannel(position, count, target); } private long transferFromFileChannel(FileChannelImpl src, @@ -700,6 +713,14 @@ private long transferFromFileChannel(FileChannelImpl src, long pos = src.position(); long max = Math.min(count, src.size() - pos); + if (src == this) { + if (position() - max + 1 <= pos && + pos - max + 1 <= position() && + !nd.canTransferToFromOverlappedMap()) { + return IOStatus.UNSUPPORTED_CASE; + } + } + long remaining = max; long p = pos; while (remaining > 0L) { @@ -775,9 +796,12 @@ public long transferFrom(ReadableByteChannel src, throw new IllegalArgumentException(); if (position > size()) return 0; - if (src instanceof FileChannelImpl) - return transferFromFileChannel((FileChannelImpl)src, - position, count); + + if (src instanceof FileChannelImpl fci) { + long n = transferFromFileChannel(fci, position, count); + if (n >= 0) + return n; + } return transferFromArbitraryChannel(src, position, count); } @@ -1348,11 +1372,15 @@ private native long map0(int prot, long position, long length, boolean isSync) private native long transferTo0(FileDescriptor src, long position, long count, FileDescriptor dst); + // Retrieves the maximum size of a transfer + private static native int maxDirectTransferSize0(); + // Caches fieldIDs private static native long initIDs(); static { IOUtil.load(); allocationGranularity = initIDs(); + MAX_DIRECT_TRANSFER_SIZE = maxDirectTransferSize0(); } } diff --git a/src/java.base/share/classes/sun/nio/ch/FileDispatcher.java b/src/java.base/share/classes/sun/nio/ch/FileDispatcher.java index 5089ab944d6..1ccbf514d53 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileDispatcher.java +++ b/src/java.base/share/classes/sun/nio/ch/FileDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -67,5 +67,7 @@ abstract FileDescriptor duplicateForMapping(FileDescriptor fd) abstract boolean transferToDirectlyNeedsPositionLock(); + abstract boolean canTransferToFromOverlappedMap(); + abstract int setDirectIO(FileDescriptor fd, String path); } diff --git a/src/java.base/share/classes/sun/security/pkcs/PKCS9Attributes.java b/src/java.base/share/classes/sun/security/pkcs/PKCS9Attributes.java index d8a7ba7ffa8..f37070cd64e 100644 --- a/src/java.base/share/classes/sun/security/pkcs/PKCS9Attributes.java +++ b/src/java.base/share/classes/sun/security/pkcs/PKCS9Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -241,10 +241,8 @@ public void encode(byte tag, OutputStream out) throws IOException { private byte[] generateDerEncoding() throws IOException { DerOutputStream out = new DerOutputStream(); - Object[] attribVals = attributes.values().toArray(); - - out.putOrderedSetOf(DerValue.tag_SetOf, - castToDerEncoder(attribVals)); + DerEncoder[] attribVals = attributes.values().toArray(new DerEncoder[0]); + out.putOrderedSetOf(DerValue.tag_SetOf, attribVals); return out.toByteArray(); } @@ -348,17 +346,4 @@ public String toString() { return sb.toString(); } - /** - * Cast an object array whose components are - * DerEncoders to DerEncoder[]. - */ - static DerEncoder[] castToDerEncoder(Object[] objs) { - - DerEncoder[] encoders = new DerEncoder[objs.length]; - - for (int i=0; i < encoders.length; i++) - encoders[i] = (DerEncoder) objs[i]; - - return encoders; - } } diff --git a/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java b/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java index 8c8ca9b42d4..f61466e0245 100644 --- a/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java +++ b/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -187,7 +187,6 @@ private static BigInteger[] generatePandQ(SecureRandom random, int valueL, hashObj = MessageDigest.getInstance(hashAlg); } catch (NoSuchAlgorithmException nsae) { // should never happen - nsae.printStackTrace(); } /* Step 3, 4: Useful variables */ diff --git a/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java b/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java index 4fdb6694c3b..2b07e69dcfd 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java @@ -55,6 +55,8 @@ import sun.security.x509.URIName; import sun.security.x509.X509CertImpl; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * This is a class that checks the revocation status of a certificate(s) using * OCSP. It is not a PKIXCertPathChecker and therefore can be used outside of @@ -176,7 +178,7 @@ public static byte[] getOCSPBytes(List certIds, URI responderURI, try { String encodedGetReq = responderURI.toString() + "/" + URLEncoder.encode(Base64.getEncoder().encodeToString(bytes), - "UTF-8"); + UTF_8); if (encodedGetReq.length() <= 255) { url = new URL(encodedGetReq); diff --git a/src/java.base/share/classes/sun/security/ssl/RSAKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/RSAKeyExchange.java index 835bfc538d3..3ad4a009556 100644 --- a/src/java.base/share/classes/sun/security/ssl/RSAKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/RSAKeyExchange.java @@ -236,8 +236,7 @@ private static SecretKey generatePremasterSecret( NoSuchAlgorithmException iae) { // unlikely to happen, otherwise, must be a provider exception if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine("RSA premaster secret generation error:"); - iae.printStackTrace(System.out); + SSLLogger.fine("RSA premaster secret generation error", iae); } throw new GeneralSecurityException( diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 45e5b8476dc..c21177233e4 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -1747,6 +1747,9 @@ written when the recording is stopped, for example: \f[CB]/home/user/recordings/recording.jfr\f[R] .IP \[bu] 2 \f[CB]c:\\recordings\\recording.jfr\f[R] +.PP +If \f[CB]%p\f[R] and/or \f[CB]%t\f[R] is specified in the filename, it expands to the JVM\[aq]s +PID and the current timestamp, respectively. .RE .TP .B \f[CB]name=\f[R]\f[I]identifier\f[R] @@ -1813,6 +1816,30 @@ is needed. .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 +.B \f[CB]option=\f[R]\f[I]value\f[R] +Specifies the option value to modify. +To list available options, use the \f[CB]JAVA_HOME\f[R]/bin/jfr tool. +.RS +.RE +.TP +.B \f[CB]event\-setting\f[R]=\f[I]value\f[R] +Specifies the event setting value to modify. +Use the form: #= To add a new event setting, prefix the event name with +\[aq]+\[aq]. +.RS +.RE +.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. .RE .TP .B \f[CB]\-XX:ThreadStackSize=\f[R]\f[I]size\f[R] diff --git a/src/java.base/share/man/keytool.1 b/src/java.base/share/man/keytool.1 index 70659fa119a..c5777f2db8b 100644 --- a/src/java.base/share/man/keytool.1 +++ b/src/java.base/share/man/keytool.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "KEYTOOL" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "KEYTOOL" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP @@ -382,6 +382,10 @@ For example, an Elliptic Curve name. .IP \[bu] 2 {\f[CB]\-sigalg\f[R] \f[I]alg\f[R]}: Signature algorithm name .IP \[bu] 2 +{\f[CB]\-signer\f[R] \f[I]alias\f[R]}: Signer alias +.IP \[bu] 2 +[\f[CB]\-signerkeypass\f[R] \f[I]arg\f[R]]: Signer key password +.IP \[bu] 2 [\f[CB]\-dname\f[R] \f[I]name\f[R]]: Distinguished name .IP \[bu] 2 {\f[CB]\-startdate\f[R] \f[I]date\f[R]}: Certificate validity start date @@ -417,16 +421,21 @@ with an optional configure argument. .PP Use the \f[CB]\-genkeypair\f[R] command to generate a key pair (a public key and associated private key). -Wraps the public key in an X.509 v3 self\-signed certificate, which is -stored as a single\-element certificate chain. -This certificate chain and the private key are stored in a new keystore -entry that is identified by its alias. +When the \f[CB]\-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[CB]\-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???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[CB]\-keyalg\f[R] value specifies the algorithm to be used to generate the key pair, and the \f[CB]\-keysize\f[R] value specifies the size of each key to be generated. The \f[CB]\-sigalg\f[R] value specifies the algorithm that should be used -to sign the self\-signed certificate. +to sign the certificate. This algorithm must be compatible with the \f[CB]\-keyalg\f[R] value. .PP The \f[CB]\-groupname\f[R] value specifies the named group (for example, @@ -435,9 +444,30 @@ generated. Only one of \f[CB]\-groupname\f[R] and \f[CB]\-keysize\f[R] can be specified. .PP +The \f[CB]\-signer\f[R] value specifies the alias of a +\f[CB]PrivateKeyEntry\f[R] 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 \f[CB]\-keyalg\f[R] value is \f[CB]XDH\f[R], \f[CB]X25519\f[R], +\f[CB]X448\f[R], or \f[CB]DH\f[R]) as these keys cannot be used for digital +signatures, and therefore a self\-signed certificate cannot be created. +.PP +The \f[CB]\-signerkeypass\f[R] 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. +.PP The \f[CB]\-dname\f[R] value specifies the X.500 Distinguished Name to be -associated with the value of \f[CB]\-alias\f[R], and is used as the issuer -and subject fields in the self\-signed certificate. +associated with the value of \f[CB]\-alias\f[R]. +If the \f[CB]\-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[CB]\-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 @@ -1531,9 +1561,9 @@ The following examples show the defaults for various option values: \-alias\ "mykey" \-keysize -\ \ \ \ 2048\ (when\ using\ \-genkeypair\ and\ \-keyalg\ is\ "RSA",\ "DSA",\ or\ "RSASSA\-PSS") +\ \ \ \ 2048\ (when\ using\ \-genkeypair\ and\ \-keyalg\ is\ "RSA",\ "DSA",\ "RSASSA\-PSS",\ or\ "DH") \ \ \ \ 256\ (when\ using\ \-genkeypair\ and\ \-keyalg\ is\ "EC") -\ \ \ \ 255\ (when\ using\ \-genkeypair\ and\ \-keyalg\ is\ "EdDSA") +\ \ \ \ 255\ (when\ using\ \-genkeypair\ and\ \-keyalg\ is\ "EdDSA",\ or\ "XDH) \ \ \ \ 56\ (when\ using\ \-genseckey\ and\ \-keyalg\ is\ "DES") \ \ \ \ 168\ (when\ using\ \-genseckey\ and\ \-keyalg\ is\ "DESede") @@ -2531,16 +2561,17 @@ 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 starts off containing a single -element, a self\-signed certificate. +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. -Whenever the \f[CB]\-genkeypair\f[R] command is called to generate a new +When the \f[CB]\-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. +self\-signed certificate (unless the \f[CB]\-signer\f[R] option is +specified). .PP Later, after a Certificate Signing Request (CSR) was generated with the \f[CB]\-certreq\f[R] command and sent to a Certification Authority (CA), diff --git a/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java b/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java index d9a7355337e..7c5bbcaca36 100644 --- a/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -126,6 +126,10 @@ boolean transferToDirectlyNeedsPositionLock() { return false; } + boolean canTransferToFromOverlappedMap() { + return canTransferToFromOverlappedMap0(); + } + int setDirectIO(FileDescriptor fd, String path) { int result = -1; try { @@ -184,6 +188,8 @@ static native void release0(FileDescriptor fd, long pos, long size) static native void closeIntFD(int fd) throws IOException; + static native boolean canTransferToFromOverlappedMap0(); + static native int setDirect0(FileDescriptor fd) throws IOException; static native void init(); diff --git a/src/java.base/unix/native/libnio/ch/FileChannelImpl.c b/src/java.base/unix/native/libnio/ch/FileChannelImpl.c index e0debb09fa1..8cc753e6aa0 100644 --- a/src/java.base/unix/native/libnio/ch/FileChannelImpl.c +++ b/src/java.base/unix/native/libnio/ch/FileChannelImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -252,3 +252,12 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, #endif } +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileChannelImpl_maxDirectTransferSize0(JNIEnv* env, jobject this) +{ +#if defined(LINUX) + return 0x7ffff000; // 2,147,479,552 maximum for sendfile() +#else + return java_lang_Integer_MAX_VALUE; +#endif +} diff --git a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c index 8821461277c..c0c31d6ab2c 100644 --- a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c +++ b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c @@ -338,6 +338,16 @@ Java_sun_nio_ch_FileDispatcherImpl_closeIntFD(JNIEnv *env, jclass clazz, jint fd closeFileDescriptor(env, fd); } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_FileDispatcherImpl_canTransferToFromOverlappedMap0(JNIEnv *env, jclass clazz) +{ +#ifdef MACOSX + return JNI_FALSE; +#else + return JNI_TRUE; +#endif +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_setDirect0(JNIEnv *env, jclass clazz, jobject fdo) diff --git a/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java b/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java index 6379ebf4e1d..ed6c4a5eeea 100644 --- a/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -125,6 +125,10 @@ boolean transferToDirectlyNeedsPositionLock() { return true; } + boolean canTransferToFromOverlappedMap() { + return true; + } + int setDirectIO(FileDescriptor fd, String path) { int result = -1; String filePath = path.substring(0, path.lastIndexOf(File.separator)); diff --git a/src/java.base/windows/native/libnio/ch/FileChannelImpl.c b/src/java.base/windows/native/libnio/ch/FileChannelImpl.c index 66cf760622a..097ae004a1f 100644 --- a/src/java.base/windows/native/libnio/ch/FileChannelImpl.c +++ b/src/java.base/windows/native/libnio/ch/FileChannelImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -145,6 +145,9 @@ Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this, return 0; } +// Integer.MAX_VALUE - 1 is the maximum transfer size for TransmitFile() +#define MAX_TRANSMIT_SIZE (java_lang_Integer_MAX_VALUE - 1) + JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, jobject srcFD, @@ -156,8 +159,8 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, LARGE_INTEGER where; HANDLE src = (HANDLE)(handleval(env, srcFD)); SOCKET dst = (SOCKET)(fdval(env, dstFD)); - DWORD chunkSize = (count > java_lang_Integer_MAX_VALUE) ? - java_lang_Integer_MAX_VALUE : (DWORD)count; + DWORD chunkSize = (count > MAX_TRANSMIT_SIZE) ? + MAX_TRANSMIT_SIZE : (DWORD)count; BOOL result; where.QuadPart = position; @@ -189,3 +192,10 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, } return chunkSize; } + + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileChannelImpl_maxDirectTransferSize0(JNIEnv* env, jobject this) +{ + return MAX_TRANSMIT_SIZE; +} diff --git a/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java b/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java index 213a376dae5..2639358cb74 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -126,6 +126,10 @@ public enum ElementKind { */ BINDING_VARIABLE; + // Maintenance note: check if the default implementation of + // Elements.getOutermostTypeElement needs updating when new kind + // constants are added. + /** * Returns {@code true} if this is a kind of class: * either {@code CLASS} or {@code ENUM} or {@code RECORD}. diff --git a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java index fc94c171fdd..05dd7cfef84 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java @@ -533,6 +533,67 @@ default ModuleElement getModuleOf(Element e) { */ List getAllMembers(TypeElement type); + /** + * {@return the outermost type element an element is contained in + * if such a containing element exists; otherwise returns {@code + * null}} + * + * {@linkplain ModuleElement Modules} and {@linkplain + * PackageElement packages} do not have a containing type + * element and therefore {@code null} is returned for those kinds + * of elements. + * + * A {@link NestingKind#TOP_LEVEL top-level} class or + * interface is its own outermost type element. + * + * @implSpec + * The default implementation of this method first checks the kind + * of the argument. For elements of kind {@code PACKAGE}, {@code + * MODULE}, and {@code OTHER}, {@code null} is returned. For + * elements of other kinds, the element is examined to see if it + * is a top-level class or interface. If so, that element is + * returned; otherwise, the {@linkplain + * Element#getEnclosingElement enclosing element} chain is + * followed until a top-level class or interface is found. The + * element for the eventual top-level class or interface is + * returned. + * + * @param e the element being examined + * @see Element#getEnclosingElement + * @since 18 + */ + default TypeElement getOutermostTypeElement(Element e) { + return switch (e.getKind()) { + case PACKAGE, + MODULE -> null; // Per the general spec above. + case OTHER -> null; // Outside of base model of the javax.lang.model API + + // Elements of all remaining kinds should be enclosed in some + // sort of class or interface. Check to see if the element is + // a top-level type; if so, return it. Otherwise, keep going + // up the enclosing element chain until a top-level type is + // found. + default -> { + Element enclosing = e; + // This implementation is susceptible to infinite loops + // for misbehaving element implementations. + while (true) { + // Conceptual instanceof TypeElement check. If the + // argument is a type element, put it into a + // one-element list, otherwise an empty list. + List possibleTypeElement = ElementFilter.typesIn(List.of(enclosing)); + if (!possibleTypeElement.isEmpty()) { + TypeElement typeElement = possibleTypeElement.get(0); + if (typeElement.getNestingKind() == NestingKind.TOP_LEVEL) { + yield typeElement; + } + } + enclosing = enclosing.getEnclosingElement(); + } + } + }; + } + /** * Returns all annotations present on an element, whether * directly present or present via inheritance. diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java index e6164131f59..38f409f81fd 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -326,6 +326,35 @@ public void paint(final Graphics g, final JComponent c) { } } + protected void paintFocus(Graphics g, AbstractButton b, + Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { + Graphics2D g2d = null; + Stroke oldStroke = null; + Object oldAntialiasingHint = null; + Color oldColor = g.getColor(); + if (g instanceof Graphics2D) { + g2d = (Graphics2D)g; + oldStroke = g2d.getStroke(); + oldAntialiasingHint = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING); + g2d.setStroke(new BasicStroke(3)); + g2d.setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + } + Color ringColor = UIManager.getColor("Focus.color"); + g.setColor(ringColor); + g.drawRoundRect(5, 3, b.getWidth() - 10, b.getHeight() - 7, 15, 15); + if (g2d != null) { + // Restore old state of Java2D renderer + g2d.setStroke(oldStroke); + g2d.setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + oldAntialiasingHint); + } + g.setColor(oldColor); + } + protected String layoutAndGetText(final Graphics g, final AbstractButton b, final AquaButtonBorder aquaBorder, final Insets i, Rectangle viewRect, Rectangle iconRect, Rectangle textRect) { // re-initialize the view rect to the selected insets viewRect.x = i.left; 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 d9f9a66e44c..4177e32f63d 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileView.java @@ -25,8 +25,11 @@ package com.apple.laf; -import java.io.*; -import java.util.*; +import java.io.File; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; import java.util.Map.Entry; import javax.swing.Icon; @@ -34,6 +37,8 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; +import static java.nio.charset.StandardCharsets.UTF_8; + @SuppressWarnings("serial") // JDK implementation class class AquaFileView extends FileView { private static final boolean DEBUG = false; @@ -111,11 +116,7 @@ static class FileInfo { FileInfo(final File file){ isDirectory = file.isDirectory(); absolutePath = file.getAbsolutePath(); - try { - pathBytes = absolutePath.getBytes("UTF-8"); - } catch (final UnsupportedEncodingException e) { - pathBytes = new byte[0]; - } + pathBytes = absolutePath.getBytes(UTF_8); } } diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java index fbad90af3b3..e03bdeb1e32 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java @@ -41,6 +41,7 @@ public class MTLLayer extends CFLayer { private static native void nativeSetInsets(long layerPtr, int top, int left); private static native void validate(long layerPtr, MTLSurfaceData mtlsd); private static native void blitTexture(long layerPtr); + private static native void nativeSetOpaque(long layerPtr, boolean opaque); private int scale = 1; @@ -104,7 +105,11 @@ private void setScale(final int _scale) { } } - // ---------------------------------------------------------------------- + @Override + public void setOpaque(boolean opaque) { + execute(ptr -> nativeSetOpaque(ptr, opaque)); + } +// ---------------------------------------------------------------------- // NATIVE CALLBACKS // ---------------------------------------------------------------------- diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 3eea11b1036..6356f6d21c7 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -196,7 +196,6 @@ public LWWindowPeer(Window target, PlatformComponent platformComponent, } platformWindow.initialize(target, this, ownerDelegate); - // Init warning window(for applets) SecurityWarningWindow warn = null; if (target.getWarningString() != null) { @@ -520,7 +519,10 @@ public final boolean isTextured() { } public final void setTextured(final boolean isTextured) { - textured = isTextured; + if (textured != isTextured) { + textured = isTextured; + updateOpaque(); + } } @Override 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 4a301647b5f..c4311bf0f52 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -34,11 +34,13 @@ import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.lang.annotation.Native; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Callable; +import java.util.Arrays; import javax.accessibility.Accessible; import javax.accessibility.AccessibleAction; @@ -57,6 +59,8 @@ import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JTextArea; +import javax.swing.JList; +import javax.swing.JTree; import javax.swing.KeyStroke; import sun.awt.AWTAccessor; @@ -120,12 +124,7 @@ public void propertyChange(final PropertyChangeEvent evt) { private native void focusChanged(); static T invokeAndWait(final Callable callable, final Component c) { - if (c != null) { - try { - return LWCToolkit.invokeAndWait(callable, c); - } catch (final Exception e) { e.printStackTrace(); } - } - return null; + return invokeAndWait(callable, c, null); } static T invokeAndWait(final Callable callable, final Component c, final T defValue) { @@ -555,6 +554,10 @@ public void run() { if (pac == null) return; AccessibleSelection as = pac.getAccessibleSelection(); if (as == null) return; + if (parent instanceof JList) { + ((JList) parent).setSelectedIndex(i); + return; + } as.addAccessibleSelection(i); } }, c); @@ -655,77 +658,148 @@ public boolean[] call() throws Exception { // Duplicated from JavaComponentAccessibility // Note that values >=0 are indexes into the child array - static final int JAVA_AX_ALL_CHILDREN = -1; - static final int JAVA_AX_SELECTED_CHILDREN = -2; - static final int JAVA_AX_VISIBLE_CHILDREN = -3; + @Native static final int JAVA_AX_ALL_CHILDREN = -1; + @Native static final int JAVA_AX_SELECTED_CHILDREN = -2; + @Native static final int JAVA_AX_VISIBLE_CHILDREN = -3; // Each child takes up two entries in the array: one for itself and one for its role public static Object[] getChildrenAndRoles(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored) { if (a == null) return null; return invokeAndWait(new Callable() { public Object[] call() throws Exception { - ArrayList childrenAndRoles = new ArrayList(); - _addChildren(a, whichChildren, allowIgnored, childrenAndRoles); - - /* In the case of fetching a selection, need to check to see if - * the active descendant is at the beginning of the list. If it - * is not it needs to be moved to the beginning of the list so - * VoiceOver will annouce it correctly. The list returned - * from Java is always in order from top to bottom, but when shift - * selecting downward (extending the list) or multi-selecting using - * the VO keys control+option+command+return the active descendant - * is not at the top of the list in the shift select down case and - * may not be in the multi select case. - */ - if (whichChildren == JAVA_AX_SELECTED_CHILDREN) { - if (!childrenAndRoles.isEmpty()) { - AccessibleContext activeDescendantAC = - CAccessible.getActiveDescendant(a); - if (activeDescendantAC != null) { - String activeDescendantName = - activeDescendantAC.getAccessibleName(); - AccessibleRole activeDescendantRole = - activeDescendantAC.getAccessibleRole(); - // Move active descendant to front of list. - // List contains pairs of each selected item's - // Accessible and AccessibleRole. - ArrayList newArray = new ArrayList(); - int count = childrenAndRoles.size(); - Accessible currentAccessible = null; - AccessibleContext currentAC = null; - String currentName = null; - AccessibleRole currentRole = null; - for (int i = 0; i < count; i+=2) { - // Is this the active descendant? - currentAccessible = (Accessible)childrenAndRoles.get(i); - currentAC = currentAccessible.getAccessibleContext(); - currentName = currentAC.getAccessibleName(); - currentRole = (AccessibleRole)childrenAndRoles.get(i+1); - if (currentName != null && currentName.equals(activeDescendantName) && - currentRole.equals(activeDescendantRole) ) { - newArray.add(0, currentAccessible); - newArray.add(1, currentRole); - } else { - newArray.add(currentAccessible); - newArray.add(currentRole); - } - } - childrenAndRoles = newArray; + return getChildrenAndRolesImpl(a, c, whichChildren, allowIgnored); + } + }, c); + } + + private static Object[] getChildrenAndRolesImpl(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored) { + if (a == null) return null; + + ArrayList childrenAndRoles = new ArrayList(); + _addChildren(a, whichChildren, allowIgnored, childrenAndRoles); + + /* In case of fetching a selection, we need to check if +* the active descendant is at the beginning of the list, or +* otherwise move it, so that VoiceOver announces it correctly. + * The java list is always in order from top to bottom, but when + * (1) shift-selecting downward (extending the list) or (2) multi-selecting with + * the VO keys (CTRL+ALT+CMD+RETURN) the active descendant + * is not at the top of the list in the 1st case and may not be in the 2nd. + */ + if (whichChildren == JAVA_AX_SELECTED_CHILDREN) { + if (!childrenAndRoles.isEmpty()) { + AccessibleContext activeDescendantAC = + CAccessible.getActiveDescendant(a); + if (activeDescendantAC != null) { + String activeDescendantName = + activeDescendantAC.getAccessibleName(); + AccessibleRole activeDescendantRole = + activeDescendantAC.getAccessibleRole(); + // Move active descendant to front of list. + // List contains pairs of each selected item's + // Accessible and AccessibleRole. + ArrayList newArray = new ArrayList(); + int count = childrenAndRoles.size(); + Accessible currentAccessible = null; + AccessibleContext currentAC = null; + String currentName = null; + AccessibleRole currentRole = null; + for (int i = 0; i < count; i += 2) { + // Is this the active descendant? + currentAccessible = (Accessible) childrenAndRoles.get(i); + currentAC = currentAccessible.getAccessibleContext(); + currentName = currentAC.getAccessibleName(); + currentRole = (AccessibleRole) childrenAndRoles.get(i + 1); + if (currentName != null && currentName.equals(activeDescendantName) && + currentRole.equals(activeDescendantRole)) { + newArray.add(0, currentAccessible); + newArray.add(1, currentRole); + } else { + newArray.add(currentAccessible); + newArray.add(currentRole); } } + childrenAndRoles = newArray; } + } + } + + if ((whichChildren < 0) || (whichChildren * 2 >= childrenAndRoles.size())) { + return childrenAndRoles.toArray(); + } + + return new Object[]{childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1)}; + } + + // This method is called from the native + // Each child takes up three entries in the array: one for itself, one for its role, and one for the recursion level + private static Object[] getChildrenAndRolesRecursive(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored, final int level) { + if (a == null) return null; + return invokeAndWait(new Callable() { + public Object[] call() throws Exception { + ArrayList currentLevelChildren = new ArrayList(); + ArrayList allChildren = new ArrayList(); + ArrayList parentStack = new ArrayList(); + parentStack.add(a); + ArrayList indexses = new ArrayList(); + Integer index = 0; + int currentLevel = level; + while (!parentStack.isEmpty()) { + Accessible p = parentStack.get(parentStack.size() - 1); + + currentLevelChildren.addAll(Arrays.asList(getChildrenAndRolesImpl(p, c, JAVA_AX_ALL_CHILDREN, allowIgnored))); + if ((currentLevelChildren.size() == 0) || (index >= currentLevelChildren.size())) { + if (!parentStack.isEmpty()) parentStack.remove(parentStack.size() - 1); + if (!indexses.isEmpty()) index = indexses.remove(indexses.size() - 1); + currentLevel -= 1; + currentLevelChildren.clear(); + continue; + } + + Accessible ca = null; + Object obj = currentLevelChildren.get(index); + if (!(obj instanceof Accessible)) { + index += 2; + currentLevelChildren.clear(); + continue; + } + ca = (Accessible) obj; + Object role = currentLevelChildren.get(index + 1); + currentLevelChildren.clear(); + + AccessibleContext cac = ca.getAccessibleContext(); + if (cac == null) { + index += 2; + continue; + } + + if ((cac.getAccessibleStateSet().contains(AccessibleState.SELECTED) && (whichChildren == JAVA_AX_SELECTED_CHILDREN)) || + (cac.getAccessibleStateSet().contains(AccessibleState.VISIBLE) && (whichChildren == JAVA_AX_VISIBLE_CHILDREN)) || + (whichChildren == JAVA_AX_ALL_CHILDREN)) { + allChildren.add(ca); + allChildren.add(role); + allChildren.add(String.valueOf(currentLevel)); + } + + index += 2; + + if (cac.getAccessibleStateSet().contains(AccessibleState.EXPANDED)) { + parentStack.add(ca); + indexses.add(index); + index = 0; + currentLevel += 1; + continue; + } - if ((whichChildren < 0) || (whichChildren * 2 >= childrenAndRoles.size())) { - return childrenAndRoles.toArray(); } - return new Object[] { childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1) }; + return allChildren.toArray(); } }, c); } - private static final int JAVA_AX_ROWS = 1; - private static final int JAVA_AX_COLS = 2; + @Native private static final int JAVA_AX_ROWS = 1; + @Native private static final int JAVA_AX_COLS = 2; public static int getTableInfo(final Accessible a, final Component c, final int info) { @@ -744,6 +818,23 @@ public static int getTableInfo(final Accessible a, final Component c, }, c); } + private static int[] getTableSelectedInfo(final Accessible a, final Component c, + final int info) { + if (a == null) return null; + return invokeAndWait(() -> { + AccessibleContext ac = a.getAccessibleContext(); + AccessibleTable table = ac.getAccessibleTable(); + if (table != null) { + if (info == JAVA_AX_COLS) { + return table.getSelectedAccessibleColumns(); + } else if (info == JAVA_AX_ROWS) { + return table.getSelectedAccessibleRows(); + } + } + return null; + }, c); + } + private static AccessibleRole getAccessibleRoleForLabel(JLabel l, AccessibleRole fallback) { String text = l.getText(); if (text != null && text.length() > 0) { @@ -862,4 +953,18 @@ public Long call() throws Exception { } }, (Component)ax); } + + private static boolean isTreeRootVisible(Accessible a, Component c) { + if (a == null) return false; + + return invokeAndWait(new Callable() { + public Boolean call() throws Exception { + Accessible sa = CAccessible.getSwingAccessible(a); + if (sa instanceof JTree) { + return ((JTree) sa).isRootVisible(); + } + return false; + } + }, c); + } } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java index 212ddb6969c..72bfa8d541e 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java @@ -31,11 +31,7 @@ import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; -import javax.swing.JProgressBar; import javax.swing.JTabbedPane; -import javax.swing.JSlider; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY; import static javax.accessibility.AccessibleContext.ACCESSIBLE_CARET_PROPERTY; @@ -75,6 +71,8 @@ public static CAccessible getCAccessible(final Accessible a) { private static native void menuOpened(long ptr); private static native void menuClosed(long ptr); private static native void menuItemSelected(long ptr); + private static native void treeNodeExpanded(long ptr); + private static native void treeNodeCollapsed(long ptr); private Accessible accessible; @@ -137,6 +135,13 @@ public void propertyChange(PropertyChangeEvent e) { if (parentAccessible != null) { parentRole = parentAccessible.getAccessibleContext().getAccessibleRole(); } + + if (newValue == AccessibleState.EXPANDED) { + treeNodeExpanded(ptr); + } else if (newValue == AccessibleState.COLLAPSED) { + treeNodeCollapsed(ptr); + } + // At least for now don't handle combo box menu state changes. // This may change when later fixing issues which currently // exist for combo boxes, but for now the following is only diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java index 795e4296c70..0ea70549d43 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -26,20 +25,27 @@ package sun.lwawt.macosx; -import java.awt.*; - -import java.io.*; -import java.net.URI; -import java.net.URISyntaxException; +import java.awt.Image; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; import java.text.Normalizer; import java.text.Normalizer.Form; -import java.util.*; -import java.util.regex.*; -import java.awt.datatransfer.*; -import java.nio.charset.StandardCharsets; -import sun.awt.datatransfer.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import sun.awt.datatransfer.DataTransferer; +import sun.awt.datatransfer.ToolkitThreadBlockedHandler; + +import static java.nio.charset.StandardCharsets.UTF_8; public class CDataTransferer extends DataTransferer { private static final Map predefinedClipboardNameMap; @@ -133,7 +139,7 @@ public Object translateBytes(byte[] bytes, DataFlavor flavor, String charset = Charset.defaultCharset().name(); if (transferable != null && transferable.isDataFlavorSupported(javaTextEncodingFlavor)) { try { - charset = new String((byte[]) transferable.getTransferData(javaTextEncodingFlavor), StandardCharsets.UTF_8); + charset = new String((byte[]) transferable.getTransferData(javaTextEncodingFlavor), UTF_8); } catch (UnsupportedFlavorException cannotHappen) { } } @@ -160,7 +166,8 @@ public Object translateBytes(byte[] bytes, DataFlavor flavor, // class by base method format = CF_STRING; } else if (format == CF_STRING) { - bytes = Normalizer.normalize(new String(bytes, "UTF8"), Form.NFC).getBytes("UTF8"); + String src = new String(bytes, UTF_8); + bytes = Normalizer.normalize(src, Form.NFC).getBytes(UTF_8); } return super.translateBytes(bytes, flavor, format, transferable); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFLayer.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFLayer.java index 269bd6fdbac..d88d3311871 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFLayer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFLayer.java @@ -70,6 +70,10 @@ public boolean isOpaque() { return !peer.isTranslucent(); } + public void setOpaque(boolean opaque) { + // Default is no op (works well for OGL) + } + public int getTransparency() { return isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT; } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java index f2e5e18d42b..14063deec40 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java @@ -41,7 +41,6 @@ import sun.java2d.SurfaceData; import sun.java2d.opengl.CGLLayer; -import sun.lwawt.macosx.CFLayer; public class CPlatformView extends CFRetainedResource { private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr); @@ -135,6 +134,10 @@ public boolean isUnderMouse() { return ref.get(); } + public void setWindowLayerOpaque(boolean opaque) { + windowLayer.setOpaque(opaque); + } + public GraphicsDevice getGraphicsDevice() { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); CGraphicsEnvironment cge = (CGraphicsEnvironment)ge; 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 587612dafea..4dff56cba21 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -928,6 +928,7 @@ public void setOpacity(float opacity) { @Override public void setOpaque(boolean isOpaque) { + contentView.setWindowLayerOpaque(isOpaque); execute(ptr -> CWrapper.NSWindow.setOpaque(ptr, isOpaque)); boolean isTextured = (peer == null) ? false : peer.isTextured(); if (!isTextured) { 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 60da8dcac1d..8e44052333c 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -27,8 +27,7 @@ #import "CGLGraphicsConfig.h" #import "AWTView.h" #import "AWTWindow.h" -#import "JavaComponentAccessibility.h" -#import "JavaTextAccessibility.h" +#import "a11y/CommonComponentAccessibility.h" #import "JavaAccessibilityUtilities.h" #import "GeomUtilities.h" #import "ThreadUtilities.h" @@ -611,42 +610,29 @@ + (AWTView *) awtView:(JNIEnv*)env ofAccessible:(jobject)jaccessible - (id)getAxData:(JNIEnv*)env { jobject jcomponent = [self awtComponent:env]; - id ax = [[[JavaComponentAccessibility alloc] initWithParent:self withEnv:env withAccessible:jcomponent withIndex:-1 withView:self withJavaRole:nil] autorelease]; + id ax = [[[CommonComponentAccessibility alloc] initWithParent:self withEnv:env withAccessible:jcomponent withIndex:-1 withView:self withJavaRole:nil] autorelease]; (*env)->DeleteLocalRef(env, jcomponent); return ax; } -- (NSArray *)accessibilityAttributeNames -{ - return [[super accessibilityAttributeNames] arrayByAddingObject:NSAccessibilityChildrenAttribute]; -} - // NSAccessibility messages -// attribute methods -- (id)accessibilityAttributeValue:(NSString *)attribute +- (id)accessibilityChildren { AWT_ASSERT_APPKIT_THREAD; + JNIEnv *env = [ThreadUtilities getJNIEnv]; - if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) - { - JNIEnv *env = [ThreadUtilities getJNIEnv]; - - (*env)->PushLocalFrame(env, 4); + (*env)->PushLocalFrame(env, 4); - id result = NSAccessibilityUnignoredChildrenForOnlyChild([self getAxData:env]); + id result = NSAccessibilityUnignoredChildrenForOnlyChild([self getAxData:env]); - (*env)->PopLocalFrame(env, NULL); + (*env)->PopLocalFrame(env, NULL); - return result; - } - else - { - return [super accessibilityAttributeValue:attribute]; - } + return result; } -- (BOOL)accessibilityIsIgnored + +- (BOOL)isAccessibilityElement { - return YES; + return NO; } - (id)accessibilityHitTest:(NSPoint)point @@ -656,7 +642,7 @@ - (id)accessibilityHitTest:(NSPoint)point (*env)->PushLocalFrame(env, 4); - id result = [[self getAxData:env] accessibilityHitTest:point withEnv:env]; + id result = [[self getAxData:env] accessibilityHitTest:point]; (*env)->PopLocalFrame(env, NULL); @@ -681,17 +667,24 @@ - (id)accessibilityFocusedUIElement // --- Services menu support for lightweights --- // finds the focused accessible element, and if it is a text element, obtains the text from it -- (NSString *)accessibleSelectedText +- (NSString *)accessibilitySelectedText { id focused = [self accessibilityFocusedUIElement]; - if (![focused isKindOfClass:[JavaTextAccessibility class]]) return nil; - return [(JavaTextAccessibility *)focused accessibilitySelectedTextAttribute]; + if (![focused respondsToSelector:@selector(accessibilitySelectedText)]) return nil; + return [focused accessibilitySelectedText]; +} + +- (void)setAccessibilitySelectedText:(NSString *)accessibilitySelectedText { + id focused = [self accessibilityFocusedUIElement]; + if ([focused respondsToSelector:@selector(setAccessibilitySelectedText:)]) { + [focused setAccessibilitySelectedText:accessibilitySelectedText]; +} } // same as above, but converts to RTFD - (NSData *)accessibleSelectedTextAsRTFD { - NSString *selectedText = [self accessibleSelectedText]; + NSString *selectedText = [self accessibilitySelectedText]; NSAttributedString *styledText = [[NSAttributedString alloc] initWithString:selectedText]; NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) documentAttributes: @@ -704,8 +697,8 @@ - (NSData *)accessibleSelectedTextAsRTFD - (BOOL)replaceAccessibleTextSelection:(NSString *)text { id focused = [self accessibilityFocusedUIElement]; - if (![focused isKindOfClass:[JavaTextAccessibility class]]) return NO; - [(JavaTextAccessibility *)focused accessibilitySetSelectedTextAttribute:text]; + if (![focused respondsToSelector:@selector(setAccessibilitySelectedText)]) return NO; + [focused setAccessibilitySelectedText:text]; return YES; } @@ -715,7 +708,7 @@ - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)retu if ([[self window] firstResponder] != self) return nil; // let AWT components handle themselves if ([sendType isEqual:NSStringPboardType] || [returnType isEqual:NSStringPboardType]) { - NSString *selectedText = [self accessibleSelectedText]; + NSString *selectedText = [self accessibilitySelectedText]; if (selectedText) return self; } @@ -728,7 +721,7 @@ - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types if ([types containsObject:NSStringPboardType]) { [pboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; - return [pboard setString:[self accessibleSelectedText] forType:NSStringPboardType]; + return [pboard setString:[self accessibilitySelectedText] forType:NSStringPboardType]; } if ([types containsObject:NSRTFDPboardType]) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.h index a628c4de5b1..b8042db69b7 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.h @@ -26,6 +26,10 @@ #import #import +extern NSMutableDictionary *sActions; +extern NSMutableDictionary *sActionSelectors; +extern NSMutableArray *sAllActionSelectors; +void initializeActions(); @protocol JavaAccessibilityAction diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m index 03a5630b608..06e998ec409 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m @@ -29,6 +29,10 @@ #import "ThreadUtilities.h" #import "JNIUtilities.h" +NSMutableDictionary *sActions = nil; +NSMutableDictionary *sActionSelectors = nil; +NSMutableArray *sAllActionSelectors = nil; +void initializeActions(); @implementation JavaAxAction @@ -148,3 +152,31 @@ - (void)perform } @end + +void initializeActions() { + int actionsCount = 5; + + sActions = [[NSMutableDictionary alloc] initWithCapacity:actionsCount]; + + [sActions setObject:NSAccessibilityPressAction forKey:@"click"]; + [sActions setObject:NSAccessibilityIncrementAction forKey:@"increment"]; + [sActions setObject:NSAccessibilityDecrementAction forKey:@"decrement"]; + [sActions setObject:NSAccessibilityShowMenuAction forKey:@"togglePopup"]; + [sActions setObject:NSAccessibilityPressAction forKey:@"toggleExpand"]; + + sActionSelectors = [[NSMutableDictionary alloc] initWithCapacity:actionsCount]; + + [sActionSelectors setObject:NSStringFromSelector(@selector(accessibilityPerformPress)) forKey:NSAccessibilityPressAction]; + [sActionSelectors setObject:NSStringFromSelector(@selector(accessibilityPerformShowMenu)) forKey:NSAccessibilityShowMenuAction]; + [sActionSelectors setObject:NSStringFromSelector(@selector(accessibilityPerformDecrement)) forKey:NSAccessibilityDecrementAction]; + [sActionSelectors setObject:NSStringFromSelector(@selector(accessibilityPerformIncrement)) forKey:NSAccessibilityIncrementAction]; + [sActionSelectors setObject:NSStringFromSelector(@selector(accessibilityPerformPick)) forKey:NSAccessibilityPickAction]; + + sAllActionSelectors = [[NSMutableArray alloc] initWithCapacity:actionsCount]; + + [sAllActionSelectors addObject:NSStringFromSelector(@selector(accessibilityPerformPick))]; + [sAllActionSelectors addObject:NSStringFromSelector(@selector(accessibilityPerformIncrement))]; + [sAllActionSelectors addObject:NSStringFromSelector(@selector(accessibilityPerformDecrement))]; + [sAllActionSelectors addObject:NSStringFromSelector(@selector(accessibilityPerformShowMenu))]; + [sAllActionSelectors addObject:NSStringFromSelector(@selector(accessibilityPerformPress))]; +} diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h index f3dfe247ede..b829335fc29 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h @@ -48,6 +48,7 @@ BOOL isVertical(JNIEnv *env, jobject axContext, jobject component); BOOL isHorizontal(JNIEnv *env, jobject axContext, jobject component); BOOL isShowing(JNIEnv *env, jobject axContext, jobject component); BOOL isSelectable(JNIEnv *env, jobject axContext, jobject component); +BOOL isExpanded(JNIEnv *env, jobject axContext, jobject component); NSPoint getAxComponentLocationOnScreen(JNIEnv *env, jobject axComponent, jobject component); jint getAxTextCharCount(JNIEnv *env, jobject axText, jobject component); @@ -60,3 +61,6 @@ void JavaAccessibilitySetAttributeValue(id element, NSString *attribute, id valu void JavaAccessibilityRaiseSetAttributeToIllegalTypeException(const char *functionName, id element, NSString *attribute, id value); void JavaAccessibilityRaiseUnimplementedAttributeException(const char *functionName, id element, NSString *attribute); void JavaAccessibilityRaiseIllegalParameterTypeException(const char *functionName, id element, NSString *attribute, id parameter); +BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component); +NSNumber* JavaNumberToNSNumber(JNIEnv *env, jobject jnumber); +NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m index 12817e63ecd..9520c3d552b 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m @@ -27,6 +27,7 @@ #import "JNIUtilities.h" #import +#import "ThreadUtilities.h" static BOOL JavaAccessibilityIsSupportedAttribute(id element, NSString *attribute); static void JavaAccessibilityLogError(NSString *message); @@ -199,6 +200,20 @@ BOOL isSelectable(JNIEnv *env, jobject axContext, jobject component) return selectable; } +BOOL isExpanded(JNIEnv *env, jobject axContext, jobject component) +{ + GET_ACCESSIBLESTATE_CLASS_RETURN(NO); + DECLARE_STATIC_FIELD_RETURN(jm_EXPANDED, + sjc_AccessibleState, + "EXPANDED", + "Ljavax/accessibility/AccessibleState;", NO ); + jobject axExpandedState = (*env)->GetStaticObjectField(env, sjc_AccessibleState, jm_EXPANDED); + CHECK_EXCEPTION_NULL_RETURN(axExpandedState, NO); + BOOL expanded = containsAxState(env, axContext, axExpandedState, component); + (*env)->DeleteLocalRef(env, axExpandedState); + return expanded; +} + NSPoint getAxComponentLocationOnScreen(JNIEnv *env, jobject axComponent, jobject component) { GET_CACCESSIBILITY_CLASS_RETURN(NSZeroPoint); @@ -348,6 +363,75 @@ static void JavaAccessibilityLogError(NSString *message) NSLog(@"!!! %@", message); } +/* + * Returns Object.equals for the two items + * This may use LWCToolkit.invokeAndWait(); don't call while holding fLock + * and try to pass a component so the event happens on the correct thread. + */ +BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component) +{ + DECLARE_CLASS_RETURN(sjc_Object, "java/lang/Object", NO); + DECLARE_METHOD_RETURN(jm_equals, sjc_Object, "equals", "(Ljava/lang/Object;)Z", NO); + + if ((a == NULL) && (b == NULL)) return YES; + if ((a == NULL) || (b == NULL)) return NO; + + if (pthread_main_np() != 0) { + // If we are on the AppKit thread + DECLARE_CLASS_RETURN(sjc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit", NO); + DECLARE_STATIC_METHOD_RETURN(jm_doEquals, sjc_LWCToolkit, "doEquals", + "(Ljava/lang/Object;Ljava/lang/Object;Ljava/awt/Component;)Z", NO); + return (*env)->CallStaticBooleanMethod(env, sjc_LWCToolkit, jm_doEquals, a, b, component); + CHECK_EXCEPTION(); + } + + jboolean jb = (*env)->CallBooleanMethod(env, a, jm_equals, b); + CHECK_EXCEPTION(); + return jb; +} + +/* + * The java/lang/Number concrete class could be for any of the Java primitive + * numerical types or some other subclass. + * All existing A11Y code uses Integer so that is what we look for first + * But all must be able to return a double and NSNumber accepts a double, + * so that's the fall back. + */ +NSNumber* JavaNumberToNSNumber(JNIEnv *env, jobject jnumber) { + if (jnumber == NULL) { + return nil; + } + DECLARE_CLASS_RETURN(jnumber_Class, "java/lang/Number", nil); + DECLARE_CLASS_RETURN(jinteger_Class, "java/lang/Integer", nil); + DECLARE_METHOD_RETURN(jm_intValue, jnumber_Class, "intValue", "()I", nil); + DECLARE_METHOD_RETURN(jm_doubleValue, jnumber_Class, "doubleValue", "()D", nil); + if ((*env)->IsInstanceOf(env, jnumber, jinteger_Class)) { + jint i = (*env)->CallIntMethod(env, jnumber, jm_intValue); + CHECK_EXCEPTION(); + return [NSNumber numberWithInteger:i]; + } else { + jdouble d = (*env)->CallDoubleMethod(env, jnumber, jm_doubleValue); + CHECK_EXCEPTION(); + return [NSNumber numberWithDouble:d]; + } +} + +/* + * Converts an int array to an NSRange wrapped inside an NSValue + * takes [start, end] values and returns [start, end - start] + */ +NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { + jint *values = (*env)->GetIntArrayElements(env, array, 0); + if (values == NULL) { + // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck. + NSLog(@"%s failed calling GetIntArrayElements", __FUNCTION__); + return nil; + }; + NSValue *value = [NSValue valueWithRange:NSMakeRange(values[0], values[1] - values[0])]; + (*env)->ReleaseIntArrayElements(env, array, values, 0); + return value; +} + // end appKit copies /* @@ -417,13 +501,13 @@ void initializeRoles() [sRoles setObject:NSAccessibilitySplitGroupRole forKey:@"splitpane"]; [sRoles setObject:NSAccessibilityValueIndicatorRole forKey:@"statusbar"]; [sRoles setObject:NSAccessibilityGroupRole forKey:@"swingcomponent"]; - [sRoles setObject:NSAccessibilityGridRole forKey:@"table"]; + [sRoles setObject:NSAccessibilityTableRole forKey:@"table"]; [sRoles setObject:NSAccessibilityTextFieldRole forKey:@"text"]; [sRoles setObject:NSAccessibilityTextAreaRole forKey:@"textarea"]; // supports top/bottom of document notifications: CAccessability.getAccessibleRole() [sRoles setObject:NSAccessibilityCheckBoxRole forKey:@"togglebutton"]; [sRoles setObject:NSAccessibilityToolbarRole forKey:@"toolbar"]; [sRoles setObject:JavaAccessibilityIgnore forKey:@"tooltip"]; - [sRoles setObject:NSAccessibilityBrowserRole forKey:@"tree"]; + [sRoles setObject:NSAccessibilityOutlineRole forKey:@"tree"]; [sRoles setObject:NSAccessibilityUnknownRole forKey:@"unknown"]; [sRoles setObject:JavaAccessibilityIgnore forKey:@"viewport"]; [sRoles setObject:JavaAccessibilityIgnore forKey:@"window"]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m index 33e838b070a..9db8342f844 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m @@ -29,7 +29,6 @@ // #import "JavaComponentAccessibility.h" -#import "a11y/CommonComponentAccessibility.h" #import "sun_lwawt_macosx_CAccessibility.h" #import @@ -45,6 +44,12 @@ #import "JNIUtilities.h" #import "AWTView.h" +// these constants are duplicated in CAccessibility.java +#define JAVA_AX_ALL_CHILDREN (-1) +#define JAVA_AX_SELECTED_CHILDREN (-2) +#define JAVA_AX_VISIBLE_CHILDREN (-3) +// If the value is >=0, it's an index + // GET* macros defined in JavaAccessibilityUtilities.h, so they can be shared. static jclass sjc_CAccessibility = NULL; @@ -82,7 +87,7 @@ static NSMutableDictionary *sAttributeNamesForRoleCache = nil; static NSObject *sAttributeNamesLOCK = nil; -@interface TabGroupAccessibility : JavaComponentAccessibility { +@interface TabGroupLegacyAccessibility : JavaComponentAccessibility { NSInteger _numTabs; } @@ -112,7 +117,7 @@ - (void)getActionsWithEnv:(JNIEnv *)env; - (id)accessibilityValueAttribute; @end -@interface TableAccessibility : JavaComponentAccessibility { +@interface TableLegacyAccessibility : JavaComponentAccessibility { } - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env; @@ -362,21 +367,18 @@ + (JavaComponentAccessibility *) createWithParent:(JavaComponentAccessibility *) // otherwise, create a new instance JavaComponentAccessibility *newChild = nil; - newChild = [CommonComponentAccessibility getComponentAccessibility:javaRole]; - if (newChild == nil) { - if ([javaRole isEqualToString:@"pagetablist"]) { - newChild = [TabGroupAccessibility alloc]; - } else if ([javaRole isEqualToString:@"table"]) { - newChild = [TableAccessibility alloc]; + if ([javaRole isEqualToString:@"pagetablist"]) { + newChild = [TabGroupLegacyAccessibility alloc]; + } else if ([javaRole isEqualToString:@"table"]) { + newChild = [TableLegacyAccessibility alloc]; + } else { + NSString *nsRole = [sRoles objectForKey:javaRole]; + if ([nsRole isEqualToString:NSAccessibilityStaticTextRole] || + [nsRole isEqualToString:NSAccessibilityTextAreaRole] || + [nsRole isEqualToString:NSAccessibilityTextFieldRole]) { + newChild = [JavaTextAccessibility alloc]; } else { - NSString *nsRole = [sRoles objectForKey:javaRole]; - if ([nsRole isEqualToString:NSAccessibilityStaticTextRole] || - [nsRole isEqualToString:NSAccessibilityTextAreaRole] || - [nsRole isEqualToString:NSAccessibilityTextFieldRole]) { - newChild = [JavaTextAccessibility alloc]; - } else { - newChild = [JavaComponentAccessibility alloc]; - } + newChild = [JavaComponentAccessibility alloc]; } } @@ -387,7 +389,7 @@ + (JavaComponentAccessibility *) createWithParent:(JavaComponentAccessibility *) // This is the only way to know if the menu is opening; visible state change // can't be caught because the listeners are not set up in time. if ( [javaRole isEqualToString:@"popupmenu"] && - ![[parent javaRole] isEqualToString:@"combobox"] ) { + ![[parent javaRole] isEqualToString:@"combobox"] ) { [newChild postMenuOpened]; } @@ -904,32 +906,6 @@ - (NSInteger)accessibilityIndex { return index; } -/* - * The java/lang/Number concrete class could be for any of the Java primitive - * numerical types or some other subclass. - * All existing A11Y code uses Integer so that is what we look for first - * But all must be able to return a double and NSNumber accepts a double, - * so that's the fall back. - */ -static NSNumber* JavaNumberToNSNumber(JNIEnv *env, jobject jnumber) { - if (jnumber == NULL) { - return nil; - } - DECLARE_CLASS_RETURN(jnumber_Class, "java/lang/Number", nil); - DECLARE_CLASS_RETURN(jinteger_Class, "java/lang/Integer", nil); - DECLARE_METHOD_RETURN(jm_intValue, jnumber_Class, "intValue", "()I", nil); - DECLARE_METHOD_RETURN(jm_doubleValue, jnumber_Class, "doubleValue", "()D", nil); - if ((*env)->IsInstanceOf(env, jnumber, jinteger_Class)) { - jint i = (*env)->CallIntMethod(env, jnumber, jm_intValue); - CHECK_EXCEPTION(); - return [NSNumber numberWithInteger:i]; - } else { - jdouble d = (*env)->CallDoubleMethod(env, jnumber, jm_doubleValue); - CHECK_EXCEPTION(); - return [NSNumber numberWithDouble:d]; - } -} - // Element's maximum value (id) - (id)accessibilityMaxValueAttribute { @@ -1600,7 +1576,7 @@ - (id)accessibilityFocusedUIElement JNI_COCOA_EXIT(env); } -@implementation TabGroupAccessibility +@implementation TabGroupLegacyAccessibility - (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withView:(NSView *)view withJavaRole:(NSString *)javaRole { @@ -1802,9 +1778,6 @@ - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUI @end - -static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component); - @implementation TabGroupControlAccessibility - (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole @@ -1873,7 +1846,7 @@ - (jobject)tabGroup #define JAVA_AX_ROWS (1) #define JAVA_AX_COLS (2) -@implementation TableAccessibility +@implementation TableLegacyAccessibility - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env { @@ -1907,30 +1880,3 @@ - (id)accessibilityColumnCountAttribute { return [self getTableInfo:JAVA_AX_COLS]; } @end - -/* - * Returns Object.equals for the two items - * This may use LWCToolkit.invokeAndWait(); don't call while holding fLock - * and try to pass a component so the event happens on the correct thread. - */ -static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component) -{ - DECLARE_CLASS_RETURN(sjc_Object, "java/lang/Object", NO); - DECLARE_METHOD_RETURN(jm_equals, sjc_Object, "equals", "(Ljava/lang/Object;)Z", NO); - - if ((a == NULL) && (b == NULL)) return YES; - if ((a == NULL) || (b == NULL)) return NO; - - if (pthread_main_np() != 0) { - // If we are on the AppKit thread - DECLARE_CLASS_RETURN(sjc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit", NO); - DECLARE_STATIC_METHOD_RETURN(jm_doEquals, sjc_LWCToolkit, "doEquals", - "(Ljava/lang/Object;Ljava/lang/Object;Ljava/awt/Component;)Z", NO); - return (*env)->CallStaticBooleanMethod(env, sjc_LWCToolkit, jm_doEquals, a, b, component); - CHECK_EXCEPTION(); - } - - jboolean jb = (*env)->CallBooleanMethod(env, a, jm_equals, b); - CHECK_EXCEPTION(); - return jb; -} diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m index 730e98e4147..4036775d275 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m @@ -53,23 +53,6 @@ GET_STATIC_METHOD_RETURN(sjm_getAccessibleEditableText, sjc_CAccessibleText, "getAccessibleEditableText", \ "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleEditableText;", ret); - -/* - * Converts an int array to an NSRange wrapped inside an NSValue - * takes [start, end] values and returns [start, end - start] - */ -NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { - jint *values = (*env)->GetIntArrayElements(env, array, 0); - if (values == NULL) { - // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck. - NSLog(@"%s failed calling GetIntArrayElements", __FUNCTION__); - return nil; - }; - NSValue *value = [NSValue valueWithRange:NSMakeRange(values[0], values[1] - values[0])]; - (*env)->ReleaseIntArrayElements(env, array, values, 0); - return value; -} - @implementation JavaTextAccessibility // based strongly upon NSTextViewAccessibility:accessibilityAttributeNames diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ButtonAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ButtonAccessibility.m index 912cef1fa67..8748d42bfa7 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ButtonAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ButtonAccessibility.m @@ -36,7 +36,7 @@ - (NSAccessibilityRole _Nonnull)accessibilityRole - (NSString * _Nullable)accessibilityLabel { - return [self accessibilityTitleAttribute]; + return [super accessibilityLabel]; } - (BOOL)accessibilityPerformPress @@ -44,4 +44,14 @@ - (BOOL)accessibilityPerformPress return [self performAccessibleAction:0]; } +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h new file mode 100644 index 00000000000..bcaa0269576 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface CellAccessibility : CommonComponentAccessibility +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m new file mode 100644 index 00000000000..688d8eb3176 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CellAccessibility.h" +#import "ThreadUtilities.h" +#import "TableAccessibility.h" + +@implementation CellAccessibility + +// NSAccessibilityElement protocol methods + +- (NSAccessibilityRole)accessibilityRole +{ + return NSAccessibilityCellRole;; +} + +- (NSArray *)accessibilityChildren +{ + NSArray *children = [super accessibilityChildren]; + if (children == NULL) { + NSString *javaRole = [self javaRole]; + CommonComponentAccessibility *newChild = [CommonComponentAccessibility createWithParent:self + accessible:self->fAccessible + role:javaRole + index:self->fIndex + withEnv:[ThreadUtilities getJNIEnv] + withView:self->fView + isWrapped:NO]; + return [NSArray arrayWithObject:newChild]; + } else { + return children; + } +} + +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + +- (NSRange)accessibilityRowIndexRange { + NSInteger location = -1; + if ([[(CommonComponentAccessibility *)fParent accessibilityParent] isKindOfClass:[TableAccessibility class]]) { + TableAccessibility *table = [(CommonComponentAccessibility *)fParent accessibilityParent]; + location = [table accessibleRowAtIndex:fIndex]; + } + + return NSMakeRange(location, 1); +} + +- (NSRange)accessibilityColumnIndexRange { + NSInteger location = -1; + if ([[(CommonComponentAccessibility *)fParent accessibilityParent] isKindOfClass:[TableAccessibility class]]) { + TableAccessibility *table = [(CommonComponentAccessibility *)fParent accessibilityParent]; + location = [table accessibleColumnAtIndex:fIndex]; + } + + return NSMakeRange(location, 1); +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m index bbfaf39fe66..f2dbf60d92d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m @@ -39,7 +39,7 @@ - (NSAccessibilityRole _Nonnull)accessibilityRole - (id _Nonnull) accessibilityValue { AWT_ASSERT_APPKIT_THREAD; - return [self accessibilityValueAttribute]; + return [super accessibilityValue]; } @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h new file mode 100644 index 00000000000..a78afaa924b --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface ColumnAccessibility : CommonComponentAccessibility + +@property(readonly) NSUInteger columnNumberInTable; + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m new file mode 100644 index 00000000000..9d4582445a4 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "jni.h" +#import "JavaAccessibilityAction.h" +#import "JavaAccessibilityUtilities.h" +#import "CellAccessibility.h" +#import "ColumnAccessibility.h" +#import "TableAccessibility.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" +#import "sun_lwawt_macosx_CAccessibility.h" + +static jclass sjc_CAccessibility = NULL; + +static jmethodID jm_getChildrenAndRoles = NULL; +#define GET_CHILDRENANDROLES_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(jm_getChildrenAndRoles, sjc_CAccessibility, "getChildrenAndRoles",\ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;IZ)[Ljava/lang/Object;", ret); + +@implementation ColumnAccessibility + +// NSAccessibilityElement protocol methods + +- (NSAccessibilityRole)accessibilityRole +{ + return NSAccessibilityColumnRole; +} + +- (NSArray *)accessibilityChildren +{ + NSArray *children = [super accessibilityChildren]; + if (children == NULL) { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + CommonComponentAccessibility *parent = [self accessibilityParent]; + if (parent->fAccessible == NULL) return nil; + GET_CHILDRENANDROLES_METHOD_RETURN(nil); + jobjectArray jchildrenAndRoles = (jobjectArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getChildrenAndRoles, + parent->fAccessible, parent->fComponent, sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN, NO); + CHECK_EXCEPTION(); + if (jchildrenAndRoles == NULL) return nil; + + jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles); + NSMutableArray *childrenCells = [NSMutableArray arrayWithCapacity:arrayLen/2]; + + NSUInteger childIndex = fIndex; + + int inc = [(TableAccessibility *)[self accessibilityParent] accessibilityRowCount] * 2; + NSInteger i = childIndex * 2; + for(i; i < arrayLen; i += inc) + { + jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i); + jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1); + + NSString *childJavaRole = nil; + if (jchildJavaRole != NULL) { + DECLARE_CLASS_RETURN(sjc_AccessibleRole, "javax/accessibility/AccessibleRole", nil); + DECLARE_FIELD_RETURN(sjf_key, sjc_AccessibleRole, "key", "Ljava/lang/String;", nil); + jobject jkey = (*env)->GetObjectField(env, jchildJavaRole, sjf_key); + CHECK_EXCEPTION(); + childJavaRole = JavaStringToNSString(env, jkey); + (*env)->DeleteLocalRef(env, jkey); + } + + CellAccessibility *child = [[CellAccessibility alloc] initWithParent:self + withEnv:env + withAccessible:jchild + withIndex:childIndex + withView:self->fView + withJavaRole:childJavaRole]; + [childrenCells addObject:[[child retain] autorelease]]; + + (*env)->DeleteLocalRef(env, jchild); + (*env)->DeleteLocalRef(env, jchildJavaRole); + + childIndex += (inc / 2); + } + (*env)->DeleteLocalRef(env, jchildrenAndRoles); + return childrenCells; + } else { + return children; + } +} + +- (NSInteger)accessibilityIndex +{ + return fIndex; +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h new file mode 100644 index 00000000000..4a39938a826 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface ComboBoxAccessibility : CommonComponentAccessibility +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m new file mode 100644 index 00000000000..63c00414d66 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "ComboBoxAccessibility.h" +#import "../JavaAccessibilityUtilities.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" + +static jclass sjc_CAccessibility = NULL; + +static jmethodID sjm_getAccessibleName = NULL; +#define GET_ACCESSIBLENAME_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", \ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", ret); + +@implementation ComboBoxAccessibility + +// NSAccessibilityElement protocol methods + +- (id)accessibilityValue { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + if (axContext == NULL) return nil; + jclass axContextClass = (*env)->GetObjectClass(env, axContext); + DECLARE_METHOD_RETURN(jm_getAccessibleSelection, axContextClass, "getAccessibleSelection", "(I)Ljavax/accessibility/Accessible;", nil); + jobject axSelectedChild = (*env)->CallObjectMethod(env, axContext, jm_getAccessibleSelection, 0); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, axContext); + if (axSelectedChild == NULL) { + return nil; + } + GET_CACCESSIBILITY_CLASS_RETURN(nil); + GET_ACCESSIBLENAME_METHOD_RETURN(nil); + jobject childName = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleName, axSelectedChild, fComponent); + CHECK_EXCEPTION(); + if (childName == NULL) { + (*env)->DeleteLocalRef(env, axSelectedChild); + return nil; + } + NSString *selectedText = JavaStringToNSString(env, childName); + (*env)->DeleteLocalRef(env, axSelectedChild); + (*env)->DeleteLocalRef(env, childName); + return selectedText; +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h index 4140e0ea5f7..0e946b4a67f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h @@ -26,23 +26,83 @@ #ifndef JAVA_COMPONENT_ACCESSIBILITY #define JAVA_COMPONENT_ACCESSIBILITY -#import "JavaComponentAccessibility.h" +#include "jni.h" + +#import #import "JavaAccessibilityUtilities.h" -// these constants are duplicated in CAccessibility.java -#define JAVA_AX_ALL_CHILDREN (-1) -#define JAVA_AX_SELECTED_CHILDREN (-2) -#define JAVA_AX_VISIBLE_CHILDREN (-3) -// If the value is >=0, it's an index +@interface CommonComponentAccessibility : NSAccessibilityElement { + NSView *fView; + NSObject *fParent; + + NSString *fNSRole; + NSString *fJavaRole; -@interface CommonComponentAccessibility : JavaComponentAccessibility { + jint fIndex; + jobject fAccessible; + jobject fComponent; + NSMutableDictionary *fActions; + NSMutableArray *fActionSelectors; + NSObject *fActionsLOCK; } + +@property(nonnull, readonly) NSArray *actionSelectors; + +- (id _Nonnull)initWithParent:(NSObject* _Nonnull)parent withEnv:(JNIEnv _Nonnull * _Nonnull)env withAccessible:(jobject _Nullable)accessible withIndex:(jint)index withView:(NSView* _Nonnull)view withJavaRole:(NSString* _Nullable)javaRole; +- (void)unregisterFromCocoaAXSystem; +- (void)postValueChanged; +- (void)postSelectedTextChanged; +- (void)postSelectionChanged; +- (void)postTitleChanged; +- (void)postTreeNodeExpanded; +- (void)postTreeNodeCollapsed; +- (BOOL)isEqual:(nonnull id)anObject; +- (BOOL)isAccessibleWithEnv:(JNIEnv _Nonnull * _Nonnull)env forAccessible:(nonnull jobject)accessible; + ++ (void)postFocusChanged:(nullable id)message; + + (void) initializeRolesMap; -+ (JavaComponentAccessibility * _Nullable) getComponentAccessibility:(NSString * _Nonnull)role; + ++ (CommonComponentAccessibility* _Nullable) getComponentAccessibility:(NSString* _Nonnull)role; ++ (CommonComponentAccessibility * _Nullable) getComponentAccessibility:(NSString * _Nonnull)role andParent:(CommonComponentAccessibility * _Nonnull)parent; + ++ (NSArray* _Nullable)childrenOfParent:(CommonComponentAccessibility* _Nonnull)parent withEnv:(JNIEnv _Nonnull * _Nonnull)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored; ++ (NSArray* _Nullable)childrenOfParent:(CommonComponentAccessibility* _Nonnull)parent withEnv:(JNIEnv _Nonnull * _Nonnull)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored recursive:(BOOL)recursive; ++ (CommonComponentAccessibility* _Nullable) createWithParent:(CommonComponentAccessibility* _Nullable)parent accessible:(jobject _Nonnull)jaccessible role:(NSString* _Nonnull)javaRole index:(jint)index withEnv:(JNIEnv _Nonnull * _Nonnull)env withView:(NSView* _Nonnull)view; ++ (CommonComponentAccessibility* _Nullable) createWithAccessible:(jobject _Nonnull)jaccessible role:(NSString* _Nonnull)role index:(jint)index withEnv:(JNIEnv _Nonnull * _Nonnull)env withView:(NSView* _Nonnull)view; ++ (CommonComponentAccessibility* _Nullable) createWithAccessible:(jobject _Nonnull)jaccessible withEnv:(JNIEnv _Nonnull * _Nonnull)env withView:(NSView* _Nonnull)view; + +// If the isWraped parameter is true, then the object passed as a parent was created based on the same java component, +// but performs a different NSAccessibilityRole of a table cell, or a list row, or tree row, +// and we need to create an element whose role corresponds to the role in Java. ++ (CommonComponentAccessibility* _Nullable) createWithParent:(CommonComponentAccessibility* _Nullable)parent accessible:(jobject _Nonnull)jaccessible role:(NSString* _Nonnull)javaRole index:(jint)index withEnv:(JNIEnv _Nonnull * _Nonnull)env withView:(NSView* _Nonnull)view isWrapped:(BOOL)wrapped; + +// The current parameter is used to bypass the check for an item's index on the parent so that the item is created. This is necessary, +// for example, for AccessibleJTreeNode, whose currentComponent has index -1 ++ (CommonComponentAccessibility* _Nullable) createWithAccessible:(jobject _Nonnull)jaccessible withEnv:(JNIEnv _Nonnull * _Nonnull)env withView:(NSView* _Nonnull)view isCurrent:(BOOL)current; + +- (jobject _Nullable)axContextWithEnv:(JNIEnv _Nonnull * _Nonnull)env; +- (NSView* _Nonnull)view; +- (NSWindow* _Nonnull)window; +- (id _Nonnull)parent; +- (NSString* _Nonnull)javaRole; + +- (BOOL)isMenu; +- (BOOL)isSelected:(JNIEnv _Nonnull * _Nonnull)env; +- (BOOL)isSelectable:(JNIEnv _Nonnull * _Nonnull)env; +- (BOOL)isVisible:(JNIEnv _Nonnull * _Nonnull)env; + +- (NSArray* _Nullable)accessibleChildrenWithChildCode:(NSInteger)childCode; + +- (NSDictionary* _Nullable)getActions:(JNIEnv _Nonnull * _Nonnull)env; +- (void)getActionsWithEnv:(JNIEnv _Nonnull * _Nonnull)env; +- (BOOL)accessiblePerformAction:(NSAccessibilityActionName _Nonnull)actionName; + +- (BOOL)performAccessibleAction:(int)index; + - (NSRect)accessibilityFrame; - (id _Nullable)accessibilityParent; -- (BOOL)performAccessibleAction:(int)index; - (BOOL)isAccessibilityElement; @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m index 25317afa3b3..9fe7ce4e520 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m @@ -24,18 +24,57 @@ */ #import "CommonComponentAccessibility.h" -#import "JNIUtilities.h" +#import +#import +#import +#import "JavaAccessibilityAction.h" +#import "JavaAccessibilityUtilities.h" #import "ThreadUtilities.h" +#import "JNIUtilities.h" +#import "AWTView.h" +#import "sun_lwawt_macosx_CAccessible.h" +#import "sun_lwawt_macosx_CAccessibility.h" + +// GET* macros defined in JavaAccessibilityUtilities.h, so they can be shared. static jclass sjc_CAccessibility = NULL; -static jmethodID sjm_getAccessibleComponent = NULL; +static jmethodID sjm_getAccessibleName = NULL; +#define GET_ACCESSIBLENAME_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", \ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", ret); + +static jmethodID jm_getChildrenAndRoles = NULL; +#define GET_CHILDRENANDROLES_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(jm_getChildrenAndRoles, sjc_CAccessibility, "getChildrenAndRoles",\ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;IZ)[Ljava/lang/Object;", ret); + +static jmethodID jm_getChildrenAndRolesRecursive = NULL; +#define GET_CHILDRENANDROLESRECURSIVE_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(jm_getChildrenAndRolesRecursive, sjc_CAccessibility, "getChildrenAndRolesRecursive",\ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;IZI)[Ljava/lang/Object;", ret); + +static jmethodID sjm_getAccessibleComponent = NULL; #define GET_ACCESSIBLECOMPONENT_STATIC_METHOD_RETURN(ret) \ GET_CACCESSIBILITY_CLASS_RETURN(ret); \ GET_STATIC_METHOD_RETURN(sjm_getAccessibleComponent, sjc_CAccessibility, "getAccessibleComponent", \ "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleComponent;", ret); +static jmethodID sjm_getAccessibleIndexInParent = NULL; +#define GET_ACCESSIBLEINDEXINPARENT_STATIC_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(sjm_getAccessibleIndexInParent, sjc_CAccessibility, "getAccessibleIndexInParent", \ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I", ret); + +static jclass sjc_CAccessible = NULL; +#define GET_CACCESSIBLE_CLASS_RETURN(ret) \ + GET_CLASS_RETURN(sjc_CAccessible, "sun/lwawt/macosx/CAccessible", ret); + static NSMutableDictionary * _Nullable rolesMap; +static NSMutableDictionary * _Nullable rowRolesMapForParent; NSString *const IgnoreClassName = @"IgnoreAccessibility"; static jobject sAccessibilityClass = NULL; @@ -44,11 +83,46 @@ */ @implementation CommonComponentAccessibility +- (BOOL)isMenu +{ + id role = [self accessibilityRole]; + return [role isEqualToString:NSAccessibilityMenuBarRole] || [role isEqualToString:NSAccessibilityMenuRole] || [role isEqualToString:NSAccessibilityMenuItemRole]; +} + +- (BOOL)isSelected:(JNIEnv *)env +{ + if (fIndex == -1) { + return NO; + } + + return isChildSelected(env, ((CommonComponentAccessibility *)[self parent])->fAccessible, fIndex, fComponent); +} + +- (BOOL)isSelectable:(JNIEnv *)env +{ + jobject axContext = [self axContextWithEnv:env]; + BOOL selectable = isSelectable(env, axContext, fComponent); + (*env)->DeleteLocalRef(env, axContext); + return selectable; +} + +- (BOOL)isVisible:(JNIEnv *)env +{ + if (fIndex == -1) { + return NO; + } + + jobject axContext = [self axContextWithEnv:env]; + BOOL showing = isShowing(env, axContext, fComponent); + (*env)->DeleteLocalRef(env, axContext); + return showing; +} + + (void) initializeRolesMap { /* * Here we should keep all the mapping between the accessibility roles and implementing classes */ - rolesMap = [[NSMutableDictionary alloc] initWithCapacity:37]; + rolesMap = [[NSMutableDictionary alloc] initWithCapacity:46]; [rolesMap setObject:@"ButtonAccessibility" forKey:@"pushbutton"]; [rolesMap setObject:@"ImageAccessibility" forKey:@"icon"]; @@ -69,6 +143,15 @@ + (void) initializeRolesMap { [rolesMap setObject:@"ToolbarAccessibility" forKey:@"toolbar"]; [rolesMap setObject:@"SplitpaneAccessibility" forKey:@"splitpane"]; [rolesMap setObject:@"StatusbarAccessibility" forKey:@"statusbar"]; + [rolesMap setObject:@"NavigableTextAccessibility" forKey:@"textarea"]; + [rolesMap setObject:@"NavigableTextAccessibility" forKey:@"text"]; + [rolesMap setObject:@"NavigableTextAccessibility" forKey:@"passwordtext"]; + [rolesMap setObject:@"NavigableTextAccessibility" forKey:@"dateeditor"]; + [rolesMap setObject:@"ComboBoxAccessibility" forKey:@"combobox"]; + [rolesMap setObject:@"TabGroupAccessibility" forKey:@"pagetablist"]; + [rolesMap setObject:@"ListAccessibility" forKey:@"list"]; + [rolesMap setObject:@"OutlineAccessibility" forKey:@"tree"]; + [rolesMap setObject:@"TableAccessibility" forKey:@"table"]; /* * All the components below should be ignored by the accessibility subsystem, @@ -94,6 +177,11 @@ + (void) initializeRolesMap { [rolesMap setObject:IgnoreClassName forKey:@"viewport"]; [rolesMap setObject:IgnoreClassName forKey:@"window"]; + rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:2]; + + [rowRolesMapForParent setObject:@"ListRowAccessibility" forKey:@"ListAccessibility"]; + [rowRolesMapForParent setObject:@"OutlineRowAccessibility" forKey:@"OutlineAccessibility"]; + /* * Initialize CAccessibility instance */ @@ -132,7 +220,7 @@ + (void) initializeRolesMap { * If new implementation of the accessible component peer for the given role exists * return the allocated class otherwise return nil to let old implementation being initialized */ -+ (JavaComponentAccessibility *) getComponentAccessibility:(NSString *)role ++ (CommonComponentAccessibility *) getComponentAccessibility:(NSString *)role { AWT_ASSERT_APPKIT_THREAD; if (rolesMap == nil) { @@ -143,10 +231,542 @@ + (JavaComponentAccessibility *) getComponentAccessibility:(NSString *)role if (className != nil) { return [NSClassFromString(className) alloc]; } - return nil; + return [CommonComponentAccessibility alloc]; +} + ++ (CommonComponentAccessibility *) getComponentAccessibility:(NSString *)role andParent:(CommonComponentAccessibility *)parent +{ + AWT_ASSERT_APPKIT_THREAD; + if (rolesMap == nil) { + [self initializeRolesMap]; + } + NSString *className = [rowRolesMapForParent objectForKey:[[parent class] className]]; + if (className == nil) { + return [CommonComponentAccessibility getComponentAccessibility:role]; + } + return [NSClassFromString(className) alloc]; +} + +- (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withView:(NSView *)view withJavaRole:(NSString *)javaRole +{ + self = [super init]; + if (self) + { + fParent = [parent retain]; + fView = [view retain]; + fJavaRole = [javaRole retain]; + + if (accessible != NULL) { + fAccessible = (*env)->NewWeakGlobalRef(env, accessible); + CHECK_EXCEPTION(); + } + + jobject jcomponent = [(AWTView *)fView awtComponent:env]; + fComponent = (*env)->NewWeakGlobalRef(env, jcomponent); + CHECK_EXCEPTION(); + + (*env)->DeleteLocalRef(env, jcomponent); + + fIndex = index; + + fActions = nil; + fActionSelectors = nil; + fActionsLOCK = [[NSObject alloc] init]; + } + return self; +} + +- (void)unregisterFromCocoaAXSystem +{ + AWT_ASSERT_APPKIT_THREAD; + static dispatch_once_t initialize_unregisterUniqueId_once; + static void (*unregisterUniqueId)(id); + dispatch_once(&initialize_unregisterUniqueId_once, ^{ + void *jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL); + unregisterUniqueId = dlsym(jrsFwk, "JRSAccessibilityUnregisterUniqueIdForUIElement"); + }); + if (unregisterUniqueId) unregisterUniqueId(self); +} + +- (void)dealloc +{ + [self unregisterFromCocoaAXSystem]; + + JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; + + (*env)->DeleteWeakGlobalRef(env, fAccessible); + fAccessible = NULL; + + (*env)->DeleteWeakGlobalRef(env, fComponent); + fComponent = NULL; + + [fParent release]; + fParent = nil; + + [fNSRole release]; + fNSRole = nil; + + [fJavaRole release]; + fJavaRole = nil; + + [fView release]; + fView = nil; + + [fActions release]; + fActions = nil; + + [fActionsLOCK release]; + fActionsLOCK = nil; + + [fActionSelectors release]; + fActionSelectors = nil; + + [super dealloc]; +} + +- (void)postValueChanged +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification(self, NSAccessibilityValueChangedNotification); +} + +- (void)postSelectedTextChanged +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification(self, NSAccessibilitySelectedTextChangedNotification); +} + +- (void)postSelectionChanged +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification(self, NSAccessibilitySelectedChildrenChangedNotification); +} + +-(void)postTitleChanged +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification(self, NSAccessibilityTitleChangedNotification); +} + +- (void)postMenuOpened +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification(self, (NSString *)kAXMenuOpenedNotification); +} + +- (void)postMenuClosed +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification(self, (NSString *)kAXMenuClosedNotification); +} + +- (void)postMenuItemSelected +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification(self, (NSString *)kAXMenuItemSelectedNotification); +} + +- (void)postTreeNodeExpanded +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification([[self accessibilitySelectedRows] firstObject], NSAccessibilityRowExpandedNotification); +} + +- (void)postTreeNodeCollapsed +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification([[self accessibilitySelectedRows] firstObject], NSAccessibilityRowCollapsedNotification); +} + +- (BOOL)isEqual:(id)anObject +{ + if (![anObject isKindOfClass:[self class]]) return NO; + CommonComponentAccessibility *accessibility = (CommonComponentAccessibility *)anObject; + + JNIEnv* env = [ThreadUtilities getJNIEnv]; + return (*env)->IsSameObject(env, accessibility->fAccessible, fAccessible); +} + +- (BOOL)isAccessibleWithEnv:(JNIEnv *)env forAccessible:(jobject)accessible +{ + return (*env)->IsSameObject(env, fAccessible, accessible); +} + ++ (void)initialize +{ + if (sRoles == nil) { + initializeRoles(); + } + if (sActions == nil) { + initializeActions(); + } +} + ++ (void)postFocusChanged:(id)message +{ + AWT_ASSERT_APPKIT_THREAD; + NSAccessibilityPostNotification([NSApp accessibilityFocusedUIElement], NSAccessibilityFocusedUIElementChangedNotification); +} + ++ (jobject) getCAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env { + DECLARE_CLASS_RETURN(sjc_Accessible, "javax/accessibility/Accessible", NULL); + GET_CACCESSIBLE_CLASS_RETURN(NULL); + DECLARE_STATIC_METHOD_RETURN(sjm_getCAccessible, sjc_CAccessible, "getCAccessible", + "(Ljavax/accessibility/Accessible;)Lsun/lwawt/macosx/CAccessible;", NULL); + if ((*env)->IsInstanceOf(env, jaccessible, sjc_CAccessible)) { + return jaccessible; + } else if ((*env)->IsInstanceOf(env, jaccessible, sjc_Accessible)) { + jobject o = (*env)->CallStaticObjectMethod(env, sjc_CAccessible, sjm_getCAccessible, jaccessible); + CHECK_EXCEPTION(); + return o; + } + return NULL; +} + ++ (NSArray *)childrenOfParent:(CommonComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored +{ + return [CommonComponentAccessibility childrenOfParent:parent withEnv:env withChildrenCode:whichChildren allowIgnored:allowIgnored recursive:NO]; +} + ++ (NSArray *)childrenOfParent:(CommonComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored recursive:(BOOL)recursive +{ + if (parent->fAccessible == NULL) return nil; + jobjectArray jchildrenAndRoles = NULL; + if (recursive) { + GET_CHILDRENANDROLESRECURSIVE_METHOD_RETURN(nil); + jchildrenAndRoles = (jobjectArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getChildrenAndRolesRecursive, + parent->fAccessible, parent->fComponent, whichChildren, allowIgnored, 0); + CHECK_EXCEPTION(); + } else { + GET_CHILDRENANDROLES_METHOD_RETURN(nil); + jchildrenAndRoles = (jobjectArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getChildrenAndRoles, + parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); + CHECK_EXCEPTION(); + } + if (jchildrenAndRoles == NULL) return nil; + + jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles); + NSMutableArray *children = [NSMutableArray arrayWithCapacity:(recursive ? arrayLen/3 : arrayLen/2)]; //childrenAndRoles array contains two elements (child, role) for each child + + NSInteger i; + NSUInteger childIndex = (whichChildren >= 0) ? whichChildren : 0; // if we're getting one particular child, make sure to set its index correctly + int inc = recursive ? 3 : 2; + for(i = 0; i < arrayLen; i+=inc) + { + jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i); + jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1); + + NSString *childJavaRole = nil; + if (jchildJavaRole != NULL) { + DECLARE_CLASS_RETURN(sjc_AccessibleRole, "javax/accessibility/AccessibleRole", nil); + DECLARE_FIELD_RETURN(sjf_key, sjc_AccessibleRole, "key", "Ljava/lang/String;", nil); + jobject jkey = (*env)->GetObjectField(env, jchildJavaRole, sjf_key); + CHECK_EXCEPTION(); + childJavaRole = JavaStringToNSString(env, jkey); + (*env)->DeleteLocalRef(env, jkey); + } + + CommonComponentAccessibility *child = [self createWithParent:parent accessible:jchild role:childJavaRole index:childIndex withEnv:env withView:parent->fView]; + + if (recursive && [child respondsToSelector:@selector(accessibleLevel)]) { + jobject jLevel = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+2); + NSString *sLevel = nil; + if (jLevel != NULL) { + sLevel = JavaStringToNSString(env, jLevel); + if (sLevel != nil) { + int level = sLevel.intValue; + [child setAccessibleLevel:level]; + } + (*env)->DeleteLocalRef(env, jLevel); + } + } + + (*env)->DeleteLocalRef(env, jchild); + (*env)->DeleteLocalRef(env, jchildJavaRole); + + [children addObject:child]; + childIndex++; + } + (*env)->DeleteLocalRef(env, jchildrenAndRoles); + + return children; +} + ++ (CommonComponentAccessibility *) createWithAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env withView:(NSView *)view +{ + return [CommonComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:view isCurrent:NO]; +} + ++ (CommonComponentAccessibility *) createWithAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env withView:(NSView *)view isCurrent:(BOOL)current +{ + GET_ACCESSIBLEINDEXINPARENT_STATIC_METHOD_RETURN(nil); + CommonComponentAccessibility *ret = nil; + jobject jcomponent = [(AWTView *)view awtComponent:env]; + jint index = (*env)->CallStaticIntMethod(env, sjc_CAccessibility, sjm_getAccessibleIndexInParent, jaccessible, jcomponent); + CHECK_EXCEPTION(); + if (index >= 0 || current) { + NSString *javaRole = getJavaRole(env, jaccessible, jcomponent); + ret = [self createWithAccessible:jaccessible role:javaRole index:index withEnv:env withView:view]; + } + (*env)->DeleteLocalRef(env, jcomponent); + return ret; +} + ++ (CommonComponentAccessibility *) createWithAccessible:(jobject)jaccessible role:(NSString *)javaRole index:(jint)index withEnv:(JNIEnv *)env withView:(NSView *)view +{ + return [self createWithParent:nil accessible:jaccessible role:javaRole index:index withEnv:env withView:view]; +} + ++ (CommonComponentAccessibility *) createWithParent:(CommonComponentAccessibility *)parent accessible:(jobject)jaccessible role:(NSString *)javaRole index:(jint)index withEnv:(JNIEnv *)env withView:(NSView *)view +{ + return [CommonComponentAccessibility createWithParent:parent accessible:jaccessible role:javaRole index:index withEnv:env withView:view isWrapped:NO]; +} + ++ (CommonComponentAccessibility *) createWithParent:(CommonComponentAccessibility *)parent accessible:(jobject)jaccessible role:(NSString *)javaRole index:(jint)index withEnv:(JNIEnv *)env withView:(NSView *)view isWrapped:(BOOL)wrapped +{ + GET_CACCESSIBLE_CLASS_RETURN(NULL); + DECLARE_FIELD_RETURN(jf_ptr, sjc_CAccessible, "ptr", "J", NULL); + // try to fetch the jCAX from Java, and return autoreleased + jobject jCAX = [CommonComponentAccessibility getCAccessible:jaccessible withEnv:env]; + if (jCAX == NULL) return nil; + if (!wrapped) { // If wrapped is true, then you don't need to get an existing instance, you need to create a new one + CommonComponentAccessibility *value = (CommonComponentAccessibility *) jlong_to_ptr((*env)->GetLongField(env, jCAX, jf_ptr)); + if (value != nil) { + (*env)->DeleteLocalRef(env, jCAX); + return [[value retain] autorelease]; + } + } + + // otherwise, create a new instance + CommonComponentAccessibility *newChild = [CommonComponentAccessibility getComponentAccessibility:javaRole andParent:parent]; + + // must init freshly -alloc'd object + [newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance + + // If creating a JPopupMenu (not a combobox popup list) need to fire menuOpened. + // This is the only way to know if the menu is opening; visible state change + // can't be caught because the listeners are not set up in time. + if ( [javaRole isEqualToString:@"popupmenu"] && + ![[parent javaRole] isEqualToString:@"combobox"] ) { + [newChild postMenuOpened]; + } + + // must hard retain pointer poked into Java object + [newChild retain]; + (*env)->SetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild)); + + // the link is removed in the wrapper + if (!wrapped) { + (*env)->DeleteLocalRef(env, jCAX); + } + + // return autoreleased instance + return [newChild autorelease]; +} + +- (NSDictionary *)getActions:(JNIEnv *)env +{ + @synchronized(fActionsLOCK) { + if (fActions == nil) { + [self getActionsWithEnv:env]; + } + } + + return fActions; +} + +- (void)getActionsWithEnv:(JNIEnv *)env +{ + GET_CACCESSIBILITY_CLASS(); + DECLARE_STATIC_METHOD(jm_getAccessibleAction, sjc_CAccessibility, "getAccessibleAction", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleAction;"); + + jobject axAction = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleAction, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axAction != NULL) { + jclass jc_AccessibleAction = NULL; + GET_CLASS(jc_AccessibleAction, "javax/accessibility/AccessibleAction"); + jmethodID jm_getAccessibleActionCount = NULL; + GET_METHOD(jm_getAccessibleActionCount, jc_AccessibleAction, "getAccessibleActionCount", "()I"); + jint count = (*env)->CallIntMethod(env, axAction, jm_getAccessibleActionCount); + fActions = [[NSMutableDictionary alloc] initWithCapacity:count]; + fActionSelectors = [[NSMutableArray alloc] initWithCapacity:count]; + for (int i =0; i < count; i++) { + JavaAxAction *action = [[JavaAxAction alloc] initWithEnv:env withAccessibleAction:axAction withIndex:i withComponent:fComponent]; + if ([fParent isKindOfClass:[CommonComponentAccessibility class]] && + [(CommonComponentAccessibility *)fParent isMenu] && + [[sActions objectForKey:[action getDescription]] isEqualToString:NSAccessibilityPressAction]) { + [fActions setObject:action forKey:NSAccessibilityPickAction]; + [fActionSelectors addObject:[sActionSelectors objectForKey:NSAccessibilityPickAction]]; + } else { + [fActions setObject:action forKey:[sActions objectForKey:[action getDescription]]]; + [fActionSelectors addObject:[sActionSelectors objectForKey:[sActions objectForKey:[action getDescription]]]]; + } + [action release]; + } + (*env)->DeleteLocalRef(env, axAction); + } +} + +- (BOOL)accessiblePerformAction:(NSAccessibilityActionName)actionName { + NSMutableDictionary *currentAction = [self getActions:[ThreadUtilities getJNIEnv]]; + if (currentAction == nil) { + return NO; + } + if ([[currentAction allKeys] containsObject:actionName]) { + [(JavaAxAction *)[currentAction objectForKey:actionName] perform]; + return YES;; + } + return NO; +} + +- (NSArray *)actionSelectors { + @synchronized(fActionsLOCK) { + if (fActionSelectors == nil) { + [self getActionsWithEnv:[ThreadUtilities getJNIEnv]]; + } + } + + return [NSArray arrayWithArray:fActionSelectors]; +} + +- (NSArray *)accessibleChildrenWithChildCode:(NSInteger)childCode +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + NSArray *children = [CommonComponentAccessibility childrenOfParent:self + withEnv:env + withChildrenCode:childCode + allowIgnored:([[self accessibilityRole] isEqualToString:NSAccessibilityListRole] || [[self accessibilityRole] isEqualToString:NSAccessibilityOutlineRole] || [[self accessibilityRole] isEqualToString:NSAccessibilityTableRole]) + recursive:[[self accessibilityRole] isEqualToString:NSAccessibilityOutlineRole]]; + + NSArray *value = nil; + if ([children count] > 0) { + value = children; + } + + return value; +} + +- (NSView *)view +{ + return fView; +} + +- (NSWindow *)window +{ + return [[self view] window]; +} + +- (id)parent +{ + if(fParent == nil) { + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleParent, sjc_CAccessibility, "getAccessibleParent", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/Accessible;", nil); + GET_CACCESSIBLE_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(sjm_getSwingAccessible, sjc_CAccessible, "getSwingAccessible", + "(Ljavax/accessibility/Accessible;)Ljavax/accessibility/Accessible;", nil); + DECLARE_CLASS_RETURN(sjc_Window, "java/awt/Window", nil); + + jobject jparent = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleParent, fAccessible, fComponent); + CHECK_EXCEPTION(); + + if (jparent == NULL) { + fParent = fView; + } else { + AWTView *view = fView; + jobject jax = (*env)->CallStaticObjectMethod(env, sjc_CAccessible, sjm_getSwingAccessible, fAccessible); + CHECK_EXCEPTION(); + + if ((*env)->IsInstanceOf(env, jax, sjc_Window)) { + // In this case jparent is an owner toplevel and we should retrieve its own view + view = [AWTView awtView:env ofAccessible:jparent]; + } + if (view != nil) { + fParent = [CommonComponentAccessibility createWithAccessible:jparent withEnv:env withView:view]; + } + if (fParent == nil) { + fParent = fView; + } + (*env)->DeleteLocalRef(env, jparent); + (*env)->DeleteLocalRef(env, jax ); + } + [fParent retain]; + } + return fParent; +} + +- (NSString *)javaRole +{ + if(fJavaRole == nil) { + JNIEnv* env = [ThreadUtilities getJNIEnv]; + fJavaRole = getJavaRole(env, fAccessible, fComponent); + [fJavaRole retain]; + } + return fJavaRole; +} + +- (jobject)axContextWithEnv:(JNIEnv *)env +{ + return getAxContext(env, fAccessible, fComponent); } // NSAccessibilityElement protocol implementation + +- (BOOL)isAccessibilityElement +{ + return ![[self accessibilityRole] isEqualToString:JavaAccessibilityIgnore]; +} + +- (NSString *)accessibilityLabel +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + + GET_ACCESSIBLENAME_METHOD_RETURN(nil); + jobject val = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleName, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (val == NULL) { + return nil; + } + NSString* str = JavaStringToNSString(env, val); + (*env)->DeleteLocalRef(env, val); + return str; +} + +- (NSString *)accessibilityHelp +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleDescription, sjc_CAccessibility, "getAccessibleDescription", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil); + jobject val = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, + sjm_getAccessibleDescription, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (val == NULL) { + return nil; + } + NSString* str = JavaStringToNSString(env, val); + (*env)->DeleteLocalRef(env, val); + return str; +} + +- (NSArray *)accessibilityChildren +{ + return [self accessibleChildrenWithChildCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN]; +} + +- (NSArray *)accessibilitySelectedChildren +{ + return [self accessibleChildrenWithChildCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_SELECTED_CHILDREN]; +} + +- (NSArray *)accessibilityVisibleChildren +{ + return [self accessibleChildrenWithChildCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_VISIBLE_CHILDREN]; +} + - (NSRect)accessibilityFrame { JNIEnv* env = [ThreadUtilities getJNIEnv]; @@ -168,10 +788,370 @@ - (NSRect)accessibilityFrame - (id _Nullable)accessibilityParent { - return [self accessibilityParentAttribute]; + return NSAccessibilityUnignoredAncestor([self parent]); +} + +- (BOOL)isAccessibilityEnabled +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(NO); + DECLARE_STATIC_METHOD_RETURN(jm_isEnabled, sjc_CAccessibility, "isEnabled", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Z", NO); + + BOOL value = (*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, jm_isEnabled, fAccessible, fComponent); + CHECK_EXCEPTION(); + + return value; +} + +- (id)accessibilityApplicationFocusedUIElement +{ + return [self accessibilityFocusedUIElement]; +} + +- (NSAccessibilityRole)accessibilityRole +{ + if (fNSRole == nil) { + NSString *javaRole = [self javaRole]; + fNSRole = [sRoles objectForKey:javaRole]; + // The sRoles NSMutableDictionary maps popupmenu to Mac's popup button. + // JComboBox behavior currently relies on this. However this is not the + // proper mapping for a JPopupMenu so fix that. + if ( [javaRole isEqualToString:@"popupmenu"] && + ![[[self parent] javaRole] isEqualToString:@"combobox"] ) { + fNSRole = NSAccessibilityMenuRole; + } + if (fNSRole == nil) { + // this component has assigned itself a custom AccessibleRole not in the sRoles array + fNSRole = javaRole; + } + [fNSRole retain]; + } + return fNSRole; +} + +- (NSString *)accessibilityRoleDescription +{ + // first ask AppKit for its accessible role description for a given AXRole + NSString *value = NSAccessibilityRoleDescription([self accessibilityRole], nil); + + if (value == nil) { + // query java if necessary + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(jm_getAccessibleRoleDisplayString, sjc_CAccessibility, "getAccessibleRoleDisplayString", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil); + + jobject axRole = (*env)->CallStaticObjectMethod(env, jm_getAccessibleRoleDisplayString, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axRole != NULL) { + value = JavaStringToNSString(env, axRole); + (*env)->DeleteLocalRef(env, axRole); + } else { + value = @"unknown"; + } + } + + return value; +} + +- (BOOL)isAccessibilityFocused +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(NO); + DECLARE_STATIC_METHOD_RETURN(sjm_isFocusTraversable, sjc_CAccessibility, "isFocusTraversable", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Z", NO); + // According to javadoc, a component that is focusable will return true from isFocusTraversable, + // as well as having AccessibleState.FOCUSABLE in its AccessibleStateSet. + // We use the former heuristic; if the component focus-traversable, add a focused attribute + // See also initializeAttributeNamesWithEnv: + if ((*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, sjm_isFocusTraversable, fAccessible, fComponent)) { + return [self isEqual:[NSApp accessibilityFocusedUIElement]]; + } + CHECK_EXCEPTION(); + + return NO; +} + +- (void)setAccessibilityFocused:(BOOL)accessibilityFocused +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + + GET_CACCESSIBILITY_CLASS(); + DECLARE_STATIC_METHOD(jm_requestFocus, sjc_CAccessibility, "requestFocus", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)V"); + + if (accessibilityFocused) + { + (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestFocus, fAccessible, fComponent); + CHECK_EXCEPTION(); + } +} + +- (NSUInteger)accessibilityIndexOfChild:(id)child +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_ACCESSIBLEINDEXINPARENT_STATIC_METHOD_RETURN(0); + jint returnValue = + (*env)->CallStaticIntMethod( env, + sjc_CAccessibility, + sjm_getAccessibleIndexInParent, + ((CommonComponentAccessibility *)child)->fAccessible, + ((CommonComponentAccessibility *)child)->fComponent ); + CHECK_EXCEPTION(); + return (returnValue == -1) ? NSNotFound : returnValue; +} + +- (NSInteger)accessibilityIndex +{ + int index = 0; + if (fParent != NULL) { + index = [fParent accessibilityIndexOfChild:self]; + } + return index; +} + +- (id)accessibilityMaxValue +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(jm_getMaximumAccessibleValue, sjc_CAccessibility, "getMaximumAccessibleValue", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/Number;", nil); + + jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getMaximumAccessibleValue, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axValue == NULL) { + return [NSNumber numberWithInt:0]; + } + NSNumber* num = JavaNumberToNSNumber(env, axValue); + (*env)->DeleteLocalRef(env, axValue); + return num; +} + +- (id)accessibilityMinValue +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(jm_getMinimumAccessibleValue, sjc_CAccessibility, "getMinimumAccessibleValue", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/Number;", nil); + + jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getMinimumAccessibleValue, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axValue == NULL) { + return [NSNumber numberWithInt:0]; + } + NSNumber* num = JavaNumberToNSNumber(env, axValue); + (*env)->DeleteLocalRef(env, axValue); + return num; +} + +- (NSAccessibilityOrientation)accessibilityOrientation +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + + // cmcnote - should batch these two calls into one that returns an array of two bools, one for vertical and one for horiz + if (isVertical(env, axContext, fComponent)) { + (*env)->DeleteLocalRef(env, axContext); + return NSAccessibilityOrientationVertical; + } + if (isHorizontal(env, axContext, fComponent)) { + (*env)->DeleteLocalRef(env, axContext); + return NSAccessibilityOrientationHorizontal; + } + return NSAccessibilityOrientationUnknown; +} + +- (NSPoint)accessibilityActivationPoint +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_ACCESSIBLECOMPONENT_STATIC_METHOD_RETURN(NSPointFromString(@"")); + jobject axComponent = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleComponent, + fAccessible, fComponent); + CHECK_EXCEPTION(); + + // NSAccessibility wants the bottom left point of the object in + // bottom left based screen coords + + // Get the java screen coords, and make a NSPoint of the bottom left of the AxComponent. + NSSize size = getAxComponentSize(env, axComponent, fComponent); + NSPoint point = getAxComponentLocationOnScreen(env, axComponent, fComponent); + (*env)->DeleteLocalRef(env, axComponent); + + point.y += size.height; + + // Now make it into Cocoa screen coords. + point.y = [[[[self view] window] screen] frame].size.height - point.y; + + return point; +} + +- (BOOL)isAccessibilitySelected +{ + return [self isSelected:[ThreadUtilities getJNIEnv]]; +} + +- (void)setAccessibilitySelected:(BOOL)accessibilitySelected +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS(); + DECLARE_STATIC_METHOD(jm_requestSelection, + sjc_CAccessibility, + "requestSelection", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)V"); + + if (accessibilitySelected) { + (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestSelection, fAccessible, fComponent); + CHECK_EXCEPTION(); + } +} + +- (id)accessibilityValue +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + + // Need to handle popupmenus differently. + // + // At least for now don't handle combo box menus. + // This may change when later fixing issues which currently + // exist for combo boxes, but for now the following is only + // for JPopupMenus, not for combobox menus. + id parent = [self parent]; + if ( [[self javaRole] isEqualToString:@"popupmenu"] && + ![[parent javaRole] isEqualToString:@"combobox"] ) { + NSArray *children = + [CommonComponentAccessibility childrenOfParent:self + withEnv:env + withChildrenCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN + allowIgnored:YES]; + if ([children count] > 0) { + // handle case of AXMenuItem + // need to ask menu what is selected + NSArray *selectedChildrenOfMenu = + [self accessibilitySelectedChildren]; + CommonComponentAccessibility *selectedMenuItem = + [selectedChildrenOfMenu objectAtIndex:0]; + if (selectedMenuItem != nil) { + GET_CACCESSIBILITY_CLASS_RETURN(nil); + GET_ACCESSIBLENAME_METHOD_RETURN(nil); + jobject itemValue = + (*env)->CallStaticObjectMethod( env, + sjm_getAccessibleName, + selectedMenuItem->fAccessible, + selectedMenuItem->fComponent ); + CHECK_EXCEPTION(); + if (itemValue == NULL) { + return nil; + } + NSString* itemString = JavaStringToNSString(env, itemValue); + (*env)->DeleteLocalRef(env, itemValue); + return itemString; + } else { + return nil; + } + } + } + + // ask Java for the component's accessibleValue. In java, the "accessibleValue" just means a numerical value + // a text value is taken care of in JavaTextAccessibility + + // cmcnote should coalesce these calls into one java call + NSNumber *num = nil; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleValue, sjc_CAccessibility, "getAccessibleValue", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleValue;", nil); + jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleValue, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axValue != NULL) { + DECLARE_STATIC_METHOD_RETURN(jm_getCurrentAccessibleValue, sjc_CAccessibility, "getCurrentAccessibleValue", + "(Ljavax/accessibility/AccessibleValue;Ljava/awt/Component;)Ljava/lang/Number;", nil); + jobject str = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getCurrentAccessibleValue, axValue, fComponent); + CHECK_EXCEPTION(); + if (str != NULL) { + num = JavaNumberToNSNumber(env, str); + (*env)->DeleteLocalRef(env, str); + } + (*env)->DeleteLocalRef(env, axValue); + } + if (num == nil) { + num = [NSNumber numberWithInt:0]; + } + return num; +} + +- (id)accessibilityHitTest:(NSPoint)point +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + + DECLARE_CLASS_RETURN(jc_Container, "java/awt/Container", nil); + DECLARE_STATIC_METHOD_RETURN(jm_accessibilityHitTest, sjc_CAccessibility, "accessibilityHitTest", + "(Ljava/awt/Container;FF)Ljavax/accessibility/Accessible;", nil); + + // Make it into java screen coords + point.y = [[[[self view] window] screen] frame].size.height - point.y; + + jobject jparent = fComponent; + + id value = nil; + if ((*env)->IsInstanceOf(env, jparent, jc_Container)) { + jobject jaccessible = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_accessibilityHitTest, + jparent, (jfloat)point.x, (jfloat)point.y); + CHECK_EXCEPTION(); + if (jaccessible != NULL) { + value = [CommonComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:fView]; + (*env)->DeleteLocalRef(env, jaccessible); + } + } + + if (value == nil) { + value = self; + } + + if (![value isAccessibilityElement]) { + value = NSAccessibilityUnignoredAncestor(value); + } + +#ifdef JAVA_AX_DEBUG + NSLog(@"%s: %@", __FUNCTION__, value); +#endif + return value; +} + +- (id)accessibilityFocusedUIElement +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(jm_getFocusOwner, sjc_CAccessibility, "getFocusOwner", + "(Ljava/awt/Component;)Ljavax/accessibility/Accessible;", nil); + id value = nil; + + NSWindow* hostWindow = [[self->fView window] retain]; + jobject focused = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getFocusOwner, fComponent); + [hostWindow release]; + CHECK_EXCEPTION(); + + if (focused != NULL) { + DECLARE_CLASS_RETURN(sjc_Accessible, "javax/accessibility/Accessible", nil); + if ((*env)->IsInstanceOf(env, focused, sjc_Accessible)) { + value = [CommonComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; + } + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, focused); + } + + if (value == nil) { + value = self; + } +#ifdef JAVA_AX_DEBUG + NSLog(@"%s: %@", __FUNCTION__, value); +#endif + return value; +} + +- (id)accessibilityWindow { + return [self window]; } // AccessibleAction support + - (BOOL)performAccessibleAction:(int)index { AWT_ASSERT_APPKIT_THREAD; @@ -187,8 +1167,66 @@ - (BOOL)performAccessibleAction:(int)index return TRUE; } -- (BOOL)isAccessibilityElement { - return YES; +// NSAccessibilityActions methods + +- (BOOL)isAccessibilitySelectorAllowed:(SEL)selector { + if ([sAllActionSelectors containsObject:NSStringFromSelector(selector)] && + ![[self actionSelectors] containsObject:NSStringFromSelector(selector)]) { + return NO; + } + return [super isAccessibilitySelectorAllowed:selector]; +} + +- (BOOL)accessibilityPerformPick { + return [self accessiblePerformAction:NSAccessibilityPickAction]; +} + +- (BOOL)accessibilityPerformPress { + return [self accessiblePerformAction:NSAccessibilityPressAction]; +} + +- (BOOL)accessibilityPerformShowMenu { + return [self accessiblePerformAction:NSAccessibilityShowMenuAction]; +} + +- (BOOL)accessibilityPerformDecrement { + return [self accessiblePerformAction:NSAccessibilityDecrementAction]; +} + +- (BOOL)accessibilityPerformIncrement { + return [self accessiblePerformAction:NSAccessibilityIncrementAction]; } @end + +/* + * Class: sun_lwawt_macosx_CAccessible + * Method: treeNodeExpanded + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_treeNodeExpanded + (JNIEnv *env, jclass jklass, jlong element) +{ + JNI_COCOA_ENTER(env); + [ThreadUtilities performOnMainThread:@selector(postTreeNodeExpanded) + on:(CommonComponentAccessibility *)jlong_to_ptr(element) + withObject:nil + waitUntilDone:NO]; + JNI_COCOA_EXIT(env); +} + +/* + * Class: sun_lwawt_macosx_CAccessible + * Method: treeNodeCollapsed + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_treeNodeCollapsed + (JNIEnv *env, jclass jklass, jlong element) +{ + JNI_COCOA_ENTER(env); + [ThreadUtilities performOnMainThread:@selector(postTreeNodeCollapsed) + on:(CommonComponentAccessibility *)jlong_to_ptr(element) + withObject:nil + waitUntilDone:NO]; + JNI_COCOA_EXIT(env); +} diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m index 007cbe9de8c..18e3f47e1eb 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m @@ -70,7 +70,7 @@ - (nullable NSString *)accessibilityValueAttribute GET_CACCESSIBILITY_CLASS_RETURN(nil); DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil); - if ([[self accessibilityRoleAttribute] isEqualToString:NSAccessibilityStaticTextRole]) { + if ([[self accessibilityRole] isEqualToString:NSAccessibilityStaticTextRole]) { jobject axName = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleName, fAccessible, fComponent); CHECK_EXCEPTION(); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/GroupAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/GroupAccessibility.m index 1a33b6a003a..f3e0ee1f092 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/GroupAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/GroupAccessibility.m @@ -26,6 +26,7 @@ #import "GroupAccessibility.h" #import "JNIUtilities.h" #import "ThreadUtilities.h" +#import "sun_lwawt_macosx_CAccessibility.h" /* * This is the protocol for the components that contain children. * Basic logic of accessibilityChildren might be overridden in the specific implementing @@ -43,9 +44,9 @@ - (NSAccessibilityRole _Nonnull)accessibilityRole - (NSArray *)accessibilityChildren { JNIEnv *env = [ThreadUtilities getJNIEnv]; - NSArray *children = [JavaComponentAccessibility childrenOfParent:self + NSArray *children = [CommonComponentAccessibility childrenOfParent:self withEnv:env - withChildrenCode:JAVA_AX_ALL_CHILDREN + withChildrenCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN allowIgnored:NO]; if ([children count] == 0) { @@ -55,4 +56,14 @@ - (NSArray *)accessibilityChildren { } } +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ImageAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ImageAccessibility.m index 4882d709a01..63701a180c9 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ImageAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ImageAccessibility.m @@ -36,7 +36,17 @@ - (NSAccessibilityRole _Nonnull)accessibilityRole - (NSString * _Nullable)accessibilityLabel { - return [self accessibilityTitleAttribute]; + return [super accessibilityLabel]; +} + +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; } @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h new file mode 100644 index 00000000000..ddfcd2217f8 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface ListAccessibility : CommonComponentAccessibility +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m new file mode 100644 index 00000000000..4dc958886bb --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "ListAccessibility.h" +#import "JavaAccessibilityUtilities.h" +#import "ThreadUtilities.h" + +@implementation ListAccessibility + +// NSAccessibilityElement protocol methods + +- (nullable NSArray> *)accessibilityRows +{ + return [self accessibilityChildren]; +} + +- (nullable NSArray> *)accessibilitySelectedRows +{ + return [self accessibilitySelectedChildren]; +} + +- (NSString *)accessibilityLabel +{ + return [super accessibilityLabel] == NULL ? @"list" : [super accessibilityLabel]; +} + +// to avoid warning (why?): method in protocol 'NSAccessibilityElement' not implemented + +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +// to avoid warning (why?): method in protocol 'NSAccessibilityElement' not implemented + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + +@end + diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h new file mode 100644 index 00000000000..2453f92e58f --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface ListRowAccessibility : CommonComponentAccessibility +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m new file mode 100644 index 00000000000..2c4d51e10ff --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "jni.h" +#import "ListRowAccessibility.h" +#import "JavaAccessibilityAction.h" +#import "JavaAccessibilityUtilities.h" +#import "ListAccessibility.h" +#import "ThreadUtilities.h" + +@implementation ListRowAccessibility + +// NSAccessibilityElement protocol methods + +- (NSAccessibilityRole)accessibilityRole +{ + return NSAccessibilityRowRole; +} + +- (NSArray *)accessibilityChildren +{ + NSArray *children = [super accessibilityChildren]; + if (children == NULL) { + + // Since the row element has already been created, we should no create it again, but just retrieve it by a pointer, that's why isWrapped is set to YES. + CommonComponentAccessibility *newChild = [CommonComponentAccessibility createWithParent:self + accessible:self->fAccessible + role:self->fJavaRole + index:self->fIndex + withEnv:[ThreadUtilities getJNIEnv] + withView:self->fView + isWrapped:YES]; + return [NSArray arrayWithObject:newChild]; + } else { + return children; + } +} + +- (NSInteger)accessibilityIndex +{ + return [[self accessibilityParent] accessibilityIndexOfChild:self]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h new file mode 100644 index 00000000000..33a05318b5a --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface NavigableTextAccessibility : CommonComponentAccessibility + +@property(readonly) BOOL accessibleIsPasswordText; + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m new file mode 100644 index 00000000000..84d8785e205 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "NavigableTextAccessibility.h" +#import "JavaAccessibilityUtilities.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" + +static jclass sjc_CAccessibility = NULL; +#define GET_CACCESSIBLITY_CLASS() \ + GET_CLASS(sjc_CAccessibility, "sun/lwawt/macosx/CAccessibility"); +#define GET_CACCESSIBLITY_CLASS_RETURN(ret) \ + GET_CLASS_RETURN(sjc_CAccessibility, "sun/lwawt/macosx/CAccessibility", ret); + +static jmethodID sjm_getAccessibleText = NULL; +#define GET_ACCESSIBLETEXT_METHOD_RETURN(ret) \ + GET_CACCESSIBLITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(sjm_getAccessibleText, sjc_CAccessibility, "getAccessibleText", \ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleText;", ret); + +static jclass sjc_CAccessibleText = NULL; +#define GET_CACCESSIBLETEXT_CLASS() \ + GET_CLASS(sjc_CAccessibleText, "sun/lwawt/macosx/CAccessibleText"); +#define GET_CACCESSIBLETEXT_CLASS_RETURN(ret) \ + GET_CLASS_RETURN(sjc_CAccessibleText, "sun/lwawt/macosx/CAccessibleText", ret); + +static jmethodID sjm_getAccessibleEditableText = NULL; +#define GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(ret) \ + GET_CACCESSIBLETEXT_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(sjm_getAccessibleEditableText, sjc_CAccessibleText, "getAccessibleEditableText", \ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleEditableText;", ret); + + +@implementation NavigableTextAccessibility + +- (BOOL)accessibleIsPasswordText { + return [fJavaRole isEqualToString:@"passwordtext"]; +} + +// NSAccessibilityElement protocol methods + +- (NSRect)accessibilityFrameForRange:(NSRange)range +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(NSMakeRect(0, 0, 0, 0)); + DECLARE_STATIC_METHOD_RETURN(jm_getBoundsForRange, sjc_CAccessibleText, "getBoundsForRange", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)[D", NSMakeRect(0, 0, 0, 0)); + jdoubleArray axBounds = (jdoubleArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getBoundsForRange, + fAccessible, fComponent, range.location, range.length); + CHECK_EXCEPTION(); + if (axBounds == NULL) return NSMakeRect(0, 0, 0, 0); + + // We cheat because we know that the array is 4 elements long (x, y, width, height) + jdouble *values = (*env)->GetDoubleArrayElements(env, axBounds, 0); + CHECK_EXCEPTION(); + + NSRect bounds; + bounds.origin.x = values[0]; + bounds.origin.y = [[[[self view] window] screen] frame].size.height - values[1] - values[3]; //values[1] is y-coord from top-left of screen. Flip. Account for the height (values[3]) when flipping + bounds.size.width = values[2]; + bounds.size.height = values[3]; + (*env)->ReleaseDoubleArrayElements(env, axBounds, values, 0); + return bounds; +} + +- (NSInteger)accessibilityLineForIndex:(NSInteger)index +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(-1); + DECLARE_STATIC_METHOD_RETURN(jm_getLineNumberForIndex, sjc_CAccessibleText, "getLineNumberForIndex", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)I", -1); + jint row = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, jm_getLineNumberForIndex, + fAccessible, fComponent, index); + CHECK_EXCEPTION(); + if (row < 0) return -1; + return row; +} + +- (NSRange)accessibilityRangeForLine:(NSInteger)line +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(NSRangeFromString(@"")); + DECLARE_STATIC_METHOD_RETURN(jm_getRangeForLine, sjc_CAccessibleText, "getRangeForLine", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", NSRangeFromString(@"")); + jintArray axTextRange = (jintArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, + jm_getRangeForLine, fAccessible, fComponent, line); + CHECK_EXCEPTION(); + if (axTextRange == NULL) return NSRangeFromString(@""); + + NSRange range = [javaIntArrayToNSRangeValue(env,axTextRange) rangeValue]; + (*env)->DeleteLocalRef(env, axTextRange); + return range; +} + +- (NSString *)accessibilityStringForRange:(NSRange)range +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;", nil); + jstring jstringForRange = (jstring)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getStringForRange, + fAccessible, fComponent, range.location, range.length); + CHECK_EXCEPTION(); + if (jstringForRange == NULL) return @""; + NSString* str = JavaStringToNSString(env, jstringForRange); + (*env)->DeleteLocalRef(env, jstringForRange); + return str; +} + +- (id)accessibilityValue +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil); + // cmcnote: inefficient to make three distinct JNI calls. Coalesce. radr://3951923 + GET_ACCESSIBLETEXT_METHOD_RETURN(@""); + jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, + sjm_getAccessibleText, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axText == NULL) return nil; + (*env)->DeleteLocalRef(env, axText); + + GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(nil); + jobject axEditableText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, + sjm_getAccessibleEditableText, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axEditableText == NULL) return nil; + + DECLARE_STATIC_METHOD_RETURN(jm_getTextRange, sjc_CAccessibleText, "getTextRange", + "(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;", nil); + jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange, + axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent); + CHECK_EXCEPTION(); + NSString *string = JavaStringToNSString(env, jrange); + + (*env)->DeleteLocalRef(env, jrange); + (*env)->DeleteLocalRef(env, axEditableText); + + if (string == nil) string = @""; + return string; +} + +- (NSAccessibilitySubrole)accessibilitySubrole { + if ([self accessibleIsPasswordText]) { + return NSAccessibilitySecureTextFieldSubrole; + } + return nil; +} + +- (NSRange)accessibilityRangeForIndex:(NSInteger)index +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(NSRangeFromString(@"")); + DECLARE_STATIC_METHOD_RETURN(jm_getRangeForIndex, sjc_CAccessibleText, "getRangeForIndex", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", NSRangeFromString(@"")); + jintArray axTextRange = (jintArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getRangeForIndex, + fAccessible, fComponent, index); + CHECK_EXCEPTION(); + if (axTextRange == NULL) return NSRangeFromString(@""); + + return [javaIntArrayToNSRangeValue(env, axTextRange) rangeValue]; +} + +- (NSAccessibilityRole)accessibilityRole { + return [sRoles objectForKey:self.javaRole]; +} + +- (NSRange)accessibilityRangeForPosition:(NSPoint)point +{ + point.y = [[[[self view] window] screen] frame].size.height - point.y; // flip into java screen coords (0 is at upper-left corner of screen) + + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(NSRangeFromString(@"")); + DECLARE_STATIC_METHOD_RETURN(jm_getCharacterIndexAtPosition, sjc_CAccessibleText, "getCharacterIndexAtPosition", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)I", NSRangeFromString(@"")); + jint charIndex = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, jm_getCharacterIndexAtPosition, + fAccessible, fComponent, point.x, point.y); + CHECK_EXCEPTION(); + if (charIndex == -1) return NSRangeFromString(@""); + + // AccessibleText.getIndexAtPoint returns -1 for an invalid point + NSRange range = NSMakeRange(charIndex, 1); //range's length is 1 - one-character range + return range; +} + +- (NSString *)accessibilitySelectedText +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(jm_getSelectedText, sjc_CAccessibleText, "getSelectedText", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil); + jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getSelectedText, + fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axText == NULL) return @""; + NSString* str = JavaStringToNSString(env, axText); + (*env)->DeleteLocalRef(env, axText); + return str; +} + +- (NSRange)accessibilitySelectedTextRange +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(NSRangeFromString(@"")); + DECLARE_STATIC_METHOD_RETURN(jm_getSelectedTextRange, sjc_CAccessibleText, "getSelectedTextRange", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I", NSRangeFromString(@"")); + jintArray axTextRange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, + jm_getSelectedTextRange, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axTextRange == NULL) return NSRangeFromString(@""); + + return [javaIntArrayToNSRangeValue(env, axTextRange) rangeValue]; +} + +- (NSInteger)accessibilityNumberOfCharacters +{ + // cmcnote: should coalesce these two calls - radr://3951923 + // also, static text doesn't always have accessibleText. if axText is null, should get the charcount of the accessibleName instead + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_ACCESSIBLETEXT_METHOD_RETURN(0); + jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, + sjm_getAccessibleText, fAccessible, fComponent); + CHECK_EXCEPTION(); + NSInteger num = getAxTextCharCount(env, axText, fComponent); + (*env)->DeleteLocalRef(env, axText); + return num; +} + +- (NSInteger)accessibilityInsertionPointLineNumber +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS_RETURN(0); + DECLARE_STATIC_METHOD_RETURN(jm_getLineNumberForInsertionPoint, sjc_CAccessibleText, + "getLineNumberForInsertionPoint", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I", 0); + jint row = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, + jm_getLineNumberForInsertionPoint, fAccessible, fComponent); + CHECK_EXCEPTION(); + return row >= 0 ? row : 0; +} + +- (void)setAccessibilitySelectedText:(NSString *)accessibilitySelectedText +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jstring jstringValue = NSStringToJavaString(env, accessibilitySelectedText); + GET_CACCESSIBLETEXT_CLASS(); + DECLARE_STATIC_METHOD(jm_setSelectedText, sjc_CAccessibleText, "setSelectedText", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;Ljava/lang/String;)V"); + (*env)->CallStaticVoidMethod(env, sjc_CAccessibleText, jm_setSelectedText, + fAccessible, fComponent, jstringValue); + CHECK_EXCEPTION(); +} + +- (void)setAccessibilitySelectedTextRange:(NSRange)accessibilitySelectedTextRange +{ + jint startIndex = accessibilitySelectedTextRange.location; + jint endIndex = startIndex + accessibilitySelectedTextRange.length; + + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBLETEXT_CLASS(); + DECLARE_STATIC_METHOD(jm_setSelectedTextRange, sjc_CAccessibleText, "setSelectedTextRange", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)V"); + (*env)->CallStaticVoidMethod(env, sjc_CAccessibleText, jm_setSelectedTextRange, + fAccessible, fComponent, startIndex, endIndex); + CHECK_EXCEPTION(); +} + +- (BOOL)isAccessibilityEdited { + return YES; +} + +- (BOOL)isAccessibilityEnabled { + return YES; +} + +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + +/* +* Other text methods +- (NSRange)accessibilitySharedCharacterRange; +- (NSArray *)accessibilitySharedTextUIElements; +- (NSData *)accessibilityRTFForRange:(NSRange)range; +- (NSRange)accessibilityStyleRangeForIndex:(NSInteger)index; +*/ + +@end + diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h new file mode 100644 index 00000000000..48074b209e0 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "ListAccessibility.h" + +// This is a tree representation. See: https://developer.apple.com/documentation/appkit/nsoutlineview + +@interface OutlineAccessibility : ListAccessibility + +@property(readonly) BOOL isTreeRootVisible; + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m new file mode 100644 index 00000000000..acc5727cd6b --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "OutlineAccessibility.h" +#import "JavaAccessibilityUtilities.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" + +static jclass sjc_CAccessibility = NULL; + +static jmethodID sjm_isTreeRootVisible = NULL; +#define GET_ISTREEROOTVISIBLE_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(sjm_isTreeRootVisible, sjc_CAccessibility, "isTreeRootVisible", \ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Z", ret); + +@implementation OutlineAccessibility + +- (BOOL)isTreeRootVisible +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_ISTREEROOTVISIBLE_METHOD_RETURN(NO); + bool isTreeRootVisible = (*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, sjm_isTreeRootVisible, fAccessible, fComponent); + CHECK_EXCEPTION(); + return isTreeRootVisible; +} + +// NSAccessibilityElement protocol methods + +- (NSString *)accessibilityLabel +{ + return [[super accessibilityLabel] isEqualToString:@"list"] ? @"tree" : [super accessibilityLabel]; +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h new file mode 100644 index 00000000000..8cc8e1760c6 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "ListRowAccessibility.h" + +@interface OutlineRowAccessibility : ListRowAccessibility + +@property(readwrite) int accessibleLevel; + +- (jobject)currentAccessibleWithENV:(JNIEnv *)env; + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m new file mode 100644 index 00000000000..a2bce0bf701 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "jni.h" +#import "OutlineRowAccessibility.h" +#import "JavaAccessibilityUtilities.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" +#import "OutlineAccessibility.h" +#import "sun_lwawt_macosx_CAccessibility.h" + +static jclass sjc_CAccessible = NULL; +#define GET_CACCESSIBLE_CLASS_RETURN(ret) \ + GET_CLASS_RETURN(sjc_CAccessible, "sun/lwawt/macosx/CAccessible", ret); + +@implementation OutlineRowAccessibility + +@synthesize accessibleLevel; + +- (jobject)currentAccessibleWithENV:(JNIEnv *)env +{ + jobject jAxContext = getAxContext(env, fAccessible, fComponent); + if (jAxContext == NULL) return NULL; + jclass axContextClass = (*env)->GetObjectClass(env, jAxContext); + DECLARE_METHOD_RETURN(jm_getCurrentComponent, axContextClass, "getCurrentComponent", "()Ljava/awt/Component;", NULL); + jobject newComponent = (*env)->CallObjectMethod(env, jAxContext, jm_getCurrentComponent); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, jAxContext); + if (newComponent != NULL) { + GET_CACCESSIBLE_CLASS_RETURN(NULL); + DECLARE_STATIC_METHOD_RETURN(sjm_getCAccessible, sjc_CAccessible, "getCAccessible", "(Ljavax/accessibility/Accessible;)Lsun/lwawt/macosx/CAccessible;", NULL); + jobject currentAccessible = (*env)->CallStaticObjectMethod(env, sjc_CAccessible, sjm_getCAccessible, newComponent); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, newComponent); + return currentAccessible; + } else { + return NULL; + } +} + +// NSAccessibilityElement protocol methods + +- (NSArray *)accessibilityChildren +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject currentAccessible = [self currentAccessibleWithENV:env]; + if (currentAccessible != NULL) { + CommonComponentAccessibility *currentElement = [CommonComponentAccessibility createWithAccessible:currentAccessible withEnv:env withView:self->fView isCurrent:YES]; + NSArray *children = [CommonComponentAccessibility childrenOfParent:currentElement withEnv:env withChildrenCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN allowIgnored:YES]; + if ([children count] != 0) { + return children; + } + } + + return [NSArray arrayWithObject:[CommonComponentAccessibility createWithParent:self + accessible:self->fAccessible + role:self->fJavaRole + index:self->fIndex + withEnv:env + withView:self->fView + isWrapped:YES]]; +} + +- (NSInteger)accessibilityDisclosureLevel +{ + int level = [self accessibleLevel]; + return [(OutlineAccessibility *)[self accessibilityParent] isTreeRootVisible] ? level - 1 : level; +} + +- (BOOL)isAccessibilityDisclosed +{ + return isExpanded([ThreadUtilities getJNIEnv], [self axContextWithEnv:[ThreadUtilities getJNIEnv]], self->fComponent); +} + +- (NSAccessibilitySubrole)accessibilitySubrole +{ + return NSAccessibilityOutlineRowSubrole;; +} + +- (NSAccessibilityRole)accessibilityRole +{ + return NSAccessibilityRowRole;; +} + +- (BOOL)isAccessibilitySelected +{ + return YES; +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.m index 8254b63df3d..7c2ce4a4735 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.m @@ -39,7 +39,7 @@ - (NSAccessibilityRole _Nonnull)accessibilityRole - (id _Nonnull) accessibilityValue { AWT_ASSERT_APPKIT_THREAD; - return [self accessibilityValueAttribute]; + return [super accessibilityValue]; } @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ScrollAreaAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ScrollAreaAccessibility.m index 71c8de3de6a..d3e2d352db6 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ScrollAreaAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ScrollAreaAccessibility.m @@ -26,6 +26,7 @@ #import "ScrollAreaAccessibility.h" #import "ThreadUtilities.h" #import "JNIUtilities.h" +#import "sun_lwawt_macosx_CAccessibility.h" /* * Implementation of the accessibility peer for the ScrollArea role @@ -35,16 +36,16 @@ @implementation ScrollAreaAccessibility - (NSArray * _Nullable)accessibilityContentsAttribute { JNIEnv *env = [ThreadUtilities getJNIEnv]; - NSArray *children = [JavaComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_ALL_CHILDREN allowIgnored:YES]; + NSArray *children = [CommonComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN allowIgnored:YES]; if ([children count] <= 0) return nil; NSArray *contents = [NSMutableArray arrayWithCapacity:[children count]]; // The scroll bars are in the children. children less the scroll bars is the contents NSEnumerator *enumerator = [children objectEnumerator]; - JavaComponentAccessibility *aElement; - while ((aElement = (JavaComponentAccessibility *)[enumerator nextObject])) { - if (![[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) { + CommonComponentAccessibility *aElement; + while ((aElement = (CommonComponentAccessibility *)[enumerator nextObject])) { + if (![[aElement accessibilityRole] isEqualToString:NSAccessibilityScrollBarRole]) { // no scroll bars in contents [(NSMutableArray *)contents addObject:aElement]; } @@ -56,14 +57,14 @@ - (id _Nullable)getScrollBarwithOrientation:(enum NSAccessibilityOrientation)ori { JNIEnv *env = [ThreadUtilities getJNIEnv]; - NSArray *children = [JavaComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_ALL_CHILDREN allowIgnored:YES]; + NSArray *children = [CommonComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN allowIgnored:YES]; if ([children count] <= 0) return nil; // The scroll bars are in the children. - JavaComponentAccessibility *aElement; + CommonComponentAccessibility *aElement; NSEnumerator *enumerator = [children objectEnumerator]; - while ((aElement = (JavaComponentAccessibility *)[enumerator nextObject])) { - if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) { + while ((aElement = (CommonComponentAccessibility *)[enumerator nextObject])) { + if ([[aElement accessibilityRole] isEqualToString:NSAccessibilityScrollBarRole]) { jobject elementAxContext = [aElement axContextWithEnv:env]; if (orientation == NSAccessibilityOrientationHorizontal) { if (isHorizontal(env, elementAxContext, fComponent)) { diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SliderAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SliderAccessibility.m index 5324b7e1afd..39cb21f3149 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SliderAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SliderAccessibility.m @@ -39,12 +39,12 @@ - (NSAccessibilityRole _Nonnull)accessibilityRole - (NSString * _Nullable)accessibilityLabel { - return [self accessibilityTitleAttribute]; + return [super accessibilityLabel]; } - (id _Nullable)accessibilityValue { - return [self accessibilityValueAttribute]; + return [super accessibilityValue]; } - (BOOL)accessibilityPerformIncrement @@ -57,4 +57,14 @@ - (BOOL)accessibilityPerformDecrement return [self performAccessibleAction:DECREMENT]; } +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SpinboxAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SpinboxAccessibility.m index 7290a2ee848..4dac6bd93f9 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SpinboxAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SpinboxAccessibility.m @@ -39,12 +39,12 @@ - (NSAccessibilityRole _Nonnull)accessibilityRole - (NSString * _Nullable)accessibilityLabel { - return [self accessibilityTitleAttribute]; + return [super accessibilityLabel]; } - (id _Nullable)accessibilityValue { - return [self accessibilityValueAttribute]; + return [super accessibilityValue]; } - (BOOL)accessibilityPerformIncrement @@ -58,4 +58,14 @@ - (BOOL)accessibilityPerformDecrement return [self performAccessibleAction:DECREMENT]; } +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/StaticTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/StaticTextAccessibility.m index 8e905c45c64..b54a32be5eb 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/StaticTextAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/StaticTextAccessibility.m @@ -47,4 +47,14 @@ - (NSRange)accessibilityVisibleCharacterRange return [self accessibilityVisibleCharacterRangeAttribute]; } +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + @end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h new file mode 100644 index 00000000000..0b497d4afc2 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface TabButtonAccessibility : CommonComponentAccessibility { + jobject fTabGroupAxContext; +} + +@property(readonly) jobject tabGroup; + +// from TabGroup controller +- (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole; +- (void)performPressAction; + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m new file mode 100644 index 00000000000..4caf97c21cb --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "TabButtonAccessibility.h" +#import "JavaAccessibilityAction.h" +#import "JavaAccessibilityUtilities.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" + +@implementation TabButtonAccessibility + +- (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole +{ + self = [super initWithParent:parent withEnv:env withAccessible:accessible withIndex:index withView:view withJavaRole:javaRole]; + if (self) { + if (tabGroup != NULL) { + fTabGroupAxContext = (*env)->NewWeakGlobalRef(env, tabGroup); + CHECK_EXCEPTION(); + } else { + fTabGroupAxContext = NULL; + } + } + return self; +} + +- (void)dealloc +{ + JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; + + if (fTabGroupAxContext != NULL) { + (*env)->DeleteWeakGlobalRef(env, fTabGroupAxContext); + fTabGroupAxContext = NULL; + } + + [super dealloc]; +} + +- (jobject)tabGroup +{ + if (fTabGroupAxContext == NULL) { + JNIEnv* env = [ThreadUtilities getJNIEnv]; + jobject tabGroupAxContext = [(CommonComponentAccessibility *)[self parent] axContextWithEnv:env]; + fTabGroupAxContext = (*env)->NewWeakGlobalRef(env, tabGroupAxContext); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, tabGroupAxContext); + } + return fTabGroupAxContext; +} + +- (void)performPressAction { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + TabGroupAction *action = [[TabGroupAction alloc] initWithEnv:env withTabGroup:[self tabGroup] withIndex:fIndex withComponent:fComponent]; + [action perform]; + [action release]; +} + +// NSAccessibilityElement protocol methods + +- (NSAccessibilitySubrole)accessibilitySubrole +{ + if (@available(macOS 10.13, *)) { + return NSAccessibilityTabButtonSubrole; + } + return NSAccessibilityUnknownSubrole; +} + +- (id)accessibilityValue +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + jobject selAccessible = getAxContextSelection(env, [self tabGroup], fIndex, fComponent); + + // Returns the current selection of the page tab list + id val = [NSNumber numberWithBool:ObjectEquals(env, axContext, selAccessible, fComponent)]; + + (*env)->DeleteLocalRef(env, selAccessible); + (*env)->DeleteLocalRef(env, axContext); + return val; +} + +- (BOOL)accessibilityPerformPress { + [self performPressAction]; + return YES; +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h new file mode 100644 index 00000000000..c99b18c904e --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface TabGroupAccessibility : CommonComponentAccessibility { + NSInteger _numTabs; +} + +@property(readonly) NSInteger numTabs; + +- (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext; +- (NSArray *)tabButtonsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored; +- (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored; + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m new file mode 100644 index 00000000000..76fafc0faaf --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "TabGroupAccessibility.h" +#import "TabButtonAccessibility.h" +#import "../JavaAccessibilityUtilities.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" +#import "sun_lwawt_macosx_CAccessibility.h" + +static jclass sjc_CAccessibility = NULL; + +static jmethodID jm_getChildrenAndRoles = NULL; +#define GET_CHILDRENANDROLES_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(jm_getChildrenAndRoles, sjc_CAccessibility, "getChildrenAndRoles",\ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;IZ)[Ljava/lang/Object;", ret); + +@implementation TabGroupAccessibility + +- (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext +{ + NSArray *tabs = [self tabButtonsWithEnv:env withTabGroupAxContext:axContext withTabCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN allowIgnored:NO]; + + // Looking at the JTabbedPane sources, there is always one AccessibleSelection. + jobject selAccessible = getAxContextSelection(env, axContext, 0, fComponent); + if (selAccessible == NULL) return nil; + + // Go through the tabs and find selAccessible + _numTabs = [tabs count]; + CommonComponentAccessibility *aTab; + NSInteger i; + for (i = 0; i < _numTabs; i++) { + aTab = (CommonComponentAccessibility *)[tabs objectAtIndex:i]; + if ([aTab isAccessibleWithEnv:env forAccessible:selAccessible]) { + (*env)->DeleteLocalRef(env, selAccessible); + return aTab; + } + } + (*env)->DeleteLocalRef(env, selAccessible); + return nil; +} + +- (NSArray *)tabButtonsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored +{ + GET_CHILDRENANDROLES_METHOD_RETURN(nil); + jobjectArray jtabsAndRoles = (jobjectArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getChildrenAndRoles, + fAccessible, fComponent, whichTabs, allowIgnored); + CHECK_EXCEPTION(); + if(jtabsAndRoles == NULL) return nil; + + jsize arrayLen = (*env)->GetArrayLength(env, jtabsAndRoles); + if (arrayLen == 0) { + (*env)->DeleteLocalRef(env, jtabsAndRoles); + return nil; + } + NSMutableArray *tabs = [NSMutableArray arrayWithCapacity:(arrayLen/2)]; + + // all of the tabs have the same role, so we can just find out what that is here and use it for all the tabs + jobject jtabJavaRole = (*env)->GetObjectArrayElement(env, jtabsAndRoles, 1); // the array entries alternate between tab/role, starting with tab. so the first role is entry 1. + if (jtabJavaRole == NULL) { + (*env)->DeleteLocalRef(env, jtabsAndRoles); + return nil; + } + DECLARE_CLASS_RETURN(sjc_AccessibleRole, "javax/accessibility/AccessibleRole", nil); + DECLARE_FIELD_RETURN(sjf_key, sjc_AccessibleRole, "key", "Ljava/lang/String;", nil); + jobject jkey = (*env)->GetObjectField(env, jtabJavaRole, sjf_key); + CHECK_EXCEPTION(); + NSString *tabJavaRole = JavaStringToNSString(env, jkey); + (*env)->DeleteLocalRef(env, jkey); + + NSInteger i; + NSUInteger tabIndex = (whichTabs >= 0) ? whichTabs : 0; // if we're getting one particular child, make sure to set its index correctly + for(i = 0; i < arrayLen; i+=2) { + jobject jtab = (*env)->GetObjectArrayElement(env, jtabsAndRoles, i); + CommonComponentAccessibility *tab = [[[TabButtonAccessibility alloc] initWithParent:self withEnv:env withAccessible:jtab withIndex:tabIndex withTabGroup:axContext withView:[self view] withJavaRole:tabJavaRole] autorelease]; + (*env)->DeleteLocalRef(env, jtab); + [tabs addObject:tab]; + tabIndex++; + } + (*env)->DeleteLocalRef(env, jtabsAndRoles); + return tabs; +} + +- (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored +{ + // Contents are the children of the selected tab. + id currentTab = [self currentTabWithEnv:env withAxContext:axContext]; + if (currentTab == nil) return nil; + + NSArray *contents = [CommonComponentAccessibility childrenOfParent:currentTab withEnv:env withChildrenCode:whichTabs allowIgnored:allowIgnored]; + if ([contents count] <= 0) return nil; + return contents; +} + +- (NSInteger)numTabs +{ + if (_numTabs == -1) { + _numTabs = [[self accessibilityTabsAttribute] count]; + } + return _numTabs; +} + +// NSAccessibilityElement protocol methods + +- (NSArray *)accessibilityTabs +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + id tabs = [self tabButtonsWithEnv:env withTabGroupAxContext:axContext withTabCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN allowIgnored:NO]; + (*env)->DeleteLocalRef(env, axContext); + return tabs; +} + +- (NSArray *)accessibilityContents +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + NSArray* cont = [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN allowIgnored:NO]; + (*env)->DeleteLocalRef(env, axContext); + return cont; +} + +- (id)accessibilityValue +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + id val = [self currentTabWithEnv:env withAxContext:axContext]; + (*env)->DeleteLocalRef(env, axContext); + return val; +} + +- (NSArray *)accessibilityChildren +{ + //children = AXTabs + AXContents + NSArray *tabs = [self accessibilityTabs]; + NSArray *contents = [self accessibilityContents]; + + NSMutableArray *children = [NSMutableArray arrayWithCapacity:[tabs count] + [contents count]]; + [children addObjectsFromArray:tabs]; + [children addObjectsFromArray:contents]; + + return (NSArray *)children; +} + +- (NSArray *)accessibilityArrayAttributeValues:(NSAccessibilityAttributeName)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount +{ + NSArray *result = nil; + if ( (maxCount == 1) && [attribute isEqualToString:NSAccessibilityChildrenAttribute]) { + // Children codes for ALL, SELECTED, VISIBLE are <0. If the code is >=0, we treat it as an index to a single child + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + + //children = AXTabs + AXContents + NSArray *children = [self tabButtonsWithEnv:env withTabGroupAxContext:axContext withTabCode:index allowIgnored:NO]; // first look at the tabs + if ([children count] > 0) { + result = children; + } else { + children= [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:(index-[self numTabs]) allowIgnored:NO]; + if ([children count] > 0) { + result = children; + } + } + (*env)->DeleteLocalRef(env, axContext); + } else { + result = [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount]; + } + return result; +} + +- (void)setAccessibilityValue:(id)accessibilityValue +{ + // set the current tab + NSNumber *number = (NSNumber *)accessibilityValue; + if (![number boolValue]) return; + + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + setAxContextSelection(env, axContext, fIndex, fComponent); + (*env)->DeleteLocalRef(env, axContext); +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h new file mode 100644 index 00000000000..4f746706f5c --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface TableAccessibility : CommonComponentAccessibility + +- (BOOL)isAccessibleChildSelectedFromIndex:(int)index; +- (int) accessibleRowAtIndex:(int)index; +- (int) accessibleColumnAtIndex:(int)index; + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m new file mode 100644 index 00000000000..cd534c1ad3c --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "jni.h" +#import "TableRowAccessibility.h" +#import "JavaAccessibilityAction.h" +#import "JavaAccessibilityUtilities.h" +#import "TableAccessibility.h" +#import "CellAccessibility.h" +#import "ColumnAccessibility.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" +#import "CellAccessibility.h" +#import "sun_lwawt_macosx_CAccessibility.h" + +static jclass sjc_CAccessibility = NULL; + +static jmethodID sjm_getAccessibleName = NULL; +#define GET_ACCESSIBLENAME_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", \ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", ret); + +@implementation TableAccessibility + +- (id)getTableInfo:(jint)info +{ + if (fAccessible == NULL) return 0; + + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(jm_getTableInfo, sjc_CAccessibility, "getTableInfo", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)I", nil); + jint count = (*env)->CallStaticIntMethod(env, sjc_CAccessibility, jm_getTableInfo, fAccessible, + fComponent, info); + CHECK_EXCEPTION(); + NSNumber *index = [NSNumber numberWithInt:count]; + return index; +} + +- (NSArray *)getTableSelectedInfo:(jint)info +{ + if (fAccessible == NULL) return 0; + + JNIEnv* env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(jm_getTableSelectedInfo, sjc_CAccessibility, "getTableSelectedInfo", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", nil); + jintArray selected = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getTableSelectedInfo, fAccessible, + fComponent, info); + CHECK_EXCEPTION(); + if (selected == NULL) { + return nil; + } + jsize arrayLen = (*env)->GetArrayLength(env, selected); + jint *indexsis = (*env)->GetIntArrayElements(env, selected, 0); + NSMutableArray *nsArraySelected = [NSMutableArray arrayWithCapacity:arrayLen]; + for (int i = 0; i < arrayLen; i++) { + [nsArraySelected addObject:[NSNumber numberWithInt:indexsis[i]]]; + } + (*env)->DeleteLocalRef(env, selected); + return [NSArray arrayWithArray:nsArraySelected]; +} + +- (int)accessibleRowAtIndex:(int)index +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + if (axContext == NULL) return 0; + jclass clsInfo = (*env)->GetObjectClass(env, axContext); + DECLARE_METHOD_RETURN(jm_getAccessibleRowAtIndex, clsInfo, "getAccessibleRowAtIndex", "(I)I", -1); + jint rowAtIndex = (*env)->CallIntMethod(env, axContext, jm_getAccessibleRowAtIndex, (jint)index); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, axContext); + return (int)rowAtIndex; +} + +- (int)accessibleColumnAtIndex:(int)index +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + if (axContext == NULL) return 0; + jclass clsInfo = (*env)->GetObjectClass(env, axContext); + DECLARE_METHOD_RETURN(jm_getAccessibleColumnAtIndex, clsInfo, "getAccessibleColumnAtIndex", "(I)I", -1); + jint columnAtIndex = (*env)->CallIntMethod(env, axContext, jm_getAccessibleColumnAtIndex, (jint)index); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, axContext); + return (int)columnAtIndex; +} + +- (BOOL) isAccessibleChildSelectedFromIndex:(int)index +{ + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject axContext = [self axContextWithEnv:env]; + if (axContext == NULL) return NO; + jclass clsInfo = (*env)->GetObjectClass(env, axContext); + DECLARE_METHOD_RETURN(jm_isAccessibleChildSelected, clsInfo, "isAccessibleChildSelected", "(I)Z", NO); + jboolean isAccessibleChildSelected = (*env)->CallIntMethod(env, axContext, jm_isAccessibleChildSelected, (jint)index); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, axContext); + return isAccessibleChildSelected; +} + +// NSAccessibilityElement protocol methods + +- (NSArray *)accessibilityChildren +{ + return [self accessibilityRows]; +} + +- (NSArray *)accessibilitySelectedChildren +{ + return [self accessibilitySelectedRows]; +} + +- (NSArray *)accessibilityRows +{ + int rowCount = [self accessibilityRowCount]; + NSMutableArray *children = [NSMutableArray arrayWithCapacity:rowCount]; + for (int i = 0; i < rowCount; i++) { + [children addObject:[[TableRowAccessibility alloc] initWithParent:self + withEnv:[ThreadUtilities getJNIEnv] + withAccessible:NULL + withIndex:i + withView:[self view] + withJavaRole:JavaAccessibilityIgnore]]; + } + return [NSArray arrayWithArray:children]; +} + +- (nullable NSArray> *)accessibilitySelectedRows +{ + NSArray *selectedRowIndexses = [self getTableSelectedInfo:sun_lwawt_macosx_CAccessibility_JAVA_AX_ROWS]; + NSMutableArray *children = [NSMutableArray arrayWithCapacity:[selectedRowIndexses count]]; + for (NSNumber *index in selectedRowIndexses) { + [children addObject:[[TableRowAccessibility alloc] initWithParent:self + withEnv:[ThreadUtilities getJNIEnv] + withAccessible:NULL + withIndex:index.unsignedIntValue + withView:[self view] + withJavaRole:JavaAccessibilityIgnore]]; + } + return [NSArray arrayWithArray:children]; +} + +- (NSString *)accessibilityLabel +{ + return [super accessibilityLabel] == NULL ? @"table" : [super accessibilityLabel]; +} + +- (NSRect)accessibilityFrame +{ + return [super accessibilityFrame]; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + +- (nullable NSArray *)accessibilityColumns +{ + int colCount = [self accessibilityColumnCount]; + NSMutableArray *columns = [NSMutableArray arrayWithCapacity:colCount]; + for (int i = 0; i < colCount; i++) { + [columns addObject:[[ColumnAccessibility alloc] initWithParent:self + withEnv:[ThreadUtilities getJNIEnv] + withAccessible:NULL + withIndex:i + withView:self->fView + withJavaRole:JavaAccessibilityIgnore]]; + } + return [NSArray arrayWithArray:columns]; +} + +- (nullable NSArray *)accessibilitySelectedColumns +{ + NSArray *indexes = [self getTableSelectedInfo:sun_lwawt_macosx_CAccessibility_JAVA_AX_COLS]; + NSMutableArray *columns = [NSMutableArray arrayWithCapacity:[indexes count]]; + for (NSNumber *i in indexes) { + [columns addObject:[[ColumnAccessibility alloc] initWithParent:self + withEnv:[ThreadUtilities getJNIEnv] + withAccessible:NULL + withIndex:i.unsignedIntValue + withView:self->fView + withJavaRole:JavaAccessibilityIgnore]]; + } + return [NSArray arrayWithArray:columns]; +} + +- (NSInteger)accessibilityRowCount +{ + return [[self getTableInfo:sun_lwawt_macosx_CAccessibility_JAVA_AX_ROWS] integerValue]; +} + +- (NSInteger)accessibilityColumnCount +{ + return [[self getTableInfo:sun_lwawt_macosx_CAccessibility_JAVA_AX_COLS] integerValue]; +} + +- (nullable NSArray *)accessibilitySelectedCells +{ + NSArray *children = [super accessibilitySelectedChildren]; + NSMutableArray *cells = [NSMutableArray arrayWithCapacity:[children count]]; + for (CommonComponentAccessibility *child in children) { + [cells addObject:[[CellAccessibility alloc] initWithParent:self + withEnv:[ThreadUtilities getJNIEnv] + withAccessible:child->fAccessible + withIndex:child->fIndex + withView:fView + withJavaRole:child->fJavaRole]]; + } + return [NSArray arrayWithArray:cells]; +} + +- (id)accessibilityCellForColumn:(NSInteger)column row:(NSInteger)row { + return [[(TableRowAccessibility *)[[self accessibilityRows] objectAtIndex:row] accessibilityChildren] objectAtIndex:column]; +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h new file mode 100644 index 00000000000..afa9eb44e3f --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "CommonComponentAccessibility.h" + +@interface TableRowAccessibility : CommonComponentAccessibility + +@property(readonly) NSUInteger rowNumberInTable; + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m new file mode 100644 index 00000000000..60985e203f9 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 "TableRowAccessibility.h" +#import "JavaAccessibilityAction.h" +#import "JavaAccessibilityUtilities.h" +#import "TableAccessibility.h" +#import "CellAccessibility.h" +#import "ThreadUtilities.h" +#import "JNIUtilities.h" +#import "sun_lwawt_macosx_CAccessibility.h" + +static jclass sjc_CAccessibility = NULL; + +static jmethodID jm_getChildrenAndRoles = NULL; +#define GET_CHILDRENANDROLES_METHOD_RETURN(ret) \ + GET_CACCESSIBILITY_CLASS_RETURN(ret); \ + GET_STATIC_METHOD_RETURN(jm_getChildrenAndRoles, sjc_CAccessibility, "getChildrenAndRoles",\ + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;IZ)[Ljava/lang/Object;", ret); + +@implementation TableRowAccessibility + +// NSAccessibilityElement protocol methods + +- (NSAccessibilityRole)accessibilityRole +{ + return NSAccessibilityRowRole; +} + +- (NSAccessibilitySubrole)accessibilitySubrole +{ + return NSAccessibilityTableRowSubrole; +} + +- (NSArray *)accessibilityChildren +{ + NSArray *children = [super accessibilityChildren]; + if (children == nil) { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + CommonComponentAccessibility *parent = [self accessibilityParent]; + if (parent->fAccessible == NULL) return nil; + GET_CHILDRENANDROLES_METHOD_RETURN(nil); + jobjectArray jchildrenAndRoles = (jobjectArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getChildrenAndRoles, + parent->fAccessible, parent->fComponent, sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN, NO); + CHECK_EXCEPTION(); + if (jchildrenAndRoles == NULL) return nil; + + jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles); + NSMutableArray *childrenCells = [NSMutableArray arrayWithCapacity:arrayLen/2]; + + NSUInteger childIndex = fIndex * [(TableAccessibility *)parent accessibilityColumnCount]; + NSInteger i = childIndex * 2; + NSInteger n = (fIndex + 1) * [(TableAccessibility *)parent accessibilityColumnCount] * 2; + for(i; i < n; i+=2) + { + jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i); + jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1); + + NSString *childJavaRole = nil; + if (jchildJavaRole != NULL) { + DECLARE_CLASS_RETURN(sjc_AccessibleRole, "javax/accessibility/AccessibleRole", nil); + DECLARE_FIELD_RETURN(sjf_key, sjc_AccessibleRole, "key", "Ljava/lang/String;", nil); + jobject jkey = (*env)->GetObjectField(env, jchildJavaRole, sjf_key); + CHECK_EXCEPTION(); + childJavaRole = JavaStringToNSString(env, jkey); + (*env)->DeleteLocalRef(env, jkey); + } + + CellAccessibility *child = [[CellAccessibility alloc] initWithParent:self + withEnv:env + withAccessible:jchild + withIndex:childIndex + withView:self->fView + withJavaRole:childJavaRole]; + [childrenCells addObject:[[child retain] autorelease]]; + + (*env)->DeleteLocalRef(env, jchild); + (*env)->DeleteLocalRef(env, jchildJavaRole); + + childIndex++; + } + (*env)->DeleteLocalRef(env, jchildrenAndRoles); + return childrenCells; + } else { + return children; + } +} + +- (NSInteger)accessibilityIndex +{ + return self->fIndex; +} + +- (NSString *)accessibilityLabel +{ + NSString *accessibilityName = @""; + NSArray *children = [self accessibilityChildren]; + for (id cell in children) { + if ([accessibilityName isEqualToString:@""]) { + accessibilityName = [cell accessibilityLabel]; + } else { + accessibilityName = [accessibilityName stringByAppendingFormat:@", %@", [cell accessibilityLabel]]; + } + } + return accessibilityName; +} + +- (id)accessibilityParent +{ + return [super accessibilityParent]; +} + +- (NSRect)accessibilityFrame +{ + int height = [[[self accessibilityChildren] objectAtIndex:0] accessibilityFrame].size.height; + int width = 0; + NSPoint point = [[[self accessibilityChildren] objectAtIndex:0] accessibilityFrame].origin; + for (id cell in [self accessibilityChildren]) { + width += [cell accessibilityFrame].size.width; + } + return NSMakeRect(point.x, point.y, width, height); +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m index ecd4b67509f..1d30f7eb51d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m @@ -71,7 +71,7 @@ - (id) initWithJavaLayer:(jobject)layer self.leftInset = 0; self.framebufferOnly = NO; self.nextDrawableCount = 0; - self.opaque = FALSE; + self.opaque = YES; CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); CVDisplayLinkSetOutputCallback(displayLink, &displayLinkCallback, (__bridge void*)self); return self; @@ -288,3 +288,17 @@ CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* no [layer blitTexture]; } + +JNIEXPORT void JNICALL +Java_sun_java2d_metal_MTLLayer_nativeSetOpaque +(JNIEnv *env, jclass cls, jlong layerPtr, jboolean opaque) +{ + JNI_COCOA_ENTER(env); + + MTLLayer *mtlLayer = OBJC(layerPtr); + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + [mtlLayer setOpaque:(opaque == JNI_TRUE)]; + }]; + + JNI_COCOA_EXIT(env); +} diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java index 4510882ad4b..5e5a4a52d35 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,19 +25,15 @@ package com.sun.imageio.plugins.bmp; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; -import javax.imageio.metadata.IIOMetadataNode; -import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; -import org.w3c.dom.Node; -import com.sun.imageio.plugins.common.I18N; +import javax.imageio.metadata.IIOMetadataNode; +import com.sun.imageio.plugins.common.I18N; import com.sun.imageio.plugins.common.ImageUtil; +import org.w3c.dom.Node; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; public class BMPMetadata extends IIOMetadata implements BMPConstants { public static final String nativeMetadataFormatName = @@ -114,11 +110,7 @@ public Node getAsTree(String formatName) { } private String toISO8859(byte[] data) { - try { - return new String(data, "ISO-8859-1"); - } catch (UnsupportedEncodingException e) { - return ""; - } + return new String(data, ISO_8859_1); } private Node getNativeTree() { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java index d865a58d431..061f3b1eaf0 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -25,18 +25,17 @@ package com.sun.imageio.plugins.gif; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import javax.imageio.ImageTypeSpecifier; + import javax.imageio.metadata.IIOInvalidTreeException; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.metadata.IIOMetadataNode; -import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; +import javax.imageio.metadata.IIOMetadataNode; + import org.w3c.dom.Node; +import static java.nio.charset.StandardCharsets.ISO_8859_1; + public class GIFImageMetadata extends GIFMetadata { // package scope @@ -132,11 +131,7 @@ public Node getAsTree(String formatName) { } private String toISO8859(byte[] data) { - try { - return new String(data, "ISO-8859-1"); - } catch (UnsupportedEncodingException e) { - return ""; - } + return new String(data, ISO_8859_1); } private Node getNativeTree() { @@ -384,12 +379,7 @@ public IIOMetadataNode getStandardTextNode() { while (commentIter.hasNext()) { byte[] comment = commentIter.next(); - String s = null; - try { - s = new String(comment, "ISO-8859-1"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("Encoding ISO-8859-1 unknown!"); - } + String s = new String(comment, ISO_8859_1); node = new IIOMetadataNode("TextEntry"); node.setAttribute("value", s); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java index dc780602a90..8566d45f6a4 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -25,19 +25,17 @@ package com.sun.imageio.plugins.gif; -import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import javax.imageio.ImageTypeSpecifier; + import javax.imageio.metadata.IIOInvalidTreeException; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.metadata.IIOMetadataNode; -import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; +import javax.imageio.metadata.IIOMetadataNode; + import org.w3c.dom.Node; +import static java.nio.charset.StandardCharsets.ISO_8859_1; + class GIFWritableImageMetadata extends GIFImageMetadata { // package scope @@ -95,11 +93,7 @@ public void reset() { } private byte[] fromISO8859(String data) { - try { - return data.getBytes("ISO-8859-1"); - } catch (UnsupportedEncodingException e) { - return "".getBytes(); - } + return data.getBytes(ISO_8859_1); } protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java index d4a996ee3ee..f28e7b35658 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -25,15 +25,16 @@ package com.sun.imageio.plugins.jpeg; +import java.io.IOException; + +import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.ImageOutputStream; -import javax.imageio.metadata.IIOInvalidTreeException; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; import org.w3c.dom.Node; +import static java.nio.charset.StandardCharsets.ISO_8859_1; + /** * A Comment marker segment. Retains an array of bytes representing the * comment data as it is read from the stream. If the marker segment is @@ -45,7 +46,6 @@ * byte array, again assuming the default local encoding. */ class COMMarkerSegment extends MarkerSegment { - private static final String ENCODING = "ISO-8859-1"; /** * Constructs a marker segment from the given buffer, which contains @@ -96,10 +96,7 @@ class COMMarkerSegment extends MarkerSegment { * consulted directly. */ String getComment() { - try { - return new String (data, ENCODING); - } catch (UnsupportedEncodingException e) {} // Won't happen - return null; + return new String(data, ISO_8859_1); } /** diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java index 1de4f53a813..e944847ed57 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java @@ -25,40 +25,41 @@ package com.sun.imageio.plugins.jpeg; -import javax.imageio.IIOException; -import javax.imageio.IIOImage; -import javax.imageio.ImageTypeSpecifier; -import javax.imageio.ImageReader; -import javax.imageio.metadata.IIOInvalidTreeException; -import javax.imageio.metadata.IIOMetadataNode; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.stream.ImageInputStream; -import javax.imageio.stream.ImageOutputStream; -import javax.imageio.stream.MemoryCacheImageOutputStream; -import javax.imageio.event.IIOReadProgressListener; - import java.awt.Graphics; -import java.awt.color.ICC_Profile; -import java.awt.color.ICC_ColorSpace; import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.image.BufferedImage; import java.awt.image.ColorModel; -import java.awt.image.SampleModel; -import java.awt.image.IndexColorModel; import java.awt.image.ComponentColorModel; -import java.awt.image.BufferedImage; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; +import java.awt.image.IndexColorModel; import java.awt.image.Raster; +import java.awt.image.SampleModel; import java.awt.image.WritableRaster; -import java.io.IOException; import java.io.ByteArrayOutputStream; -import java.util.List; +import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; +import javax.imageio.IIOException; +import javax.imageio.IIOImage; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.event.IIOReadProgressListener; +import javax.imageio.metadata.IIOInvalidTreeException; +import javax.imageio.metadata.IIOMetadataNode; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; +import javax.imageio.stream.MemoryCacheImageOutputStream; + +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import org.w3c.dom.NamedNodeMap; + +import static java.nio.charset.StandardCharsets.US_ASCII; /** * A JFIF (JPEG File Interchange Format) APP0 (Application-Specific) @@ -1353,7 +1354,7 @@ static void writeICC(ICC_Profile profile, ImageOutputStream ios) ios.write(0xff); ios.write(JPEG.APP2); MarkerSegment.write2bytes(ios, segLength); - byte [] id = ID.getBytes("US-ASCII"); + byte[] id = ID.getBytes(US_ASCII); ios.write(id); ios.write(0); // Null-terminate the string ios.write(chunkNum++); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java index 25bfef7f14c..c0855f1b574 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -36,10 +36,11 @@ import java.awt.image.WritableRaster; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.EOFException; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.io.SequenceInputStream; import java.util.ArrayList; import java.util.Arrays; @@ -47,19 +48,23 @@ import java.util.Iterator; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; + import javax.imageio.IIOException; -import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; + import com.sun.imageio.plugins.common.InputStreamAdapter; import com.sun.imageio.plugins.common.ReaderUtil; import com.sun.imageio.plugins.common.SubImageInputStream; -import java.io.ByteArrayOutputStream; import sun.awt.image.ByteInterleavedRaster; +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; + class PNGImageDataEnumeration implements Enumeration { boolean firstTime = true; @@ -486,9 +491,9 @@ private void parse_iTXt_chunk(int chunkLength) throws IOException { stream.readFully(b); if (compressionFlag == 1) { // Decompress the text - text = new String(inflate(b), "UTF8"); + text = new String(inflate(b), UTF_8); } else { - text = new String(b, "UTF8"); + text = new String(b, UTF_8); } metadata.iTXt_text.add(text); @@ -589,7 +594,7 @@ private void parse_tEXt_chunk(int chunkLength) throws IOException { byte[] b = new byte[textLength]; stream.readFully(b); - metadata.tEXt_text.add(new String(b, "ISO-8859-1")); + metadata.tEXt_text.add(new String(b, ISO_8859_1)); // Check if the text chunk contains image creation time if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) { @@ -690,7 +695,7 @@ private void parse_zTXt_chunk(int chunkLength) throws IOException { byte[] b = new byte[textLength]; stream.readFully(b); - metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1")); + metadata.zTXt_text.add(new String(inflate(b), ISO_8859_1)); // Check if the text chunk contains image creation time if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java index 9dc60991d13..449661b8c91 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -28,15 +28,16 @@ import java.awt.Rectangle; import java.awt.image.IndexColorModel; import java.awt.image.Raster; -import java.awt.image.WritableRaster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Iterator; import java.util.Locale; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; + import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageTypeSpecifier; @@ -47,6 +48,9 @@ import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStreamImpl; +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; + final class CRC { private static final int[] crcTable = new int[256]; @@ -801,15 +805,14 @@ private void write_iTXt() throws IOException { cs.writeBytes(languageIter.next()); cs.writeByte(0); - - cs.write(translatedKeywordIter.next().getBytes("UTF8")); + cs.write(translatedKeywordIter.next().getBytes(UTF_8)); cs.writeByte(0); String text = textIter.next(); if (compressed) { - cs.write(deflate(text.getBytes("UTF8"))); + cs.write(deflate(text.getBytes(UTF_8))); } else { - cs.write(text.getBytes("UTF8")); + cs.write(text.getBytes(UTF_8)); } cs.finish(); } @@ -833,7 +836,7 @@ private void write_zTXt() throws IOException { cs.writeByte(compressionMethod); String text = textIter.next(); - cs.write(deflate(text.getBytes("ISO-8859-1"))); + cs.write(deflate(text.getBytes(ISO_8859_1))); cs.finish(); } } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java index 5c0334abbef..3d307e9ad1b 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java @@ -22,24 +22,27 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package com.sun.imageio.plugins.tiff; import java.io.EOFException; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; + import javax.imageio.IIOException; -import javax.imageio.stream.ImageInputStream; -import javax.imageio.stream.ImageOutputStream; import javax.imageio.plugins.tiff.BaselineTIFFTagSet; import javax.imageio.plugins.tiff.TIFFDirectory; import javax.imageio.plugins.tiff.TIFFField; import javax.imageio.plugins.tiff.TIFFTag; import javax.imageio.plugins.tiff.TIFFTagSet; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +import static java.nio.charset.StandardCharsets.US_ASCII; public class TIFFIFD extends TIFFDirectory { private static final long MAX_SAMPLES_PER_PIXEL = 0xffff; @@ -283,8 +286,7 @@ private static int readFieldValue(ImageInputStream stream, if (inString) { // end of string String s = new String(bvalues, prevIndex, - index - prevIndex, - StandardCharsets.US_ASCII); + index - prevIndex, US_ASCII); v.add(s); inString = false; } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java index fdf9d49b467..1d2cff42311 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -22,6 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package com.sun.imageio.plugins.tiff; import java.awt.Point; @@ -34,8 +35,8 @@ import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.IndexColorModel; -import java.awt.image.RenderedImage; import java.awt.image.Raster; +import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.EOFException; @@ -44,27 +45,30 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; + import javax.imageio.IIOException; import javax.imageio.IIOImage; +import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; -import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; -import javax.imageio.spi.ImageWriterSpi; -import javax.imageio.stream.ImageOutputStream; -import org.w3c.dom.Node; -import com.sun.imageio.plugins.common.ImageUtil; import javax.imageio.plugins.tiff.BaselineTIFFTagSet; import javax.imageio.plugins.tiff.ExifParentTIFFTagSet; import javax.imageio.plugins.tiff.ExifTIFFTagSet; import javax.imageio.plugins.tiff.TIFFField; import javax.imageio.plugins.tiff.TIFFTag; import javax.imageio.plugins.tiff.TIFFTagSet; +import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.stream.ImageOutputStream; + +import com.sun.imageio.plugins.common.ImageUtil; import com.sun.imageio.plugins.common.SimpleRenderedImage; import com.sun.imageio.plugins.common.SingleTileRenderedImage; -import java.nio.charset.StandardCharsets; +import org.w3c.dom.Node; + +import static java.nio.charset.StandardCharsets.US_ASCII; public class TIFFImageWriter extends ImageWriter { @@ -1512,7 +1516,7 @@ void setupMetadata(ColorModel cm, SampleModel sm, (exifTags.getTag(ExifTIFFTagSet.TAG_EXIF_VERSION), TIFFTag.TIFF_UNDEFINED, 4, - ExifTIFFTagSet.EXIF_VERSION_2_2.getBytes(StandardCharsets.US_ASCII)); + ExifTIFFTagSet.EXIF_VERSION_2_2.getBytes(US_ASCII)); exifIFD.addTIFFField(f); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java index 28ad467eadd..3a13bcca94f 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPMetadata.java @@ -25,19 +25,13 @@ package com.sun.imageio.plugins.wbmp; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; -import javax.imageio.metadata.IIOMetadataNode; -import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; -import org.w3c.dom.Node; -import com.sun.imageio.plugins.common.I18N; +import javax.imageio.metadata.IIOMetadataNode; +import com.sun.imageio.plugins.common.I18N; import com.sun.imageio.plugins.common.ImageUtil; +import org.w3c.dom.Node; public class WBMPMetadata extends IIOMetadata { 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 042ca187874..141184087d0 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 @@ -22,29 +22,76 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.sun.java.swing.plaf.gtk; -import sun.swing.SwingUtilities2; -import com.sun.java.swing.plaf.gtk.GTKConstants.ArrowType; -import com.sun.java.swing.plaf.gtk.GTKConstants.ShadowType; +package com.sun.java.swing.plaf.gtk; +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Composite; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RectangularShape; +import java.awt.image.FilteredImageSource; +import java.awt.image.ImageProducer; +import java.awt.image.RGBImageFilter; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +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; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JInternalFrame; import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.basic.BasicInternalFrameTitlePane; -import javax.swing.plaf.synth.*; - -import java.awt.*; -import java.awt.geom.*; -import java.awt.image.*; -import java.io.*; -import java.net.*; -import java.security.*; -import java.util.*; +import javax.swing.plaf.synth.ColorType; +import javax.swing.plaf.synth.SynthConstants; +import javax.swing.plaf.synth.SynthContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; -import javax.swing.*; - -import javax.xml.parsers.*; +import com.sun.java.swing.plaf.gtk.GTKConstants.ArrowType; +import com.sun.java.swing.plaf.gtk.GTKConstants.ShadowType; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import org.xml.sax.SAXException; -import org.w3c.dom.*; +import sun.swing.SwingUtilities2; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; /** */ @@ -536,7 +583,8 @@ public Object run() { URL url = new URL(new File(userHome).toURI().toURL(), ".gconf/apps/metacity/general/%25gconf.xml"); // Pending: verify character encoding spec for gconf - Reader reader = new InputStreamReader(url.openStream(), "ISO-8859-1"); + Reader reader = new InputStreamReader(url.openStream(), + ISO_8859_1); char[] buf = new char[1024]; StringBuilder sb = new StringBuilder(); int n; diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatInputStream.java b/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatInputStream.java index 845312ca409..cd5ebcfd0f5 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatInputStream.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatInputStream.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.util.Objects; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; @@ -81,8 +82,7 @@ public long getFrameLength() { public int read(float[] b, int off, int len) throws IOException { if (b == null) throw new NullPointerException(); - if (off < 0 || len < 0 || len > b.length - off) - throw new IndexOutOfBoundsException(); + Objects.checkFromIndexSize(off, len, b.length); if (pos >= buffer_len) return -1; if (len == 0) diff --git a/src/java.desktop/share/classes/com/sun/media/sound/DLSSoundbank.java b/src/java.desktop/share/classes/com/sun/media/sound/DLSSoundbank.java index 55f937f0333..ebd6fba65b1 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/DLSSoundbank.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/DLSSoundbank.java @@ -47,6 +47,8 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; +import static java.nio.charset.StandardCharsets.US_ASCII; + /** * A DLS Level 1 and Level 2 soundbank reader (from files/url/streams). * @@ -1147,7 +1149,7 @@ private void writeInfoStringChunk(RIFFWriter writer, return; RIFFWriter chunk = writer.writeChunk(name); chunk.writeString(value); - int len = value.getBytes("ascii").length; + int len = value.getBytes(US_ASCII).length; chunk.write(0); len++; if (len % 2 != 0) diff --git a/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java b/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java index 4266fbe8193..62789e4493f 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -29,6 +29,8 @@ import java.io.IOException; import java.io.InputStream; +import static java.nio.charset.StandardCharsets.US_ASCII; + /** * Resource Interchange File Format (RIFF) stream decoder. * @@ -76,14 +78,14 @@ public RIFFReader(final InputStream stream) throws IOException { byte[] fourcc = new byte[4]; fourcc[0] = (byte) b; readFully(fourcc, 1, 3); - this.fourcc = new String(fourcc, "ascii"); + this.fourcc = new String(fourcc, US_ASCII); ckSize = readUnsignedInt(); avail = ckSize; if (getFormat().equals("RIFF") || getFormat().equals("LIST")) { byte[] format = new byte[4]; readFully(format); - this.riff_type = new String(format, "ascii"); + this.riff_type = new String(format, US_ASCII); } } @@ -227,10 +229,10 @@ public String readString(final int len) throws IOException { readFully(buff); for (int i = 0; i < buff.length; i++) { if (buff[i] == 0) { - return new String(buff, 0, i, "ascii"); + return new String(buff, 0, i, US_ASCII); } } - return new String(buff, "ascii"); + return new String(buff, US_ASCII); } // Read 8 bit signed integer from stream diff --git a/src/java.desktop/share/classes/com/sun/media/sound/RIFFWriter.java b/src/java.desktop/share/classes/com/sun/media/sound/RIFFWriter.java index f6943c9ef3c..6650e413613 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/RIFFWriter.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/RIFFWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -31,6 +31,8 @@ import java.io.OutputStream; import java.io.RandomAccessFile; +import static java.nio.charset.StandardCharsets.US_ASCII; + /** * Resource Interchange File Format (RIFF) stream encoder. * @@ -208,11 +210,11 @@ private RIFFWriter(RandomAccessWriter raf, String format, int chunktype) raf.write(0); if (chunktype == 0) - raf.write("RIFF".getBytes("ascii")); + raf.write("RIFF".getBytes(US_ASCII)); else if (chunktype == 1) - raf.write("LIST".getBytes("ascii")); + raf.write("LIST".getBytes(US_ASCII)); else - raf.write((format + " ").substring(0, 4).getBytes("ascii")); + raf.write((format + " ").substring(0, 4).getBytes(US_ASCII)); chunksizepointer = raf.getPointer(); this.chunktype = 2; @@ -220,8 +222,7 @@ else if (chunktype == 1) this.chunktype = chunktype; startpointer = raf.getPointer(); if (chunktype != 2) - raf.write((format + " ").substring(0, 4).getBytes("ascii")); - + raf.write((format + " ").substring(0, 4).getBytes(US_ASCII)); } public void seek(long pos) throws IOException { diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SF2Soundbank.java b/src/java.desktop/share/classes/com/sun/media/sound/SF2Soundbank.java index 7d7cff36377..ccade6b1a2e 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SF2Soundbank.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SF2Soundbank.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -42,6 +42,8 @@ import javax.sound.midi.Soundbank; import javax.sound.midi.SoundbankResource; +import static java.nio.charset.StandardCharsets.US_ASCII; + /** * A SoundFont 2.04 soundbank reader. * @@ -539,7 +541,7 @@ private void writeInfoStringChunk(RIFFWriter writer, String name, return; RIFFWriter chunk = writer.writeChunk(name); chunk.writeString(value); - int len = value.getBytes("ascii").length; + int len = value.getBytes(US_ASCII).length; chunk.write(0); len++; if (len % 2 != 0) diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SoftTuning.java b/src/java.desktop/share/classes/com/sun/media/sound/SoftTuning.java index 9ed8871f523..73b2226c6f1 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SoftTuning.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SoftTuning.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -25,11 +25,12 @@ package com.sun.media.sound; -import java.io.UnsupportedEncodingException; import java.util.Arrays; import javax.sound.midi.Patch; +import static java.nio.charset.StandardCharsets.US_ASCII; + /** * A tuning program container, for use with MIDI Tuning. * See: http://www.midi.org @@ -99,11 +100,7 @@ public void load(byte[] data) { // http://www.midi.org/about-midi/tuning.shtml //if (!checksumOK2(data)) // break; - try { - name = new String(data, 6, 16, "ascii"); - } catch (UnsupportedEncodingException e) { - name = null; - } + name = new String(data, 6, 16, US_ASCII); int r = 22; for (int i = 0; i < 128; i++) { int xx = data[r++] & 0xFF; @@ -135,11 +132,7 @@ public void load(byte[] data) { // http://www.midi.org/about-midi/tuning_extens.shtml if (!checksumOK(data)) break; - try { - name = new String(data, 7, 16, "ascii"); - } catch (UnsupportedEncodingException e) { - name = null; - } + name = new String(data, 7, 16, US_ASCII); int r = 23; for (int i = 0; i < 128; i++) { int xx = data[r++] & 0xFF; @@ -156,11 +149,7 @@ public void load(byte[] data) { // http://www.midi.org/about-midi/tuning_extens.shtml if (!checksumOK(data)) break; - try { - name = new String(data, 7, 16, "ascii"); - } catch (UnsupportedEncodingException e) { - name = null; - } + name = new String(data, 7, 16, US_ASCII); int[] octave_tuning = new int[12]; for (int i = 0; i < 12; i++) octave_tuning[i] = (data[i + 23] & 0xFF) - 64; @@ -174,11 +163,7 @@ public void load(byte[] data) { // http://www.midi.org/about-midi/tuning_extens.shtml if (!checksumOK(data)) break; - try { - name = new String(data, 7, 16, "ascii"); - } catch (UnsupportedEncodingException e) { - name = null; - } + name = new String(data, 7, 16, US_ASCII); double[] octave_tuning = new double[12]; for (int i = 0; i < 12; i++) { int v = (data[i * 2 + 23] & 0xFF) * 128 diff --git a/src/java.desktop/share/classes/javax/swing/JTabbedPane.java b/src/java.desktop/share/classes/javax/swing/JTabbedPane.java index ee484e55c47..4acf4f8a930 100644 --- a/src/java.desktop/share/classes/javax/swing/JTabbedPane.java +++ b/src/java.desktop/share/classes/javax/swing/JTabbedPane.java @@ -45,6 +45,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Locale; +import java.util.Objects; import javax.accessibility.Accessible; import javax.accessibility.AccessibleComponent; @@ -1790,7 +1791,7 @@ public String getToolTipText(MouseEvent event) { private void checkIndex(int index) { if (index < 0 || index >= pages.size()) { - throw new IndexOutOfBoundsException("Index: "+index+", Tab count: "+pages.size()); + throw new IndexOutOfBoundsException("Index: " + index + ", Tab count: " + pages.size()); } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf index 8b0b1493891..17019bb00c2 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf @@ -25751,7 +25751,7 @@ true - + @@ -25857,7 +25857,7 @@ true - + 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 7ec09676d2b..53e0aedf3a5 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 @@ -22,26 +22,82 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package javax.swing.text.html; -import sun.awt.AppContext; +package javax.swing.text.html; -import java.awt.*; -import java.awt.event.*; -import java.io.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringReader; +import java.io.Writer; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.net.URL; -import javax.swing.text.*; -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.TextUI; -import java.util.*; -import javax.accessibility.*; -import java.lang.ref.*; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Enumeration; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.swing.Action; +import javax.swing.JComponent; +import javax.swing.JEditorPane; +import javax.swing.JViewport; +import javax.swing.SizeRequirements; +import javax.swing.SwingUtilities; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.HyperlinkEvent; +import javax.swing.plaf.TextUI; +import javax.swing.text.AbstractDocument; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.BoxView; +import javax.swing.text.ComponentView; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +import javax.swing.text.Element; +import javax.swing.text.ElementIterator; +import javax.swing.text.Highlighter; +import javax.swing.text.IconView; +import javax.swing.text.JTextComponent; +import javax.swing.text.LabelView; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.Position; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import javax.swing.text.StyledEditorKit; +import javax.swing.text.TextAction; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; import javax.swing.text.html.parser.ParserDelegator; +import sun.awt.AppContext; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; + /** * The Swing JEditorPane text component supports different kinds * of content via a plug-in mechanism called an EditorKit. Because @@ -403,7 +459,7 @@ public StyleSheet getStyleSheet() { try { InputStream is = HTMLEditorKit.getResourceAsStream(DEFAULT_CSS); Reader r = new BufferedReader( - new InputStreamReader(is, "ISO-8859-1")); + new InputStreamReader(is, ISO_8859_1)); defaultStyles.loadRules(r, null); r.close(); } catch (Throwable e) { 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 ed7a97e29ad..0867e40defe 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 @@ -22,15 +22,34 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package javax.swing.text.rtf; -import java.lang.*; -import java.util.*; -import java.io.*; import java.awt.Color; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.StreamTokenizer; import java.security.AccessController; import java.security.PrivilegedAction; -import javax.swing.text.*; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.StyledDocument; +import javax.swing.text.TabStop; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; /** * Takes a sequence of RTF tokens and text and appends the text @@ -592,7 +611,7 @@ static char[] readCharset(InputStream strm) char[] values = new char[256]; int i; StreamTokenizer in = new StreamTokenizer(new BufferedReader( - new InputStreamReader(strm, "ISO-8859-1"))); + new InputStreamReader(strm, ISO_8859_1))); in.eolIsSignificant(false); in.commentChar('#'); diff --git a/src/java.desktop/share/classes/sun/awt/FontDescriptor.java b/src/java.desktop/share/classes/sun/awt/FontDescriptor.java index e934c27a4c1..046ecce16da 100644 --- a/src/java.desktop/share/classes/sun/awt/FontDescriptor.java +++ b/src/java.desktop/share/classes/sun/awt/FontDescriptor.java @@ -22,14 +22,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package sun.awt; import java.io.ByteArrayOutputStream; -import java.io.OutputStreamWriter; import java.io.IOException; +import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; -import java.nio.charset.StandardCharsets; + +import static java.nio.charset.StandardCharsets.UTF_16BE; +import static java.nio.charset.StandardCharsets.UTF_16LE; public class FontDescriptor implements Cloneable { @@ -109,9 +112,8 @@ public String toString() { public boolean useUnicode() { if (useUnicode && unicodeEncoder == null) { try { - this.unicodeEncoder = isLE? - StandardCharsets.UTF_16LE.newEncoder(): - StandardCharsets.UTF_16BE.newEncoder(); + this.unicodeEncoder = isLE ? UTF_16LE.newEncoder(): + UTF_16BE.newEncoder(); } catch (IllegalArgumentException x) {} } return useUnicode; 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 84677785cc6..0898a3ddcec 100644 --- a/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java +++ b/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java @@ -29,77 +29,78 @@ import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; - import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.FlavorMap; import java.awt.datatransfer.FlavorTable; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; - +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.WritableRaster; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FilePermission; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Reader; import java.io.SequenceInputStream; import java.io.StringReader; - +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; import java.net.URI; import java.net.URISyntaxException; - import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; - import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; - -import java.util.*; - -import sun.datatransfer.DataFlavorUtil; - -import sun.awt.AppContext; -import sun.awt.ComponentFactory; -import sun.awt.SunToolkit; - -import java.awt.image.BufferedImage; -import java.awt.image.ImageObserver; -import java.awt.image.RenderedImage; -import java.awt.image.WritableRaster; -import java.awt.image.ColorModel; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.Stack; +import java.util.TreeMap; +import java.util.stream.Stream; import javax.imageio.ImageIO; -import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; -import javax.imageio.ImageWriter; +import javax.imageio.ImageReader; import javax.imageio.ImageTypeSpecifier; - +import javax.imageio.ImageWriter; import javax.imageio.spi.ImageWriterSpi; - import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; +import sun.awt.AppContext; +import sun.awt.ComponentFactory; +import sun.awt.SunToolkit; import sun.awt.image.ImageRepresentation; import sun.awt.image.ToolkitImage; +import sun.datatransfer.DataFlavorUtil; -import java.io.FilePermission; -import java.util.stream.Stream; - +import static java.nio.charset.StandardCharsets.UTF_8; /** * Provides a set of functions to be shared among the DataFlavor class and @@ -550,7 +551,7 @@ protected String getBestCharsetForTextFormat(Long lFormat, try { byte[] charsetNameBytes = (byte[])localeTransferable .getTransferData(javaTextEncodingFlavor); - charset = new String(charsetNameBytes, StandardCharsets.UTF_8); + charset = new String(charsetNameBytes, UTF_8); } catch (UnsupportedFlavorException cannotHappen) { } } else { diff --git a/src/java.desktop/share/classes/sun/font/SunFontManager.java b/src/java.desktop/share/classes/sun/font/SunFontManager.java index 870009612f7..1942aacd997 100644 --- a/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java @@ -3352,14 +3352,7 @@ public Font[] getAllInstalledFonts() { } } - String[] fontNames = null; - if (fontMapNames.size() > 0) { - fontNames = new String[fontMapNames.size()]; - Object [] keyNames = fontMapNames.keySet().toArray(); - for (int i=0; i < keyNames.length; i++) { - fontNames[i] = (String)keyNames[i]; - } - } + String[] fontNames = fontMapNames.keySet().toArray(new String[0]); Font[] fonts = new Font[fontNames.length]; for (int i=0; i < fontNames.length; i++) { fonts[i] = new Font(fontNames[i], Font.PLAIN, 1); @@ -3428,11 +3421,7 @@ public String[] getInstalledFontFamilyNames(Locale requestedLocale) { // Add any native font family names here addNativeFontFamilyNames(familyNames, requestedLocale); - String[] retval = new String[familyNames.size()]; - Object [] keyNames = familyNames.keySet().toArray(); - for (int i=0; i < keyNames.length; i++) { - retval[i] = familyNames.get(keyNames[i]); - } + String[] retval = familyNames.values().toArray(new String[0]); if (requestedLocale.equals(Locale.getDefault())) { lastDefaultLocale = requestedLocale; allFamilies = new String[retval.length]; diff --git a/src/java.desktop/share/classes/sun/font/Type1Font.java b/src/java.desktop/share/classes/sun/font/Type1Font.java index f640c6f09a9..1c9cf9f8e88 100644 --- a/src/java.desktop/share/classes/sun/font/Type1Font.java +++ b/src/java.desktop/share/classes/sun/font/Type1Font.java @@ -25,23 +25,23 @@ package sun.font; -import java.lang.ref.WeakReference; import java.awt.FontFormatException; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; -import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.nio.BufferUnderflowException; import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; +import java.util.HashMap; +import java.util.HashSet; + import sun.java2d.Disposer; import sun.java2d.DisposerRecord; -import java.util.HashSet; -import java.util.HashMap; -import java.awt.Font; + +import static java.nio.charset.StandardCharsets.US_ASCII; /* * Adobe Technical Note 5040 details the format of PFB files. @@ -609,11 +609,7 @@ private String getSimpleToken(ByteBuffer bb) { byte[] nameBytes = new byte[pos2-pos1-1]; bb.position(pos1); bb.get(nameBytes); - try { - return new String(nameBytes, "US-ASCII"); - } catch (UnsupportedEncodingException e) { - return new String(nameBytes); - } + return new String(nameBytes, US_ASCII); } private String getString(ByteBuffer bb) { @@ -623,11 +619,7 @@ private String getString(ByteBuffer bb) { byte[] nameBytes = new byte[pos2-pos1-1]; bb.position(pos1); bb.get(nameBytes); - try { - return new String(nameBytes, "US-ASCII"); - } catch (UnsupportedEncodingException e) { - return new String(nameBytes); - } + return new String(nameBytes, US_ASCII); } diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java b/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java index e7ef49b1fc9..4335b1c9fbf 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java @@ -186,11 +186,7 @@ public String[] getAvailableFontFamilyNames(Locale requestedLocale) { map.put(installed[i].toLowerCase(requestedLocale), installed[i]); } - String[] retval = new String[map.size()]; - Object [] keyNames = map.keySet().toArray(); - for (int i=0; i < keyNames.length; i++) { - retval[i] = map.get(keyNames[i]); - } + String[] retval = map.values().toArray(new String[0]); return retval; } } 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 f3a966d5075..405f9490179 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 @@ -27,6 +27,7 @@ import java.awt.color.CMMException; import java.awt.color.ICC_Profile; +import java.util.concurrent.locks.StampedLock; import sun.java2d.cmm.ColorTransform; import sun.java2d.cmm.PCMM; @@ -34,6 +35,11 @@ final class LCMS implements PCMM { + /** + * Prevent changing profiles data during transform creation. + */ + private static final StampedLock lock = new StampedLock(); + /* methods invoked from ICC_Profile */ @Override public Profile loadProfile(byte[] data) { @@ -80,8 +86,13 @@ public byte[] getTagData(Profile p, int tagSignature) { } @Override - public synchronized void setTagData(Profile p, int tagSignature, byte[] data) { - getLcmsProfile(p).setTag(tagSignature, data); + public void setTagData(Profile p, int tagSignature, byte[] data) { + long stamp = lock.writeLock(); + try { + getLcmsProfile(p).setTag(tagSignature, data); + } finally { + lock.unlockWrite(stamp); + } } static synchronized native LCMSProfile getProfileID(ICC_Profile profile); @@ -94,15 +105,20 @@ static long createTransform( Object disposerRef) { long[] ptrs = new long[profiles.length]; - - for (int i = 0; i < profiles.length; i++) { - if (profiles[i] == null) throw new CMMException("Unknown profile ID"); - - ptrs[i] = profiles[i].getLcmsPtr(); + long stamp = lock.readLock(); + try { + for (int i = 0; i < profiles.length; i++) { + if (profiles[i] == null) { + throw new CMMException("Unknown profile ID"); + } + ptrs[i] = profiles[i].getLcmsPtr(); + } + + return createNativeTransform(ptrs, renderType, inFormatter, + isInIntPacked, outFormatter, isOutIntPacked, disposerRef); + } finally { + lock.unlockRead(stamp); } - - return createNativeTransform(ptrs, renderType, inFormatter, - isInIntPacked, outFormatter, isOutIntPacked, disposerRef); } private static native long createNativeTransform( diff --git a/src/java.desktop/share/classes/sun/print/PageableDoc.java b/src/java.desktop/share/classes/sun/print/PageableDoc.java index 859f40e853e..ef829d5bfbb 100644 --- a/src/java.desktop/share/classes/sun/print/PageableDoc.java +++ b/src/java.desktop/share/classes/sun/print/PageableDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -25,12 +25,10 @@ package sun.print; +import java.awt.print.Pageable; import java.io.IOException; import java.io.InputStream; import java.io.Reader; -import java.io.UnsupportedEncodingException; - -import java.awt.print.Pageable; import javax.print.Doc; import javax.print.DocFlavor; @@ -57,9 +55,7 @@ public Object getPrintData() throws IOException { return pageable; } - public Reader getReaderForText() - throws UnsupportedEncodingException, IOException { - + public Reader getReaderForText() throws IOException { return null; } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java b/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java index 117e3865241..78b8844f061 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -58,9 +58,13 @@ * @since 1.5 */ -import jdk.internal.misc.Unsafe; import java.util.HashMap; +import jdk.internal.misc.Unsafe; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; + public final class XAtom { // Order of lock: XAWTLock -> XAtom.class @@ -308,12 +312,7 @@ public void setPropertyUTF8(long window, String str) { throw new IllegalStateException("Atom should be initialized"); } checkWindow(window); - byte[] bdata = null; - try { - bdata = str.getBytes("UTF-8"); - } catch (java.io.UnsupportedEncodingException uee) { - uee.printStackTrace(); - } + byte[] bdata = str.getBytes(UTF_8); if (bdata != null) { setAtomData(window, XA_UTF8_STRING.atom, bdata); } @@ -327,12 +326,7 @@ public void setProperty8(long window, String str) { throw new IllegalStateException("Atom should be initialized"); } checkWindow(window); - byte[] bdata = null; - try { - bdata = str.getBytes("ISO-8859-1"); - } catch (java.io.UnsupportedEncodingException uee) { - uee.printStackTrace(); - } + byte[] bdata = str.getBytes(ISO_8859_1); if (bdata != null) { setAtomData(window, XA_STRING, bdata); } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XNETProtocol.java b/src/java.desktop/unix/classes/sun/awt/X11/XNETProtocol.java index 2d82ace9845..81c31b277fb 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XNETProtocol.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XNETProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -23,14 +23,17 @@ * questions. */ - package sun.awt.X11; import java.awt.Frame; +import java.nio.charset.Charset; import sun.awt.IconInfo; import sun.util.logging.PlatformLogger; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProtocol { private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XNETProtocol"); @@ -382,22 +385,18 @@ public String getWMName() { * mandates UTF8_STRING for _NET_WM_NAME but at least sawfish-1.0 * still uses STRING. (mmm, moving targets...). */ - String charSet = "UTF8"; + Charset charSet = UTF_8; byte[] net_wm_name = XA_NET_WM_NAME.getByteArrayProperty(NetWindow, XA_UTF8_STRING.getAtom()); if (net_wm_name == null) { net_wm_name = XA_NET_WM_NAME.getByteArrayProperty(NetWindow, XAtom.XA_STRING); - charSet = "ASCII"; + charSet = US_ASCII; } if (net_wm_name == null) { return null; } - try { - net_wm_name_cache = new String(net_wm_name, charSet); - return net_wm_name_cache; - } catch (java.io.UnsupportedEncodingException uex) { - return null; - } + net_wm_name_cache = new String(net_wm_name, charSet); + return net_wm_name_cache; } /** 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 2587db4459a..f44084af6e3 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java @@ -47,7 +47,6 @@ import java.awt.event.WindowEvent; import java.awt.peer.ComponentPeer; import java.awt.peer.WindowPeer; -import java.io.UnsupportedEncodingException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; @@ -67,6 +66,8 @@ import sun.java2d.pipe.Region; import sun.util.logging.PlatformLogger; +import static java.nio.charset.StandardCharsets.UTF_8; + class XWindowPeer extends XPanelPeer implements WindowPeer, DisplayChangedListener { @@ -1358,12 +1359,7 @@ public String run() { } messageBuilder.append('"'); messageBuilder.append('\0'); - final byte[] message; - try { - message = messageBuilder.toString().getBytes("UTF-8"); - } catch (UnsupportedEncodingException cannotHappen) { - return; - } + final byte[] message = messageBuilder.toString().getBytes(UTF_8); XClientMessageEvent req = null; diff --git a/src/java.desktop/unix/classes/sun/awt/XSettings.java b/src/java.desktop/unix/classes/sun/awt/XSettings.java index 812255ea850..4136a350172 100644 --- a/src/java.desktop/unix/classes/sun/awt/XSettings.java +++ b/src/java.desktop/unix/classes/sun/awt/XSettings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -26,12 +26,10 @@ package sun.awt; import java.awt.Color; - -import java.io.UnsupportedEncodingException; - import java.util.HashMap; import java.util.Map; +import static java.nio.charset.StandardCharsets.UTF_8; /** * Per-screen XSETTINGS. @@ -198,12 +196,7 @@ private String getString(int len) { needBytes(len); - String str = null; - try { - str = new String(data, idx, len, "UTF-8"); - } catch (UnsupportedEncodingException e) { - // XXX: cannot happen, "UTF-8" is always supported - } + String str = new String(data, idx, len, UTF_8); idx = (idx + len + 3) & ~0x3; return str; diff --git a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java index 9808e46ee1f..ddf2e434f80 100644 --- a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java +++ b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -32,23 +32,24 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; import java.util.Properties; import java.util.Scanner; + import sun.awt.FcFontManager; import sun.awt.FontConfiguration; import sun.awt.FontDescriptor; import sun.awt.SunToolkit; -import sun.font.CompositeFontDescriptor; -import sun.font.FontConfigManager.FontConfigInfo; import sun.font.FontConfigManager.FcCompFont; import sun.font.FontConfigManager.FontConfigFont; +import sun.font.FontConfigManager.FontConfigInfo; import sun.util.logging.PlatformLogger; +import static java.nio.charset.StandardCharsets.ISO_8859_1; + public class FcFontConfiguration extends FontConfiguration { /** Version of the cache file format understood by this code. @@ -178,7 +179,7 @@ protected FontDescriptor[] buildFontDescriptors(int fontIndex, int styleIndex) { String[] componentFaceNames = cfi[idx].getComponentFaceNames(); FontDescriptor[] ret = new FontDescriptor[componentFaceNames.length]; for (int i = 0; i < componentFaceNames.length; i++) { - ret[i] = new FontDescriptor(componentFaceNames[i], StandardCharsets.ISO_8859_1.newEncoder(), new int[0]); + ret[i] = new FontDescriptor(componentFaceNames[i], ISO_8859_1.newEncoder(), new int[0]); } return ret; diff --git a/src/java.desktop/unix/classes/sun/font/NativeFont.java b/src/java.desktop/unix/classes/sun/font/NativeFont.java index b30b6459c3b..3bd212b2525 100644 --- a/src/java.desktop/unix/classes/sun/font/NativeFont.java +++ b/src/java.desktop/unix/classes/sun/font/NativeFont.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -32,10 +32,10 @@ import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; -import java.io.UnsupportedEncodingException; -import java.lang.ref.WeakReference; import java.util.Locale; +import static java.nio.charset.StandardCharsets.UTF_8; + /* * Ideally there would be no native fonts used, and this class would be * unneeded and removed. Presently it is still needed until such time @@ -213,23 +213,11 @@ static boolean hasExternalBitmaps(String platName) { pos = sb.indexOf("-0-", pos); }; String xlfd = sb.toString(); - byte[] bytes = null; - try { - bytes = xlfd.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - bytes = xlfd.getBytes(); - } - return haveBitmapFonts(bytes); + return haveBitmapFonts(xlfd.getBytes(UTF_8)); } public static boolean fontExists(String xlfd) { - byte[] bytes = null; - try { - bytes = xlfd.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - bytes = xlfd.getBytes(); - } - return fontExists(bytes); + return fontExists(xlfd.getBytes(UTF_8)); } private static native boolean haveBitmapFonts(byte[] xlfd); @@ -380,13 +368,7 @@ byte[] getPlatformNameBytes(int ptSize) { } String xlfd = sb.toString(); - byte[] bytes = null; - try { - bytes = xlfd.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - bytes = xlfd.getBytes(); - } - return bytes; + return xlfd.getBytes(UTF_8); } public String toString() { diff --git a/src/java.desktop/unix/classes/sun/print/AttributeClass.java b/src/java.desktop/unix/classes/sun/print/AttributeClass.java index 76a652b2a93..0fb27909a26 100644 --- a/src/java.desktop/unix/classes/sun/print/AttributeClass.java +++ b/src/java.desktop/unix/classes/sun/print/AttributeClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -22,10 +22,13 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package sun.print; -import java.util.Objects; import java.io.ByteArrayInputStream; +import java.util.Objects; + +import static java.nio.charset.StandardCharsets.UTF_8; public class AttributeClass { private String myName; @@ -187,10 +190,7 @@ public String getStringValue() { byte[] strBytes = new byte[valLength]; bufStream.read(strBytes, 0, valLength); - try { - strVal = new String(strBytes, "UTF-8"); - } catch (java.io.UnsupportedEncodingException uee) { - } + strVal = new String(strBytes, UTF_8); } return strVal; } @@ -219,10 +219,7 @@ public String[] getArrayOfStringValues() { int valLength = bufStream.read(); byte[] bufBytes = new byte[valLength]; bufStream.read(bufBytes, 0, valLength); - try { - valueArray[i] = new String(bufBytes, "UTF-8"); - } catch (java.io.UnsupportedEncodingException uee) { - } + valueArray[i] = new String(bufBytes, UTF_8); } return valueArray; } diff --git a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java index fee8bc3d3cd..7ef37b116ab 100644 --- a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java +++ b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java @@ -27,42 +27,82 @@ import java.awt.GraphicsEnvironment; import java.awt.Toolkit; -import javax.print.attribute.*; -import javax.print.attribute.standard.*; -import javax.print.DocFlavor; -import javax.print.DocPrintJob; -import javax.print.PrintService; -import javax.print.ServiceUIFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import java.util.Date; -import java.util.Arrays; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import javax.print.event.PrintServiceAttributeListener; - -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLConnection; -import java.net.HttpURLConnection; +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; import java.io.File; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.io.DataInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ByteArrayInputStream; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.nio.charset.Charset; - -import java.util.Iterator; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.Locale; import java.util.Map; +import javax.print.DocFlavor; +import javax.print.DocPrintJob; +import javax.print.PrintService; +import javax.print.ServiceUIFactory; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSet; +import javax.print.attribute.AttributeSetUtilities; +import javax.print.attribute.EnumSyntax; +import javax.print.attribute.HashAttributeSet; +import javax.print.attribute.HashPrintServiceAttributeSet; +import javax.print.attribute.PrintRequestAttribute; +import javax.print.attribute.PrintServiceAttribute; +import javax.print.attribute.PrintServiceAttributeSet; +import javax.print.attribute.Size2DSyntax; +import javax.print.attribute.standard.Chromaticity; +import javax.print.attribute.standard.ColorSupported; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.CopiesSupported; +import javax.print.attribute.standard.Destination; +import javax.print.attribute.standard.DialogOwner; +import javax.print.attribute.standard.DialogTypeSelection; +import javax.print.attribute.standard.Fidelity; +import javax.print.attribute.standard.Finishings; +import javax.print.attribute.standard.JobName; +import javax.print.attribute.standard.JobSheets; +import javax.print.attribute.standard.Media; +import javax.print.attribute.standard.MediaPrintableArea; +import javax.print.attribute.standard.MediaSize; +import javax.print.attribute.standard.MediaSizeName; +import javax.print.attribute.standard.MediaTray; +import javax.print.attribute.standard.NumberUp; +import javax.print.attribute.standard.OrientationRequested; +import javax.print.attribute.standard.PDLOverrideSupported; +import javax.print.attribute.standard.PageRanges; +import javax.print.attribute.standard.PagesPerMinute; +import javax.print.attribute.standard.PagesPerMinuteColor; +import javax.print.attribute.standard.PrinterInfo; +import javax.print.attribute.standard.PrinterIsAcceptingJobs; +import javax.print.attribute.standard.PrinterLocation; +import javax.print.attribute.standard.PrinterMakeAndModel; +import javax.print.attribute.standard.PrinterMessageFromOperator; +import javax.print.attribute.standard.PrinterMoreInfo; +import javax.print.attribute.standard.PrinterMoreInfoManufacturer; +import javax.print.attribute.standard.PrinterName; +import javax.print.attribute.standard.PrinterResolution; +import javax.print.attribute.standard.PrinterState; +import javax.print.attribute.standard.PrinterStateReasons; +import javax.print.attribute.standard.PrinterURI; +import javax.print.attribute.standard.QueuedJobCount; +import javax.print.attribute.standard.RequestingUserName; +import javax.print.attribute.standard.SheetCollate; +import javax.print.attribute.standard.Sides; +import javax.print.event.PrintServiceAttributeListener; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; public class IPPPrintService implements PrintService, SunPrinterJobService { @@ -325,11 +365,7 @@ protected static void debug_println(String str) { if ((name == null) || (url == null)){ throw new IllegalArgumentException("null uri or printer name"); } - try { - printer = java.net.URLDecoder.decode(name, "UTF-8"); - } catch (java.io.UnsupportedEncodingException e) { - printer = name; - } + printer = java.net.URLDecoder.decode(name, UTF_8); supportedDocFlavors = null; supportedCats = null; mediaSizeNames = null; @@ -359,11 +395,7 @@ protected static void debug_println(String str) { if ((name == null) || (uriStr == null)){ throw new IllegalArgumentException("null uri or printer name"); } - try { - printer = java.net.URLDecoder.decode(name, "UTF-8"); - } catch (java.io.UnsupportedEncodingException e) { - printer = name; - } + printer = java.net.URLDecoder.decode(name, UTF_8); supportedDocFlavors = null; supportedCats = null; mediaSizeNames = null; @@ -1735,9 +1767,8 @@ public synchronized boolean isPostscript() { InputStream is = urlConnection.getInputStream(); if (is != null) { - BufferedReader d = - new BufferedReader(new InputStreamReader(is, - Charset.forName("ISO-8859-1"))); + BufferedReader d = new BufferedReader( + new InputStreamReader(is, ISO_8859_1)); String lineStr; while ((lineStr = d.readLine()) != null) { if (lineStr.startsWith("*cupsFilter:")) { @@ -1829,13 +1860,7 @@ public OutputStream run() { public static boolean writeIPPRequest(OutputStream os, String operCode, AttributeClass[] attCl) { - OutputStreamWriter osw; - try { - osw = new OutputStreamWriter(os, "UTF-8"); - } catch (java.io.UnsupportedEncodingException exc) { - debug_println(debugPrefix+"writeIPPRequest, UTF-8 not supported? Exception: "+exc); - return false; - } + OutputStreamWriter osw = new OutputStreamWriter(os, UTF_8); debug_println(debugPrefix+"writeIPPRequest, op code= "+operCode); char[] opCode = new char[2]; opCode[0] = (char)Byte.parseByte(operCode.substring(0,2), 16); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDataTransferer.java b/src/java.desktop/windows/classes/sun/awt/windows/WDataTransferer.java index 16b6faf7ee7..c82fc91a4e1 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WDataTransferer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WDataTransferer.java @@ -25,19 +25,15 @@ package sun.awt.windows; -import java.awt.Image; import java.awt.Graphics2D; +import java.awt.Image; import java.awt.Transparency; - import java.awt.color.ColorSpace; - import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.FlavorTable; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; - import java.awt.geom.AffineTransform; - import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; @@ -48,18 +44,16 @@ import java.awt.image.ImageObserver; import java.awt.image.Raster; import java.awt.image.WritableRaster; - import java.io.BufferedInputStream; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.io.File; - import java.net.URL; - import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -69,13 +63,11 @@ import sun.awt.Mutex; import sun.awt.datatransfer.DataTransferer; import sun.awt.datatransfer.ToolkitThreadBlockedHandler; - import sun.awt.image.ImageRepresentation; import sun.awt.image.ToolkitImage; -import java.util.ArrayList; - -import java.io.ByteArrayOutputStream; +import static java.nio.charset.StandardCharsets.UTF_16LE; +import static java.nio.charset.StandardCharsets.UTF_8; /** * Platform-specific support for the data transfer subsystem. @@ -249,7 +241,7 @@ public Object translateBytes(byte[] bytes, DataFlavor flavor, long format, if (bytes == null || !DataFlavor.javaFileListFlavor.equals(flavor)) { throw new IOException("data translation failed"); } - String st = new String(bytes, 0, bytes.length, "UTF-16LE"); + String st = new String(bytes, 0, bytes.length, UTF_16LE); String[] filenames = st.split("\0"); if( 0 == filenames.length ){ return null; @@ -275,7 +267,7 @@ public Object translateBytes(byte[] bytes, DataFlavor flavor, long format, { try { charset = new String((byte[])localeTransferable. - getTransferData(javaTextEncodingFlavor), "UTF-8"); + getTransferData(javaTextEncodingFlavor), UTF_8); } catch (UnsupportedFlavorException cannotHappen) { } } @@ -548,8 +540,6 @@ public static EHTMLReadMode getEHTMLReadMode (DataFlavor df) { * on encode: static convertToHTMLFormat is responsible for HTML clipboard header creation */ class HTMLCodec extends InputStream { - //static section - public static final String ENCODING = "UTF-8"; public static final String VERSION = "Version:"; public static final String START_HTML = "StartHTML:"; @@ -671,13 +661,8 @@ public static byte[] convertToHTMLFormat(byte[] bytes) { //HTML header.append(htmlPrefix); - byte[] headerBytes = null, trailerBytes = null; - - try { - headerBytes = header.toString().getBytes(ENCODING); - trailerBytes = htmlSuffix.getBytes(ENCODING); - } catch (UnsupportedEncodingException cannotHappen) { - } + byte[] headerBytes = header.toString().getBytes(UTF_8); + byte[] trailerBytes = htmlSuffix.getBytes(UTF_8); byte[] retval = new byte[headerBytes.length + bytes.length + trailerBytes.length]; @@ -786,7 +771,7 @@ private void parseDescription() throws IOException BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( bufferedStream, - ENCODING + UTF_8 ), CHAR_BUFFER_LEN ); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDesktopProperties.java b/src/java.desktop/windows/classes/sun/awt/windows/WDesktopProperties.java index 54f4ddea320..8126c31b95c 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WDesktopProperties.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WDesktopProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -89,12 +89,7 @@ static boolean isWindowsProperty(String name) { * Returns String[] containing available property names */ private String [] getKeyNames() { - Object[] keys = map.keySet().toArray(); - String[] sortedKeys = new String[keys.length]; - - for ( int nkey = 0; nkey < keys.length; nkey++ ) { - sortedKeys[nkey] = keys[nkey].toString(); - } + String[] sortedKeys = map.keySet().toArray(new String[0]); Arrays.sort(sortedKeys); return sortedKeys; } diff --git a/src/java.management/share/classes/com/sun/jmx/remote/security/HashedPasswordManager.java b/src/java.management/share/classes/com/sun/jmx/remote/security/HashedPasswordManager.java index ba05ada5b0f..63b68db88f4 100644 --- a/src/java.management/share/classes/com/sun/jmx/remote/security/HashedPasswordManager.java +++ b/src/java.management/share/classes/com/sun/jmx/remote/security/HashedPasswordManager.java @@ -30,8 +30,6 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.FileLock; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -41,6 +39,8 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * HashedPasswordManager loads passwords from the password file and optionally * hashes them. @@ -139,7 +139,7 @@ private String[] getHash(String algorithm, String password) { MessageDigest digest = MessageDigest.getInstance(algorithm); digest.reset(); digest.update(salt); - byte[] hash = digest.digest(password.getBytes(StandardCharsets.UTF_8)); + byte[] hash = digest.digest(password.getBytes(UTF_8)); String saltStr = Base64.getEncoder().encodeToString(salt); String hashStr = Base64.getEncoder().encodeToString(hash); @@ -167,7 +167,7 @@ private String[] readPasswordFile() throws IOException { } lock.release(); } - String str = new String(data, StandardCharsets.UTF_8); + String str = new String(data, UTF_8); return str.split("\\r?\\n"); } } @@ -175,7 +175,7 @@ private String[] readPasswordFile() throws IOException { private void writePasswordFile(String input) throws IOException { synchronized (HashedPasswordManager.class) { try (FileOutputStream fout = new FileOutputStream(passwordFile); - OutputStreamWriter out = new OutputStreamWriter(fout, StandardCharsets.UTF_8); + OutputStreamWriter out = new OutputStreamWriter(fout, UTF_8); FileLock lock = fout.getChannel().lock()) { out.write(input); lock.release(); @@ -199,7 +199,7 @@ public synchronized boolean authenticate(String userName, char[] inputPassword) MessageDigest digest = MessageDigest.getInstance(us.hashAlgorithm); digest.reset(); digest.update(salt); - ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(CharBuffer.wrap(inputPassword)); + ByteBuffer byteBuffer = UTF_8.encode(CharBuffer.wrap(inputPassword)); byte[] passwordBytes = new byte[byteBuffer.limit()]; byteBuffer.get(passwordBytes); byte[] hash = digest.digest(passwordBytes); diff --git a/src/java.management/share/classes/javax/management/loading/MLetParser.java b/src/java.management/share/classes/javax/management/loading/MLetParser.java index a067a281403..3380a77b650 100644 --- a/src/java.management/share/classes/javax/management/loading/MLetParser.java +++ b/src/java.management/share/classes/javax/management/loading/MLetParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -26,6 +26,7 @@ package javax.management.loading; import static com.sun.jmx.defaults.JmxProperties.MLET_LOGGER; +import static java.nio.charset.StandardCharsets.UTF_8; import java.io.BufferedReader; import java.io.File; @@ -164,7 +165,7 @@ public List parse(URL url) throws IOException { conn = url.openConnection(); Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), - "UTF-8")); + UTF_8)); // The original URL may have been redirected - this // sets it to whatever URL/codebase we ended up getting diff --git a/src/java.management/share/classes/sun/management/counter/perf/PerfDataEntry.java b/src/java.management/share/classes/sun/management/counter/perf/PerfDataEntry.java index 3f69b0dd992..a3a06d23020 100644 --- a/src/java.management/share/classes/sun/management/counter/perf/PerfDataEntry.java +++ b/src/java.management/share/classes/sun/management/counter/perf/PerfDataEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -27,7 +27,8 @@ import sun.management.counter.*; import java.nio.*; -import java.io.UnsupportedEncodingException; + +import static java.nio.charset.StandardCharsets.UTF_8; class PerfDataEntry { private class EntryFieldOffset { @@ -127,14 +128,7 @@ private class EntryFieldOffset { } // convert name into a String - try { - name = new String(symbolBytes, "UTF-8"); - } - catch (UnsupportedEncodingException e) { - // should not reach here - // "UTF-8" is always a known encoding - throw new InternalError(e.getMessage(), e); - } + name = new String(symbolBytes, UTF_8); if (variability == Variability.INVALID) { throw new InstrumentationException("Invalid variability attribute:" + diff --git a/src/java.management/share/classes/sun/management/counter/perf/PerfDataType.java b/src/java.management/share/classes/sun/management/counter/perf/PerfDataType.java index 8b8d61cb950..731ff40179e 100644 --- a/src/java.management/share/classes/sun/management/counter/perf/PerfDataType.java +++ b/src/java.management/share/classes/sun/management/counter/perf/PerfDataType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,7 +25,7 @@ package sun.management.counter.perf; -import java.io.UnsupportedEncodingException; +import static java.nio.charset.StandardCharsets.UTF_8; /** * A typesafe enumeration for the data types supported for @@ -88,12 +88,7 @@ public static PerfDataType toPerfDataType(byte type) { private PerfDataType(String name, String c, int size) { this.name = name; this.size = size; - try { - byte[] b = c.getBytes("UTF-8"); - this.value = b[0]; - } catch (UnsupportedEncodingException e) { - // ignore, "UTF-8" is always a known encoding - throw new InternalError("Unknown encoding", e); - } + byte[] b = c.getBytes(UTF_8); + this.value = b[0]; } } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/Ber.java b/src/java.naming/share/classes/com/sun/jndi/ldap/Ber.java index 1e8600f9ffe..e3598e49e68 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/Ber.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/Ber.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -31,6 +31,8 @@ import sun.security.util.HexDumpEncoder; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * Base class that defines common fields, constants, and debug method. * @@ -50,7 +52,7 @@ public static void dumpBER(OutputStream outStream, String tag, byte[] bytes, try { outStream.write('\n'); - outStream.write(tag.getBytes("UTF8")); + outStream.write(tag.getBytes(UTF_8)); new HexDumpEncoder().encodeBuffer( new ByteArrayInputStream(bytes, from, to), @@ -60,7 +62,7 @@ public static void dumpBER(OutputStream outStream, String tag, byte[] bytes, } catch (IOException e) { try { outStream.write( - "Ber.dumpBER(): error encountered\n".getBytes("UTF8")); + "Ber.dumpBER(): error encountered\n".getBytes(UTF_8)); } catch (IOException e2) { // ignore } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java b/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java index 9ebc18fcac4..35b8bc1b567 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -25,7 +25,8 @@ package com.sun.jndi.ldap; -import java.io.UnsupportedEncodingException; +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; /** * A BER decoder. Contains methods to parse a BER buffer. @@ -266,17 +267,9 @@ public String parseStringWithTag(int tag, boolean decodeUTF8, int rlen[]) System.arraycopy(buf, offset, buf2, 0, len); if (decodeUTF8) { - try { - retstr = new String(buf2, "UTF8"); - } catch (UnsupportedEncodingException e) { - throw new DecodeException("UTF8 not available on platform"); - } + retstr = new String(buf2, UTF_8); } else { - try { - retstr = new String(buf2, "8859_1"); - } catch (UnsupportedEncodingException e) { - throw new DecodeException("8859_1 not available on platform"); - } + retstr = new String(buf2, ISO_8859_1); } offset += len; } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/BerEncoder.java b/src/java.naming/share/classes/com/sun/jndi/ldap/BerEncoder.java index aa19de72419..ec95d2880e9 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/BerEncoder.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/BerEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -25,7 +25,8 @@ package com.sun.jndi.ldap; -import java.io.UnsupportedEncodingException; +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; /** * A BER encoder. @@ -316,19 +317,11 @@ public void encodeString(String str, int tag, boolean encodeUTF8) if (str == null) { count = 0; } else if (encodeUTF8) { - try { - bytes = str.getBytes("UTF8"); - count = bytes.length; - } catch (UnsupportedEncodingException e) { - throw new EncodeException("UTF8 not available on platform"); - } + bytes = str.getBytes(UTF_8); + count = bytes.length; } else { - try { - bytes = str.getBytes("8859_1"); - count = bytes.length; - } catch (UnsupportedEncodingException e) { - throw new EncodeException("8859_1 not available on platform"); - } + bytes = str.getBytes(ISO_8859_1); + count = bytes.length; } encodeLength(count); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/Filter.java b/src/java.naming/share/classes/com/sun/jndi/ldap/Filter.java index c4cd4db38b4..ab43fa7aa9c 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/Filter.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/Filter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -30,6 +30,9 @@ import java.io.IOException; +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * LDAP (RFC-1960) and LDAPv3 (RFC-2254) search filters. * @@ -59,9 +62,9 @@ static void encodeFilterString(BerEncoder ber, String filterStr, byte[] filter; int filterLen; if (isLdapv3) { - filter = filterStr.getBytes("UTF8"); + filter = filterStr.getBytes(UTF_8); } else { - filter = filterStr.getBytes("8859_1"); + filter = filterStr.getBytes(ISO_8859_1); } filterLen = filter.length; if (dbg) { diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java index a2490480967..3e916a5d7f8 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -39,6 +39,9 @@ import com.sun.jndi.ldap.sasl.LdapSasl; import com.sun.jndi.ldap.sasl.SaslInputStream; +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * LDAP (RFC-1777) and LDAPv3 (RFC-2251) compliant client * @@ -421,9 +424,9 @@ private static byte[] encodePassword(Object pw, boolean v3) throws IOException { if (pw instanceof String) { if (v3) { - return ((String)pw).getBytes("UTF8"); + return ((String)pw).getBytes(UTF_8); } else { - return ((String)pw).getBytes("8859_1"); + return ((String)pw).getBytes(ISO_8859_1); } } else { return (byte[])pw; @@ -1153,7 +1156,7 @@ LdapResult compare(String DN, String type, String value, Control[] reqCtls) // replace any escaped characters in the value byte[] val = isLdapv3 ? - value.getBytes("UTF8") : value.getBytes("8859_1"); + value.getBytes(UTF_8) : value.getBytes(ISO_8859_1); ber.encodeOctetString( Filter.unescapeFilterValue(val, 0, val.length), Ber.ASN_OCTET_STR); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapName.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapName.java index 9e310b3bd92..70b420f7274 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapName.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -35,6 +35,7 @@ import javax.naming.directory.Attribute; import javax.naming.directory.BasicAttributes; +import static java.nio.charset.StandardCharsets.UTF_8; /** * LdapName implements compound names for LDAP v3 as @@ -900,11 +901,7 @@ static Object unescapeValue(String val) { // Convert hex-encoded UTF-8 to 16-bit chars. byte[] utf8 = getUtf8Octets(chars, i, end); if (utf8.length > 0) { - try { - buf.append(new String(utf8, "UTF8")); - } catch (java.io.UnsupportedEncodingException e) { - // shouldn't happen - } + buf.append(new String(utf8, UTF_8)); i += utf8.length * 3 - 1; } else { throw new IllegalArgumentException( diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java index e5e04a12ee2..2a782c0e9cc 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -30,6 +30,8 @@ import javax.security.sasl.RealmChoiceCallback; import java.io.IOException; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * DefaultCallbackHandler for satisfying NameCallback and * PasswordCallback for an LDAP client. @@ -60,7 +62,7 @@ final class DefaultCallbackHandler implements CallbackHandler { passwd = ((char[])cred).clone(); } else if (cred != null) { // assume UTF-8 encoding - String orig = new String((byte[])cred, "UTF8"); + String orig = new String((byte[])cred, UTF_8); passwd = orig.toCharArray(); } } diff --git a/src/java.naming/share/classes/javax/naming/ldap/Rdn.java b/src/java.naming/share/classes/javax/naming/ldap/Rdn.java index a24bd14b683..6d2caedc4ba 100644 --- a/src/java.naming/share/classes/javax/naming/ldap/Rdn.java +++ b/src/java.naming/share/classes/javax/naming/ldap/Rdn.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -43,6 +43,8 @@ import java.io.ObjectInputStream; import java.io.IOException; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * This class represents a relative distinguished name, or RDN, which is a * component of a distinguished name as specified by @@ -643,11 +645,7 @@ public static Object unescapeValue(String val) { // Convert hex-encoded UTF-8 to 16-bit chars. byte[] utf8 = getUtf8Octets(chars, i, end); if (utf8.length > 0) { - try { - builder.append(new String(utf8, "UTF8")); - } catch (java.io.UnsupportedEncodingException e) { - // shouldn't happen - } + builder.append(new String(utf8, UTF_8)); i += utf8.length * 3 - 1; } else { // no utf8 bytes available, invalid DN diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java index de1e6742505..013dbac2b21 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,6 +36,7 @@ import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.Utils; import static java.lang.String.format; +import static java.nio.charset.StandardCharsets.UTF_8; /** * Implements chunked/fixed transfer encodings of HTTP/1.1 responses. @@ -159,7 +160,7 @@ private void debugBuffer(ByteBuffer b) { printable.get(bytes, 0, bytes.length); String msg = "============== accepted ==================\n"; try { - var str = new String(bytes, "UTF-8"); + var str = new String(bytes, UTF_8); msg += str; } catch (Exception x) { msg += x; diff --git a/src/java.rmi/share/man/rmiregistry.1 b/src/java.rmi/share/man/rmiregistry.1 index c683afa8ff9..d4c84ea58c2 100644 --- a/src/java.rmi/share/man/rmiregistry.1 +++ b/src/java.rmi/share/man/rmiregistry.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "RMIREGISTRY" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "RMIREGISTRY" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/java.scripting/share/man/jrunscript.1 b/src/java.scripting/share/man/jrunscript.1 index dfe15f0fcb2..2c7ac2d40bc 100644 --- a/src/java.scripting/share/man/jrunscript.1 +++ b/src/java.scripting/share/man/jrunscript.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JRUNSCRIPT" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JRUNSCRIPT" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java index 087e5eb2d2d..1f5f033c58b 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -53,22 +53,22 @@ private static enum S4U2Type { /** * Used by a middle server to acquire credentials on behalf of a - * client to itself using the S4U2self extension. - * @param client the client to impersonate + * user to itself using the S4U2self extension. + * @param user the user to impersonate * @param ccreds the TGT of the middle service - * @return the new creds (cname=client, sname=middle) + * @return the new creds (cname=user, sname=middle) */ - public static Credentials acquireS4U2selfCreds(PrincipalName client, + public static Credentials acquireS4U2selfCreds(PrincipalName user, Credentials ccreds) throws KrbException, IOException { if (!ccreds.isForwardable()) { throw new KrbException("S4U2self needs a FORWARDABLE ticket"); } PrincipalName sname = ccreds.getClient(); - String uRealm = client.getRealmString(); + String uRealm = user.getRealmString(); String localRealm = ccreds.getClient().getRealmString(); if (!uRealm.equals(localRealm)) { // Referrals will be required because the middle service - // and the client impersonated are on different realms. + // and the user impersonated are on different realms. if (Config.DISABLE_REFERRALS) { throw new KrbException("Cross-realm S4U2Self request not" + " possible when referrals are disabled."); @@ -87,10 +87,10 @@ public static Credentials acquireS4U2selfCreds(PrincipalName client, } Credentials creds = serviceCreds( KDCOptions.with(KDCOptions.FORWARDABLE), - ccreds, ccreds.getClient(), sname, null, - new PAData[] { + ccreds, ccreds.getClient(), sname, user, + null, new PAData[] { new PAData(Krb5.PA_FOR_USER, - new PAForUserEnc(client, + new PAForUserEnc(user, ccreds.getSessionKey()).asn1Encode()), new PAData(Krb5.PA_PAC_OPTIONS, new PaPacOptions() @@ -98,7 +98,7 @@ public static Credentials acquireS4U2selfCreds(PrincipalName client, .setClaims(true) .asn1Encode()) }, S4U2Type.SELF); - if (!creds.getClient().equals(client)) { + if (!creds.getClient().equals(user)) { throw new KrbException("S4U2self request not honored by KDC"); } if (!creds.isForwardable()) { @@ -136,7 +136,7 @@ public static Credentials acquireS4U2proxyCreds( } Credentials creds = serviceCreds(KDCOptions.with( KDCOptions.CNAME_IN_ADDL_TKT, KDCOptions.FORWARDABLE), - ccreds, ccreds.getClient(), backendPrincipal, + ccreds, ccreds.getClient(), backendPrincipal, null, new Ticket[] {second}, new PAData[] { new PAData(Krb5.PA_PAC_OPTIONS, new PaPacOptions() @@ -313,7 +313,7 @@ private static Credentials serviceCreds( throws KrbException, IOException { return serviceCreds(new KDCOptions(), ccreds, ccreds.getClient(), service, null, null, - S4U2Type.NONE); + null, S4U2Type.NONE); } /* @@ -325,13 +325,13 @@ private static Credentials serviceCreds( private static Credentials serviceCreds( KDCOptions options, Credentials asCreds, PrincipalName cname, PrincipalName sname, - Ticket[] additionalTickets, PAData[] extraPAs, - S4U2Type s4u2Type) + PrincipalName user, Ticket[] additionalTickets, + PAData[] extraPAs, S4U2Type s4u2Type) throws KrbException, IOException { if (!Config.DISABLE_REFERRALS) { try { return serviceCredsReferrals(options, asCreds, cname, sname, - s4u2Type, additionalTickets, extraPAs); + s4u2Type, user, additionalTickets, extraPAs); } catch (KrbException e) { // Server may raise an error if CANONICALIZE is true. // Try CANONICALIZE false. @@ -339,7 +339,7 @@ private static Credentials serviceCreds( } return serviceCredsSingle(options, asCreds, cname, asCreds.getClientAlias(), sname, sname, s4u2Type, - additionalTickets, extraPAs); + user, additionalTickets, extraPAs); } /* @@ -349,8 +349,8 @@ private static Credentials serviceCreds( private static Credentials serviceCredsReferrals( KDCOptions options, Credentials asCreds, PrincipalName cname, PrincipalName sname, - S4U2Type s4u2Type, Ticket[] additionalTickets, - PAData[] extraPAs) + S4U2Type s4u2Type, PrincipalName user, + Ticket[] additionalTickets, PAData[] extraPAs) throws KrbException, IOException { options = new KDCOptions(options.toBooleanArray()); options.set(KDCOptions.CANONICALIZE, true); @@ -362,12 +362,13 @@ private static Credentials serviceCredsReferrals( PrincipalName clientAlias = asCreds.getClientAlias(); while (referrals.size() <= Config.MAX_REFERRALS) { ReferralsCache.ReferralCacheEntry ref = - ReferralsCache.get(cname, sname, refSname.getRealmString()); + ReferralsCache.get(cname, sname, user, + additionalTickets, refSname.getRealmString()); String toRealm = null; if (ref == null) { creds = serviceCredsSingle(options, asCreds, cname, clientAlias, refSname, cSname, s4u2Type, - additionalTickets, extraPAs); + user, additionalTickets, extraPAs); PrincipalName server = creds.getServer(); if (!refSname.equals(server)) { String[] serverNameStrings = server.getNameStrings(); @@ -378,15 +379,9 @@ private static Credentials serviceCredsReferrals( serverNameStrings[1])) { // Server Name (sname) has the following format: // krbtgt/TO-REALM.COM@FROM-REALM.COM - if (s4u2Type == S4U2Type.NONE) { - // Do not store S4U2Self or S4U2Proxy referral - // TGTs in the cache. Caching such tickets is not - // defined in MS-SFU and may cause unexpected - // results when using them in a different context. - ReferralsCache.put(cname, sname, - server.getRealmString(), - serverNameStrings[1], creds); - } + ReferralsCache.put(cname, sname, user, + additionalTickets, server.getRealmString(), + serverNameStrings[1], creds); toRealm = serverNameStrings[1]; isReferral = true; } @@ -411,7 +406,7 @@ private static Credentials serviceCredsReferrals( } additionalTickets[0] = credsInOut[1].getTicket(); } else if (s4u2Type == S4U2Type.SELF) { - handleS4U2SelfReferral(extraPAs, asCreds, creds); + handleS4U2SelfReferral(extraPAs, user, creds); } if (referrals.contains(toRealm)) { // Referrals loop detected @@ -440,8 +435,8 @@ private static Credentials serviceCredsSingle( KDCOptions options, Credentials asCreds, PrincipalName cname, PrincipalName clientAlias, PrincipalName refSname, PrincipalName sname, - S4U2Type s4u2Type, Ticket[] additionalTickets, - PAData[] extraPAs) + S4U2Type s4u2Type, PrincipalName user, + Ticket[] additionalTickets, PAData[] extraPAs) throws KrbException, IOException { Credentials theCreds = null; boolean[] okAsDelegate = new boolean[]{true}; @@ -469,7 +464,7 @@ private static Credentials serviceCredsSingle( Credentials.printDebug(newTgt); } if (s4u2Type == S4U2Type.SELF) { - handleS4U2SelfReferral(extraPAs, asCreds, newTgt); + handleS4U2SelfReferral(extraPAs, user, newTgt); } asCreds = newTgt; cname = asCreds.getClient(); @@ -498,7 +493,7 @@ private static Credentials serviceCredsSingle( * different realm or when using a referral TGT. */ private static void handleS4U2SelfReferral(PAData[] pas, - Credentials oldCeds, Credentials newCreds) + PrincipalName user, Credentials newCreds) throws Asn1Exception, KrbException, IOException { if (DEBUG) { System.out.println(">>> Handling S4U2Self referral"); @@ -506,11 +501,8 @@ private static void handleS4U2SelfReferral(PAData[] pas, for (int i = 0; i < pas.length; i++) { PAData pa = pas[i]; if (pa.getType() == Krb5.PA_FOR_USER) { - PAForUserEnc paForUser = new PAForUserEnc( - new DerValue(pa.getValue()), - oldCeds.getSessionKey()); pas[i] = new PAData(Krb5.PA_FOR_USER, - new PAForUserEnc(paForUser.getName(), + new PAForUserEnc(user, newCreds.getSessionKey()).asn1Encode()); break; } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java index 4c2f0688eda..36d5fbc3fa0 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Red Hat, Inc. + * Copyright (c) 2019, 2021, Red Hat, Inc. * 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,14 @@ package sun.security.krb5.internal; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import sun.security.krb5.Credentials; import sun.security.krb5.PrincipalName; @@ -51,19 +53,33 @@ final class ReferralsCache { private static final class ReferralCacheKey { private PrincipalName cname; private PrincipalName sname; - ReferralCacheKey (PrincipalName cname, PrincipalName sname) { + private PrincipalName user; // S4U2Self only + private byte[] userSvcTicketEnc; // S4U2Proxy only + ReferralCacheKey (PrincipalName cname, PrincipalName sname, + PrincipalName user, Ticket userSvcTicket) { this.cname = cname; this.sname = sname; + this.user = user; + if (userSvcTicket != null && userSvcTicket.encPart != null) { + byte[] userSvcTicketEnc = userSvcTicket.encPart.getBytes(); + if (userSvcTicketEnc.length > 0) { + this.userSvcTicketEnc = userSvcTicketEnc; + } + } } public boolean equals(Object other) { if (!(other instanceof ReferralCacheKey)) return false; ReferralCacheKey that = (ReferralCacheKey)other; return cname.equals(that.cname) && - sname.equals(that.sname); + sname.equals(that.sname) && + Objects.equals(user, that.user) && + Arrays.equals(userSvcTicketEnc, that.userSvcTicketEnc); } public int hashCode() { - return cname.hashCode() + sname.hashCode(); + return cname.hashCode() + sname.hashCode() + + Objects.hashCode(user) + + Arrays.hashCode(userSvcTicketEnc); } } @@ -84,7 +100,8 @@ String getToRealm() { /* * Add a new referral entry to the cache, including: client principal, - * service principal, source KDC realm, destination KDC realm and + * service principal, user principal (S4U2Self only), client service + * ticket (S4U2Proxy only), source KDC realm, destination KDC realm and * referral TGT. * * If a loop is generated when adding the new referral, the first hop is @@ -94,8 +111,12 @@ String getToRealm() { * REALM-1.COM -> REALM-2.COM referral entry is removed from the cache. */ static synchronized void put(PrincipalName cname, PrincipalName service, - String fromRealm, String toRealm, Credentials creds) { - ReferralCacheKey k = new ReferralCacheKey(cname, service); + PrincipalName user, Ticket[] userSvcTickets, String fromRealm, + String toRealm, Credentials creds) { + Ticket userSvcTicket = (userSvcTickets != null ? + userSvcTickets[0] : null); + ReferralCacheKey k = new ReferralCacheKey(cname, service, + user, userSvcTicket); pruneExpired(k); if (creds.getEndTime().before(new Date())) { return; @@ -125,11 +146,16 @@ static synchronized void put(PrincipalName cname, PrincipalName service, /* * Obtain a referral entry from the cache given a client principal, - * service principal and a source KDC realm. + * a service principal, a user principal (S4U2Self only), a client + * service ticket (S4U2Proxy only) and a source KDC realm. */ static synchronized ReferralCacheEntry get(PrincipalName cname, - PrincipalName service, String fromRealm) { - ReferralCacheKey k = new ReferralCacheKey(cname, service); + PrincipalName service, PrincipalName user, + Ticket[] userSvcTickets, String fromRealm) { + Ticket userSvcTicket = (userSvcTickets != null ? + userSvcTickets[0] : null); + ReferralCacheKey k = new ReferralCacheKey(cname, service, + user, userSvcTicket); pruneExpired(k); Map entries = referralsMap.get(k); if (entries != null) { diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/JoinRowSetImpl.java b/src/java.sql.rowset/share/classes/com/sun/rowset/JoinRowSetImpl.java index 1da997d6905..f89ffb10099 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/JoinRowSetImpl.java +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/JoinRowSetImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -427,13 +427,7 @@ public Collection getRowSets() throws SQLException { * @see CachedRowSet#setTableName */ public String[] getRowSetNames() throws SQLException { - Object [] arr = vecTableNames.toArray(); - String []strArr = new String[arr.length]; - - for( int i = 0;i < arr.length; i++) { - strArr[i] = arr[i].toString(); - } - + String[] strArr = vecTableNames.toArray(new String[0]); return strArr; } diff --git a/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java b/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java index d5b19930c01..01f1554a6b4 100644 --- a/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java +++ b/src/java.xml/share/classes/javax/xml/catalog/Normalizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,10 +24,11 @@ */ package javax.xml.catalog; -import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * The Normalizer is responsible for normalizing Public and System Identifiers * as specified in section 6.2, 6.3 and 6.4 of the specification @@ -93,13 +94,9 @@ static String normalizePublicId(String publicId) { static String encodeURN(String publicId) { String urn = normalizePublicId(publicId); - try { - urn = URLEncoder.encode(urn, "UTF-8"); - urn = urn.replace("::", ";"); - urn = urn.replace("//", ":"); - } catch (UnsupportedEncodingException ex) { - CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex); - } + urn = URLEncoder.encode(urn, UTF_8); + urn = urn.replace("::", ";"); + urn = urn.replace("//", ":"); return Util.URN + urn; } @@ -119,13 +116,9 @@ static String decodeURN(String urn) { } else { return urn; } - try { - publicId = publicId.replace(":", "//"); - publicId = publicId.replace(";", "::"); - publicId = URLDecoder.decode(publicId, "UTF-8"); - } catch (UnsupportedEncodingException ex) { - CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex); - } + publicId = publicId.replace(":", "//"); + publicId = publicId.replace(";", "::"); + publicId = URLDecoder.decode(publicId, UTF_8); return publicId; } @@ -141,14 +134,8 @@ static String normalizeURI(String uriref) { return null; } - byte[] bytes; uriref = uriref.trim(); - try { - bytes = uriref.getBytes("UTF-8"); - } catch (UnsupportedEncodingException uee) { - // this can't happen - return uriref; - } + byte[] bytes = uriref.getBytes(UTF_8); StringBuilder newRef = new StringBuilder(bytes.length); for (int count = 0; count < bytes.length; count++) { diff --git a/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java b/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java index 397490998d8..2f6cdbbb2d3 100644 --- a/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java +++ b/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java @@ -50,165 +50,22 @@ public class AWTEventMonitor { */ public AWTEventMonitor() {} - /** - * The current component with keyboard focus. - * - * @see #getComponentWithFocus - * - * @deprecated This field is unused; to get the component with focus use the - * getComponentWithFocus method. - */ - @Deprecated(since="8", forRemoval=true) - static protected Component componentWithFocus = null; - - static private Component componentWithFocus_private = null; + static private Component componentWithFocus = null; // Low-level listeners - /** - * The current list of registered ComponentListener classes. - * - * @see #addComponentListener - * @see #removeComponentListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected ComponentListener componentListener = null; - - static private ComponentListener componentListener_private = null; - - /** - * The current list of registered ContainerListener classes. - * - * @see #addContainerListener - * @see #removeContainerListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected ContainerListener containerListener = null; - - static private ContainerListener containerListener_private = null; - - /** - * The current list of registered FocusListener classes. - * - * @see #addFocusListener - * @see #removeFocusListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected FocusListener focusListener = null; - - static private FocusListener focusListener_private = null; - - /** - * The current list of registered KeyListener classes. - * - * @see #addKeyListener - * @see #removeKeyListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected KeyListener keyListener = null; - - static private KeyListener keyListener_private = null; - - /** - * The current list of registered MouseListener classes. - * - * @see #addMouseListener - * @see #removeMouseListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected MouseListener mouseListener = null; - - static private MouseListener mouseListener_private = null; - - /** - * The current list of registered MouseMotionListener classes. - * - * @see #addMouseMotionListener - * @see #removeMouseMotionListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected MouseMotionListener mouseMotionListener = null; - - static private MouseMotionListener mouseMotionListener_private = null; - - /** - * The current list of registered WindowListener classes. - * - * @see #addWindowListener - * @see #removeWindowListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected WindowListener windowListener = null; - - static private WindowListener windowListener_private = null; - + static private ComponentListener componentListener = null; + static private ContainerListener containerListener = null; + static private FocusListener focusListener = null; + static private KeyListener keyListener = null; + static private MouseListener mouseListener = null; + static private MouseMotionListener mouseMotionListener = null; + static private WindowListener windowListener = null; // Semantic listeners - /** - * The current list of registered ActionListener classes. - * - * @see #addActionListener - * @see #removeActionListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected ActionListener actionListener = null; - - static private ActionListener actionListener_private = null; - - /** - * The current list of registered AdjustmentListener classes. - * - * @see #addAdjustmentListener - * @see #removeAdjustmentListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected AdjustmentListener adjustmentListener = null; - - static private AdjustmentListener adjustmentListener_private = null; - - /** - * The current list of registered ItemListener classes. - * - * @see #addItemListener - * @see #removeItemListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected ItemListener itemListener = null; - - static private ItemListener itemListener_private = null; - - /** - * The current list of registered TextListener classes. - * - * @see #addTextListener - * @see #removeTextListener - * - * @deprecated This field is unused. - */ - @Deprecated(since="8", forRemoval=true) - static protected TextListener textListener = null; - - static private TextListener textListener_private = null; - + static private ActionListener actionListener = null; + static private AdjustmentListener adjustmentListener = null; + static private ItemListener itemListener = null; + static private TextListener textListener = null; /** * The actual listener that is installed on the component instances. @@ -225,7 +82,7 @@ public AWTEventMonitor() {} * @return the component that has keyboard focus */ static public Component getComponentWithFocus() { - return componentWithFocus_private; + return componentWithFocus; } /* @@ -250,11 +107,11 @@ static private void checkInstallPermission() { * @see #removeComponentListener */ static public void addComponentListener(ComponentListener l) { - if (componentListener_private == null) { + if (componentListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.COMPONENT); } - componentListener_private = AWTEventMulticaster.add(componentListener_private, l); + componentListener = AWTEventMulticaster.add(componentListener, l); } /** @@ -265,8 +122,8 @@ static public void addComponentListener(ComponentListener l) { * @see #addComponentListener */ static public void removeComponentListener(ComponentListener l) { - componentListener_private = AWTEventMulticaster.remove(componentListener_private, l); - if (componentListener_private == null) { + componentListener = AWTEventMulticaster.remove(componentListener, l); + if (componentListener == null) { awtListener.removeListeners(EventID.COMPONENT); } } @@ -282,7 +139,7 @@ static public void removeComponentListener(ComponentListener l) { * @see #removeContainerListener */ static public void addContainerListener(ContainerListener l) { - containerListener_private = AWTEventMulticaster.add(containerListener_private, l); + containerListener = AWTEventMulticaster.add(containerListener, l); } /** @@ -293,7 +150,7 @@ static public void addContainerListener(ContainerListener l) { * @see #addContainerListener */ static public void removeContainerListener(ContainerListener l) { - containerListener_private = AWTEventMulticaster.remove(containerListener_private, l); + containerListener = AWTEventMulticaster.remove(containerListener, l); } /** @@ -307,7 +164,7 @@ static public void removeContainerListener(ContainerListener l) { * @see #removeFocusListener */ static public void addFocusListener(FocusListener l) { - focusListener_private = AWTEventMulticaster.add(focusListener_private, l); + focusListener = AWTEventMulticaster.add(focusListener, l); } /** @@ -318,7 +175,7 @@ static public void addFocusListener(FocusListener l) { * @see #addFocusListener */ static public void removeFocusListener(FocusListener l) { - focusListener_private = AWTEventMulticaster.remove(focusListener_private, l); + focusListener = AWTEventMulticaster.remove(focusListener, l); } /** @@ -332,11 +189,11 @@ static public void removeFocusListener(FocusListener l) { * @see #removeKeyListener */ static public void addKeyListener(KeyListener l) { - if (keyListener_private == null) { + if (keyListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.KEY); } - keyListener_private = AWTEventMulticaster.add(keyListener_private, l); + keyListener = AWTEventMulticaster.add(keyListener, l); } /** @@ -347,8 +204,8 @@ static public void addKeyListener(KeyListener l) { * @see #addKeyListener */ static public void removeKeyListener(KeyListener l) { - keyListener_private = AWTEventMulticaster.remove(keyListener_private, l); - if (keyListener_private == null) { + keyListener = AWTEventMulticaster.remove(keyListener, l); + if (keyListener == null) { awtListener.removeListeners(EventID.KEY); } } @@ -364,11 +221,11 @@ static public void removeKeyListener(KeyListener l) { * @see #removeMouseListener */ static public void addMouseListener(MouseListener l) { - if (mouseListener_private == null) { + if (mouseListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.MOUSE); } - mouseListener_private = AWTEventMulticaster.add(mouseListener_private, l); + mouseListener = AWTEventMulticaster.add(mouseListener, l); } /** @@ -379,8 +236,8 @@ static public void addMouseListener(MouseListener l) { * @see #addMouseListener */ static public void removeMouseListener(MouseListener l) { - mouseListener_private = AWTEventMulticaster.remove(mouseListener_private, l); - if (mouseListener_private == null) { + mouseListener = AWTEventMulticaster.remove(mouseListener, l); + if (mouseListener == null) { awtListener.removeListeners(EventID.MOUSE); } } @@ -396,11 +253,11 @@ static public void removeMouseListener(MouseListener l) { * @see #removeMouseMotionListener */ static public void addMouseMotionListener(MouseMotionListener l) { - if (mouseMotionListener_private == null) { + if (mouseMotionListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.MOTION); } - mouseMotionListener_private = AWTEventMulticaster.add(mouseMotionListener_private, l); + mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, l); } /** @@ -411,8 +268,8 @@ static public void addMouseMotionListener(MouseMotionListener l) { * @see #addMouseMotionListener */ static public void removeMouseMotionListener(MouseMotionListener l) { - mouseMotionListener_private = AWTEventMulticaster.remove(mouseMotionListener_private, l); - if (mouseMotionListener_private == null) { + mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, l); + if (mouseMotionListener == null) { awtListener.removeListeners(EventID.MOTION); } } @@ -428,11 +285,11 @@ static public void removeMouseMotionListener(MouseMotionListener l) { * @see #removeWindowListener */ static public void addWindowListener(WindowListener l) { - if (windowListener_private == null) { + if (windowListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.WINDOW); } - windowListener_private = AWTEventMulticaster.add(windowListener_private, l); + windowListener = AWTEventMulticaster.add(windowListener, l); } /** @@ -443,8 +300,8 @@ static public void addWindowListener(WindowListener l) { * @see #addWindowListener */ static public void removeWindowListener(WindowListener l) { - windowListener_private = AWTEventMulticaster.remove(windowListener_private, l); - if (windowListener_private == null) { + windowListener = AWTEventMulticaster.remove(windowListener, l); + if (windowListener == null) { awtListener.removeListeners(EventID.WINDOW); } } @@ -460,11 +317,11 @@ static public void removeWindowListener(WindowListener l) { * @see #removeActionListener */ static public void addActionListener(ActionListener l) { - if (actionListener_private == null) { + if (actionListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.ACTION); } - actionListener_private = AWTEventMulticaster.add(actionListener_private, l); + actionListener = AWTEventMulticaster.add(actionListener, l); } /** @@ -475,8 +332,8 @@ static public void addActionListener(ActionListener l) { * @see #addActionListener */ static public void removeActionListener(ActionListener l) { - actionListener_private = AWTEventMulticaster.remove(actionListener_private, l); - if (actionListener_private == null) { + actionListener = AWTEventMulticaster.remove(actionListener, l); + if (actionListener == null) { awtListener.removeListeners(EventID.ACTION); } } @@ -493,11 +350,11 @@ static public void removeActionListener(ActionListener l) { * @see #removeAdjustmentListener */ static public void addAdjustmentListener(AdjustmentListener l) { - if (adjustmentListener_private == null) { + if (adjustmentListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.ADJUSTMENT); } - adjustmentListener_private = AWTEventMulticaster.add(adjustmentListener_private, l); + adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l); } /** @@ -508,8 +365,8 @@ static public void addAdjustmentListener(AdjustmentListener l) { * @see #addAdjustmentListener */ static public void removeAdjustmentListener(AdjustmentListener l) { - adjustmentListener_private = AWTEventMulticaster.remove(adjustmentListener_private, l); - if (adjustmentListener_private == null) { + adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l); + if (adjustmentListener == null) { awtListener.removeListeners(EventID.ADJUSTMENT); } } @@ -525,11 +382,11 @@ static public void removeAdjustmentListener(AdjustmentListener l) { * @see #removeItemListener */ static public void addItemListener(ItemListener l) { - if (itemListener_private == null) { + if (itemListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.ITEM); } - itemListener_private = AWTEventMulticaster.add(itemListener_private, l); + itemListener = AWTEventMulticaster.add(itemListener, l); } /** @@ -540,8 +397,8 @@ static public void addItemListener(ItemListener l) { * @see #addItemListener */ static public void removeItemListener(ItemListener l) { - itemListener_private = AWTEventMulticaster.remove(itemListener_private, l); - if (itemListener_private == null) { + itemListener = AWTEventMulticaster.remove(itemListener, l); + if (itemListener == null) { awtListener.removeListeners(EventID.ITEM); } } @@ -557,11 +414,11 @@ static public void removeItemListener(ItemListener l) { * @see #removeTextListener */ static public void addTextListener(TextListener l) { - if (textListener_private == null) { + if (textListener == null) { checkInstallPermission(); awtListener.installListeners(EventID.TEXT); } - textListener_private = AWTEventMulticaster.add(textListener_private, l); + textListener = AWTEventMulticaster.add(textListener, l); } /** @@ -572,8 +429,8 @@ static public void addTextListener(TextListener l) { * @see #addTextListener */ static public void removeTextListener(TextListener l) { - textListener_private = AWTEventMulticaster.remove(textListener_private, l); - if (textListener_private == null) { + textListener = AWTEventMulticaster.remove(textListener, l); + if (textListener == null) { awtListener.removeListeners(EventID.TEXT); } } @@ -712,34 +569,34 @@ protected void installListeners(Component c) { // conditionally install low-level listeners // - if (AWTEventMonitor.componentListener_private != null) { + if (AWTEventMonitor.componentListener != null) { installListeners(c,EventID.COMPONENT); } - if (AWTEventMonitor.keyListener_private != null) { + if (AWTEventMonitor.keyListener != null) { installListeners(c,EventID.KEY); } - if (AWTEventMonitor.mouseListener_private != null) { + if (AWTEventMonitor.mouseListener != null) { installListeners(c,EventID.MOUSE); } - if (AWTEventMonitor.mouseMotionListener_private != null) { + if (AWTEventMonitor.mouseMotionListener != null) { installListeners(c,EventID.MOTION); } - if (AWTEventMonitor.windowListener_private != null) { + if (AWTEventMonitor.windowListener != null) { installListeners(c,EventID.WINDOW); } // conditionally install Semantic listeners // - if (AWTEventMonitor.actionListener_private != null) { + if (AWTEventMonitor.actionListener != null) { installListeners(c,EventID.ACTION); } - if (AWTEventMonitor.adjustmentListener_private != null) { + if (AWTEventMonitor.adjustmentListener != null) { installListeners(c,EventID.ADJUSTMENT); } - if (AWTEventMonitor.itemListener_private != null) { + if (AWTEventMonitor.itemListener != null) { installListeners(c,EventID.ITEM); } - if (AWTEventMonitor.textListener_private != null) { + if (AWTEventMonitor.textListener != null) { installListeners(c,EventID.TEXT); } } @@ -768,15 +625,15 @@ private void processFocusGained() { last instanceof JMenu) { // This is a popup with nothing in the popup // selected. The menu itself is selected. - componentWithFocus_private = last; + componentWithFocus = last; } else if (penult instanceof JPopupMenu) { // This is a popup with an item selected - componentWithFocus_private = penult; + componentWithFocus = penult; } } } else { // The focus owner has the selection. - componentWithFocus_private = focusOwner; + componentWithFocus = focusOwner; } } @@ -965,34 +822,34 @@ protected void removeListeners(Component c) { // conditionally remove low-level listeners // - if (AWTEventMonitor.componentListener_private != null) { + if (AWTEventMonitor.componentListener != null) { removeListeners(c,EventID.COMPONENT); } - if (AWTEventMonitor.keyListener_private != null) { + if (AWTEventMonitor.keyListener != null) { removeListeners(c,EventID.KEY); } - if (AWTEventMonitor.mouseListener_private != null) { + if (AWTEventMonitor.mouseListener != null) { removeListeners(c,EventID.MOUSE); } - if (AWTEventMonitor.mouseMotionListener_private != null) { + if (AWTEventMonitor.mouseMotionListener != null) { removeListeners(c,EventID.MOTION); } - if (AWTEventMonitor.windowListener_private != null) { + if (AWTEventMonitor.windowListener != null) { removeListeners(c,EventID.WINDOW); } // Remove semantic listeners // - if (AWTEventMonitor.actionListener_private != null) { + if (AWTEventMonitor.actionListener != null) { removeListeners(c,EventID.ACTION); } - if (AWTEventMonitor.adjustmentListener_private != null) { + if (AWTEventMonitor.adjustmentListener != null) { removeListeners(c,EventID.ADJUSTMENT); } - if (AWTEventMonitor.itemListener_private != null) { + if (AWTEventMonitor.itemListener != null) { removeListeners(c,EventID.ITEM); } - if (AWTEventMonitor.textListener_private != null) { + if (AWTEventMonitor.textListener != null) { removeListeners(c,EventID.TEXT); } } @@ -1168,8 +1025,8 @@ public void topLevelWindowDestroyed(Window w) { * @see AWTEventMonitor#addActionListener */ public void actionPerformed(ActionEvent e) { - if (AWTEventMonitor.actionListener_private != null) { - AWTEventMonitor.actionListener_private.actionPerformed(e); + if (AWTEventMonitor.actionListener != null) { + AWTEventMonitor.actionListener.actionPerformed(e); } } @@ -1181,8 +1038,8 @@ public void actionPerformed(ActionEvent e) { * @see AWTEventMonitor#addAdjustmentListener */ public void adjustmentValueChanged(AdjustmentEvent e) { - if (AWTEventMonitor.adjustmentListener_private != null) { - AWTEventMonitor.adjustmentListener_private.adjustmentValueChanged(e); + if (AWTEventMonitor.adjustmentListener != null) { + AWTEventMonitor.adjustmentListener.adjustmentValueChanged(e); } } @@ -1194,8 +1051,8 @@ public void adjustmentValueChanged(AdjustmentEvent e) { * @see AWTEventMonitor#addComponentListener */ public void componentHidden(ComponentEvent e) { - if (AWTEventMonitor.componentListener_private != null) { - AWTEventMonitor.componentListener_private.componentHidden(e); + if (AWTEventMonitor.componentListener != null) { + AWTEventMonitor.componentListener.componentHidden(e); } } @@ -1205,8 +1062,8 @@ public void componentHidden(ComponentEvent e) { * @see AWTEventMonitor#addComponentListener */ public void componentMoved(ComponentEvent e) { - if (AWTEventMonitor.componentListener_private != null) { - AWTEventMonitor.componentListener_private.componentMoved(e); + if (AWTEventMonitor.componentListener != null) { + AWTEventMonitor.componentListener.componentMoved(e); } } @@ -1216,8 +1073,8 @@ public void componentMoved(ComponentEvent e) { * @see AWTEventMonitor#addComponentListener */ public void componentResized(ComponentEvent e) { - if (AWTEventMonitor.componentListener_private != null) { - AWTEventMonitor.componentListener_private.componentResized(e); + if (AWTEventMonitor.componentListener != null) { + AWTEventMonitor.componentListener.componentResized(e); } } @@ -1227,8 +1084,8 @@ public void componentResized(ComponentEvent e) { * @see AWTEventMonitor#addComponentListener */ public void componentShown(ComponentEvent e) { - if (AWTEventMonitor.componentListener_private != null) { - AWTEventMonitor.componentListener_private.componentShown(e); + if (AWTEventMonitor.componentListener != null) { + AWTEventMonitor.componentListener.componentShown(e); } } @@ -1241,8 +1098,8 @@ public void componentShown(ComponentEvent e) { */ public void componentAdded(ContainerEvent e) { installListeners(e.getChild()); - if (AWTEventMonitor.containerListener_private != null) { - AWTEventMonitor.containerListener_private.componentAdded(e); + if (AWTEventMonitor.containerListener != null) { + AWTEventMonitor.containerListener.componentAdded(e); } } @@ -1253,8 +1110,8 @@ public void componentAdded(ContainerEvent e) { */ public void componentRemoved(ContainerEvent e) { removeListeners(e.getChild()); - if (AWTEventMonitor.containerListener_private != null) { - AWTEventMonitor.containerListener_private.componentRemoved(e); + if (AWTEventMonitor.containerListener != null) { + AWTEventMonitor.containerListener.componentRemoved(e); } } @@ -1266,9 +1123,9 @@ public void componentRemoved(ContainerEvent e) { * @see AWTEventMonitor#addFocusListener */ public void focusGained(FocusEvent e) { - AWTEventMonitor.componentWithFocus_private = (Component) e.getSource(); - if (AWTEventMonitor.focusListener_private != null) { - AWTEventMonitor.focusListener_private.focusGained(e); + AWTEventMonitor.componentWithFocus = (Component) e.getSource(); + if (AWTEventMonitor.focusListener != null) { + AWTEventMonitor.focusListener.focusGained(e); } } @@ -1278,9 +1135,9 @@ public void focusGained(FocusEvent e) { * @see AWTEventMonitor#addFocusListener */ public void focusLost(FocusEvent e) { - AWTEventMonitor.componentWithFocus_private = null; - if (AWTEventMonitor.focusListener_private != null) { - AWTEventMonitor.focusListener_private.focusLost(e); + AWTEventMonitor.componentWithFocus = null; + if (AWTEventMonitor.focusListener != null) { + AWTEventMonitor.focusListener.focusLost(e); } } @@ -1292,8 +1149,8 @@ public void focusLost(FocusEvent e) { * @see AWTEventMonitor#addItemListener */ public void itemStateChanged(ItemEvent e) { - if (AWTEventMonitor.itemListener_private != null) { - AWTEventMonitor.itemListener_private.itemStateChanged(e); + if (AWTEventMonitor.itemListener != null) { + AWTEventMonitor.itemListener.itemStateChanged(e); } } @@ -1305,8 +1162,8 @@ public void itemStateChanged(ItemEvent e) { * @see AWTEventMonitor#addKeyListener */ public void keyPressed(KeyEvent e) { - if (AWTEventMonitor.keyListener_private != null) { - AWTEventMonitor.keyListener_private.keyPressed(e); + if (AWTEventMonitor.keyListener != null) { + AWTEventMonitor.keyListener.keyPressed(e); } } @@ -1316,8 +1173,8 @@ public void keyPressed(KeyEvent e) { * @see AWTEventMonitor#addKeyListener */ public void keyReleased(KeyEvent e) { - if (AWTEventMonitor.keyListener_private != null) { - AWTEventMonitor.keyListener_private.keyReleased(e); + if (AWTEventMonitor.keyListener != null) { + AWTEventMonitor.keyListener.keyReleased(e); } } @@ -1327,8 +1184,8 @@ public void keyReleased(KeyEvent e) { * @see AWTEventMonitor#addKeyListener */ public void keyTyped(KeyEvent e) { - if (AWTEventMonitor.keyListener_private != null) { - AWTEventMonitor.keyListener_private.keyTyped(e); + if (AWTEventMonitor.keyListener != null) { + AWTEventMonitor.keyListener.keyTyped(e); } } @@ -1340,8 +1197,8 @@ public void keyTyped(KeyEvent e) { * @see AWTEventMonitor#addMouseListener */ public void mouseClicked(MouseEvent e) { - if (AWTEventMonitor.mouseListener_private != null) { - AWTEventMonitor.mouseListener_private.mouseClicked(e); + if (AWTEventMonitor.mouseListener != null) { + AWTEventMonitor.mouseListener.mouseClicked(e); } } @@ -1351,8 +1208,8 @@ public void mouseClicked(MouseEvent e) { * @see AWTEventMonitor#addMouseListener */ public void mouseEntered(MouseEvent e) { - if (AWTEventMonitor.mouseListener_private != null) { - AWTEventMonitor.mouseListener_private.mouseEntered(e); + if (AWTEventMonitor.mouseListener != null) { + AWTEventMonitor.mouseListener.mouseEntered(e); } } @@ -1362,8 +1219,8 @@ public void mouseEntered(MouseEvent e) { * @see AWTEventMonitor#addMouseListener */ public void mouseExited(MouseEvent e) { - if (AWTEventMonitor.mouseListener_private != null) { - AWTEventMonitor.mouseListener_private.mouseExited(e); + if (AWTEventMonitor.mouseListener != null) { + AWTEventMonitor.mouseListener.mouseExited(e); } } @@ -1373,8 +1230,8 @@ public void mouseExited(MouseEvent e) { * @see AWTEventMonitor#addMouseListener */ public void mousePressed(MouseEvent e) { - if (AWTEventMonitor.mouseListener_private != null) { - AWTEventMonitor.mouseListener_private.mousePressed(e); + if (AWTEventMonitor.mouseListener != null) { + AWTEventMonitor.mouseListener.mousePressed(e); } } @@ -1384,8 +1241,8 @@ public void mousePressed(MouseEvent e) { * @see AWTEventMonitor#addMouseListener */ public void mouseReleased(MouseEvent e) { - if (AWTEventMonitor.mouseListener_private != null) { - AWTEventMonitor.mouseListener_private.mouseReleased(e); + if (AWTEventMonitor.mouseListener != null) { + AWTEventMonitor.mouseListener.mouseReleased(e); } } @@ -1397,8 +1254,8 @@ public void mouseReleased(MouseEvent e) { * @see AWTEventMonitor#addMouseMotionListener */ public void mouseDragged(MouseEvent e) { - if (AWTEventMonitor.mouseMotionListener_private != null) { - AWTEventMonitor.mouseMotionListener_private.mouseDragged(e); + if (AWTEventMonitor.mouseMotionListener != null) { + AWTEventMonitor.mouseMotionListener.mouseDragged(e); } } @@ -1408,8 +1265,8 @@ public void mouseDragged(MouseEvent e) { * @see AWTEventMonitor#addMouseMotionListener */ public void mouseMoved(MouseEvent e) { - if (AWTEventMonitor.mouseMotionListener_private != null) { - AWTEventMonitor.mouseMotionListener_private.mouseMoved(e); + if (AWTEventMonitor.mouseMotionListener != null) { + AWTEventMonitor.mouseMotionListener.mouseMoved(e); } } @@ -1421,8 +1278,8 @@ public void mouseMoved(MouseEvent e) { * @see AWTEventMonitor#addTextListener */ public void textValueChanged(TextEvent e) { - if (AWTEventMonitor.textListener_private != null) { - AWTEventMonitor.textListener_private.textValueChanged(e); + if (AWTEventMonitor.textListener != null) { + AWTEventMonitor.textListener.textValueChanged(e); } } @@ -1434,8 +1291,8 @@ public void textValueChanged(TextEvent e) { * @see AWTEventMonitor#addWindowListener */ public void windowOpened(WindowEvent e) { - if (AWTEventMonitor.windowListener_private != null) { - AWTEventMonitor.windowListener_private.windowOpened(e); + if (AWTEventMonitor.windowListener != null) { + AWTEventMonitor.windowListener.windowOpened(e); } } @@ -1445,8 +1302,8 @@ public void windowOpened(WindowEvent e) { * @see AWTEventMonitor#addWindowListener */ public void windowClosing(WindowEvent e) { - if (AWTEventMonitor.windowListener_private != null) { - AWTEventMonitor.windowListener_private.windowClosing(e); + if (AWTEventMonitor.windowListener != null) { + AWTEventMonitor.windowListener.windowClosing(e); } } @@ -1456,8 +1313,8 @@ public void windowClosing(WindowEvent e) { * @see AWTEventMonitor#addWindowListener */ public void windowClosed(WindowEvent e) { - if (AWTEventMonitor.windowListener_private != null) { - AWTEventMonitor.windowListener_private.windowClosed(e); + if (AWTEventMonitor.windowListener != null) { + AWTEventMonitor.windowListener.windowClosed(e); } } @@ -1467,8 +1324,8 @@ public void windowClosed(WindowEvent e) { * @see AWTEventMonitor#addWindowListener */ public void windowIconified(WindowEvent e) { - if (AWTEventMonitor.windowListener_private != null) { - AWTEventMonitor.windowListener_private.windowIconified(e); + if (AWTEventMonitor.windowListener != null) { + AWTEventMonitor.windowListener.windowIconified(e); } } @@ -1478,8 +1335,8 @@ public void windowIconified(WindowEvent e) { * @see AWTEventMonitor#addWindowListener */ public void windowDeiconified(WindowEvent e) { - if (AWTEventMonitor.windowListener_private != null) { - AWTEventMonitor.windowListener_private.windowDeiconified(e); + if (AWTEventMonitor.windowListener != null) { + AWTEventMonitor.windowListener.windowDeiconified(e); } } @@ -1489,8 +1346,8 @@ public void windowDeiconified(WindowEvent e) { * @see AWTEventMonitor#addWindowListener */ public void windowActivated(WindowEvent e) { - if (AWTEventMonitor.windowListener_private != null) { - AWTEventMonitor.windowListener_private.windowActivated(e); + if (AWTEventMonitor.windowListener != null) { + AWTEventMonitor.windowListener.windowActivated(e); } } @@ -1500,8 +1357,8 @@ public void windowActivated(WindowEvent e) { * @see AWTEventMonitor#addWindowListener */ public void windowDeactivated(WindowEvent e) { - if (AWTEventMonitor.windowListener_private != null) { - AWTEventMonitor.windowListener_private.windowDeactivated(e); + if (AWTEventMonitor.windowListener != null) { + AWTEventMonitor.windowListener.windowDeactivated(e); } } } diff --git a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java index 469354aca49..33ef57dd879 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -57,7 +57,7 @@ public interface DocTreeVisitor { /** - * Visits an AttributeTree node. + * Visits an {@code AttributeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -65,7 +65,7 @@ R visitAttribute(AttributeTree node, P p); /** - * Visits an AuthorTree node. + * Visits an {@code AuthorTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -73,7 +73,7 @@ R visitAuthor(AuthorTree node, P p); /** - * Visits a CommentTree node. + * Visits a {@code CommentTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -81,7 +81,7 @@ R visitComment(CommentTree node, P p); /** - * Visits a DeprecatedTree node. + * Visits a {@code DeprecatedTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -89,7 +89,7 @@ R visitDeprecated(DeprecatedTree node, P p); /** - * Visits a DocCommentTree node. + * Visits a {@code DocCommentTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -97,7 +97,7 @@ R visitDocComment(DocCommentTree node, P p); /** - * Visits a DocRootTree node. + * Visits a {@code DocRootTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -105,7 +105,7 @@ R visitDocRoot(DocRootTree node, P p); /** - * Visits a DocTypeTree node. + * Visits a {@code DocTypeTree} node. * * @implSpec Visits the provided {@code DocTypeTree} node * by calling {@code visitOther(node, p)}. @@ -120,7 +120,7 @@ default R visitDocType(DocTypeTree node, P p) { } /** - * Visits an EndElementTree node. + * Visits an {@code EndElementTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -128,7 +128,7 @@ default R visitDocType(DocTypeTree node, P p) { R visitEndElement(EndElementTree node, P p); /** - * Visits an EntityTree node. + * Visits an {@code EntityTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -136,7 +136,7 @@ default R visitDocType(DocTypeTree node, P p) { R visitEntity(EntityTree node, P p); /** - * Visits an ErroneousTree node. + * Visits an {@code ErroneousTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -144,7 +144,7 @@ default R visitDocType(DocTypeTree node, P p) { R visitErroneous(ErroneousTree node, P p); /** - * Visits a HiddenTree node. + * Visits a {@code HiddenTree} node. * * @implSpec Visits the provided {@code HiddenTree} node * by calling {@code visitOther(node, p)}. @@ -160,7 +160,7 @@ default R visitHidden(HiddenTree node, P p) { } /** - * Visits an IdentifierTree node. + * Visits an {@code IdentifierTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -168,7 +168,7 @@ default R visitHidden(HiddenTree node, P p) { R visitIdentifier(IdentifierTree node, P p); /** - * Visits an IndexTree node. + * Visits an {@code IndexTree} node. * * @implSpec Visits the provided {@code IndexTree} node * by calling {@code visitOther(node, p)}. @@ -184,7 +184,7 @@ default R visitIndex(IndexTree node, P p) { } /** - * Visits an InheritDocTree node. + * Visits an {@code InheritDocTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -192,7 +192,7 @@ default R visitIndex(IndexTree node, P p) { R visitInheritDoc(InheritDocTree node, P p); /** - * Visits a LinkTree node. + * Visits a {@code LinkTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -200,7 +200,7 @@ default R visitIndex(IndexTree node, P p) { R visitLink(LinkTree node, P p); /** - * Visits an LiteralTree node. + * Visits an {@code LiteralTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -208,7 +208,7 @@ default R visitIndex(IndexTree node, P p) { R visitLiteral(LiteralTree node, P p); /** - * Visits a ParamTree node. + * Visits a {@code ParamTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -216,7 +216,7 @@ default R visitIndex(IndexTree node, P p) { R visitParam(ParamTree node, P p); /** - * Visits a ProvidesTree node. + * Visits a {@code ProvidesTree} node. * * @implSpec Visits the provided {@code ProvidesTree} node * by calling {@code visitOther(node, p)}. @@ -232,7 +232,7 @@ default R visitProvides(ProvidesTree node, P p) { } /** - * Visits a ReferenceTree node. + * Visits a {@code ReferenceTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -240,7 +240,7 @@ default R visitProvides(ProvidesTree node, P p) { R visitReference(ReferenceTree node, P p); /** - * Visits a ReturnTree node. + * Visits a {@code ReturnTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -248,7 +248,7 @@ default R visitProvides(ProvidesTree node, P p) { R visitReturn(ReturnTree node, P p); /** - * Visits a SeeTree node. + * Visits a {@code SeeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -256,7 +256,7 @@ default R visitProvides(ProvidesTree node, P p) { R visitSee(SeeTree node, P p); /** - * Visits a SerialTree node. + * Visits a {@code SerialTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -264,7 +264,7 @@ default R visitProvides(ProvidesTree node, P p) { R visitSerial(SerialTree node, P p); /** - * Visits a SerialDataTree node. + * Visits a {@code SerialDataTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -272,7 +272,7 @@ default R visitProvides(ProvidesTree node, P p) { R visitSerialData(SerialDataTree node, P p); /** - * Visits a SerialFieldTree node. + * Visits a {@code SerialFieldTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -280,7 +280,7 @@ default R visitProvides(ProvidesTree node, P p) { R visitSerialField(SerialFieldTree node, P p); /** - * Visits a SinceTree node. + * Visits a {@code SinceTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -288,7 +288,7 @@ default R visitProvides(ProvidesTree node, P p) { R visitSince(SinceTree node, P p); /** - * Visits a StartElementTree node. + * Visits a {@code StartElementTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -296,7 +296,7 @@ default R visitProvides(ProvidesTree node, P p) { R visitStartElement(StartElementTree node, P p); /** - * Visits a SummaryTree node. + * Visits a {@code SummaryTree} node. * * @implSpec Visits the provided {@code SummaryTree} node * by calling {@code visitOther(node, p)}. @@ -311,7 +311,7 @@ default R visitSummary(SummaryTree node, P p) { } /** - * Visits a SystemPropertyTree node. + * Visits a {@code SystemPropertyTree} node. * * @implSpec Visits the provided {@code SystemPropertyTree} node * by calling {@code visitOther(node, p)}. @@ -326,7 +326,7 @@ default R visitSystemProperty(SystemPropertyTree node, P p) { } /** - * Visits a TextTree node. + * Visits a {@code TextTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -334,7 +334,7 @@ default R visitSystemProperty(SystemPropertyTree node, P p) { R visitText(TextTree node, P p); /** - * Visits a ThrowsTree node. + * Visits a {@code ThrowsTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -342,7 +342,7 @@ default R visitSystemProperty(SystemPropertyTree node, P p) { R visitThrows(ThrowsTree node, P p); /** - * Visits an UnknownBlockTagTree node. + * Visits an {@code UnknownBlockTagTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -350,7 +350,7 @@ default R visitSystemProperty(SystemPropertyTree node, P p) { R visitUnknownBlockTag(UnknownBlockTagTree node, P p); /** - * Visits an UnknownInlineTagTree node. + * Visits an {@code UnknownInlineTagTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -358,7 +358,7 @@ default R visitSystemProperty(SystemPropertyTree node, P p) { R visitUnknownInlineTag(UnknownInlineTagTree node, P p); /** - * Visits a UsesTree node. + * Visits a {@code UsesTree} node. * * @implSpec Visits a {@code UsesTree} node * by calling {@code visitOther(node, p)}. @@ -374,7 +374,7 @@ default R visitUses(UsesTree node, P p) { } /** - * Visits a ValueTree node. + * Visits a {@code ValueTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -382,7 +382,7 @@ default R visitUses(UsesTree node, P p) { R visitValue(ValueTree node, P p); /** - * Visits a VersionTree node. + * Visits a {@code VersionTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -390,7 +390,7 @@ default R visitUses(UsesTree node, P p) { R visitVersion(VersionTree node, P p); /** - * Visits an unknown type of DocTree node. + * Visits an unknown type of {@code DocTree} node. * This can occur if the set of tags evolves and new kinds * of nodes are added to the {@code DocTree} hierarchy. * @param node the node being visited diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java index 953210b8b21..3e2d68e8253 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -60,7 +60,7 @@ */ public interface TreeVisitor { /** - * Visits an AnnotatedTypeTree node. + * Visits an {@code AnnotatedTypeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -68,7 +68,7 @@ R visitAnnotatedType(AnnotatedTypeTree node, P p); /** - * Visits an AnnotatedTree node. + * Visits an {@code AnnotatedTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -76,7 +76,7 @@ R visitAnnotation(AnnotationTree node, P p); /** - * Visits a MethodInvocationTree node. + * Visits a {@code MethodInvocationTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -84,7 +84,7 @@ R visitMethodInvocation(MethodInvocationTree node, P p); /** - * Visits an AssertTree node. + * Visits an {@code AssertTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -92,7 +92,7 @@ R visitAssert(AssertTree node, P p); /** - * Visits an AssignmentTree node. + * Visits an {@code AssignmentTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -100,7 +100,7 @@ R visitAssignment(AssignmentTree node, P p); /** - * Visits a CompoundAssignmentTree node. + * Visits a {@code CompoundAssignmentTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -108,7 +108,7 @@ R visitCompoundAssignment(CompoundAssignmentTree node, P p); /** - * Visits a BinaryTree node. + * Visits a {@code BinaryTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -116,7 +116,7 @@ R visitBinary(BinaryTree node, P p); /** - * Visits a BlockTree node. + * Visits a {@code BlockTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -124,7 +124,7 @@ R visitBlock(BlockTree node, P p); /** - * Visits a BreakTree node. + * Visits a {@code BreakTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -132,7 +132,7 @@ R visitBreak(BreakTree node, P p); /** - * Visits a CaseTree node. + * Visits a {@code CaseTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -140,7 +140,7 @@ R visitCase(CaseTree node, P p); /** - * Visits a CatchTree node. + * Visits a {@code CatchTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -148,7 +148,7 @@ R visitCatch(CatchTree node, P p); /** - * Visits a ClassTree node. + * Visits a {@code ClassTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -156,7 +156,7 @@ R visitClass(ClassTree node, P p); /** - * Visits a ConditionalExpressionTree node. + * Visits a {@code ConditionalExpressionTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -164,7 +164,7 @@ R visitConditionalExpression(ConditionalExpressionTree node, P p); /** - * Visits a ContinueTree node. + * Visits a {@code ContinueTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -172,7 +172,7 @@ R visitContinue(ContinueTree node, P p); /** - * Visits a DefaultValue node. + * Visits a {@code DefaultValue} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -180,7 +180,7 @@ R visitDefaultValue(DefaultValueTree node, P p); /** - * Visits a DoWhileTree node. + * Visits a {@code DoWhileTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -188,7 +188,7 @@ R visitDoWhileLoop(DoWhileLoopTree node, P p); /** - * Visits an ErroneousTree node. + * Visits an {@code ErroneousTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -196,7 +196,7 @@ R visitErroneous(ErroneousTree node, P p); /** - * Visits an ExpressionStatementTree node. + * Visits an {@code ExpressionStatementTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -204,7 +204,7 @@ R visitExpressionStatement(ExpressionStatementTree node, P p); /** - * Visits an EnhancedForLoopTree node. + * Visits an {@code EnhancedForLoopTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -212,7 +212,7 @@ R visitEnhancedForLoop(EnhancedForLoopTree node, P p); /** - * Visits a ForLoopTree node. + * Visits a {@code ForLoopTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -220,7 +220,7 @@ R visitForLoop(ForLoopTree node, P p); /** - * Visits an IdentifierTree node. + * Visits an {@code IdentifierTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -228,7 +228,7 @@ R visitIdentifier(IdentifierTree node, P p); /** - * Visits an IfTree node. + * Visits an {@code IfTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -236,7 +236,7 @@ R visitIf(IfTree node, P p); /** - * Visits an ImportTree node. + * Visits an {@code ImportTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -244,7 +244,7 @@ R visitImport(ImportTree node, P p); /** - * Visits an ArrayAccessTree node. + * Visits an {@code ArrayAccessTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -252,7 +252,7 @@ R visitArrayAccess(ArrayAccessTree node, P p); /** - * Visits a LabeledStatementTree node. + * Visits a {@code LabeledStatementTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -260,7 +260,7 @@ R visitLabeledStatement(LabeledStatementTree node, P p); /** - * Visits a LiteralTree node. + * Visits a {@code LiteralTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -268,7 +268,7 @@ R visitLiteral(LiteralTree node, P p); /** - * Visits an BindingPattern node. + * Visits a {@code BindingPatternTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -277,7 +277,7 @@ R visitBindingPattern(BindingPatternTree node, P p); /** - * Visits a DefaultCaseLabelTree node. + * Visits a {@code DefaultCaseLabelTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -287,7 +287,7 @@ R visitDefaultCaseLabel(DefaultCaseLabelTree node, P p); /** - * Visits a MethodTree node. + * Visits a {@code MethodTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -295,7 +295,7 @@ R visitMethod(MethodTree node, P p); /** - * Visits a ModifiersTree node. + * Visits a {@code ModifiersTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -303,7 +303,7 @@ R visitModifiers(ModifiersTree node, P p); /** - * Visits a NewArrayTree node. + * Visits a {@code NewArrayTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -311,7 +311,7 @@ R visitNewArray(NewArrayTree node, P p); /** - * Visits a GuardPatternTree node. + * Visits a {@code GuardPatternTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -321,7 +321,7 @@ R visitGuardedPattern(GuardedPatternTree node, P p); /** - * Visits a ParenthesizedPatternTree node. + * Visits a {@code ParenthesizedPatternTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -331,7 +331,7 @@ R visitParenthesizedPattern(ParenthesizedPatternTree node, P p); /** - * Visits a NewClassTree node. + * Visits a {@code NewClassTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -339,7 +339,7 @@ R visitNewClass(NewClassTree node, P p); /** - * Visits a LambdaExpressionTree node. + * Visits a {@code LambdaExpressionTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -347,7 +347,7 @@ R visitLambdaExpression(LambdaExpressionTree node, P p); /** - * Visits a PackageTree node. + * Visits a {@code PackageTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -355,7 +355,7 @@ R visitPackage(PackageTree node, P p); /** - * Visits a ParenthesizedTree node. + * Visits a {@code ParenthesizedTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -363,7 +363,7 @@ R visitParenthesized(ParenthesizedTree node, P p); /** - * Visits a ReturnTree node. + * Visits a {@code ReturnTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -371,7 +371,7 @@ R visitReturn(ReturnTree node, P p); /** - * Visits a MemberSelectTree node. + * Visits a {@code MemberSelectTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -379,7 +379,7 @@ R visitMemberSelect(MemberSelectTree node, P p); /** - * Visits a MemberReferenceTree node. + * Visits a {@code MemberReferenceTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -387,7 +387,7 @@ R visitMemberReference(MemberReferenceTree node, P p); /** - * Visits an EmptyStatementTree node. + * Visits an {@code EmptyStatementTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -395,7 +395,7 @@ R visitEmptyStatement(EmptyStatementTree node, P p); /** - * Visits a SwitchTree node. + * Visits a {@code SwitchTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -403,7 +403,7 @@ R visitSwitch(SwitchTree node, P p); /** - * Visits a SwitchExpressionTree node. + * Visits a {@code SwitchExpressionTree} node. * * @param node the node being visited * @param p a parameter value @@ -413,7 +413,7 @@ R visitSwitchExpression(SwitchExpressionTree node, P p); /** - * Visits a SynchronizedTree node. + * Visits a {@code SynchronizedTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -421,7 +421,7 @@ R visitSynchronized(SynchronizedTree node, P p); /** - * Visits a ThrowTree node. + * Visits a {@code ThrowTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -429,7 +429,7 @@ R visitThrow(ThrowTree node, P p); /** - * Visits a CompilationUnitTree node. + * Visits a {@code CompilationUnitTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -437,7 +437,7 @@ R visitCompilationUnit(CompilationUnitTree node, P p); /** - * Visits a TryTree node. + * Visits a {@code TryTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -445,7 +445,7 @@ R visitTry(TryTree node, P p); /** - * Visits a ParameterizedTypeTree node. + * Visits a {@code ParameterizedTypeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -453,7 +453,7 @@ R visitParameterizedType(ParameterizedTypeTree node, P p); /** - * Visits a UnionTypeTree node. + * Visits a {@code UnionTypeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -461,7 +461,7 @@ R visitUnionType(UnionTypeTree node, P p); /** - * Visits an IntersectionTypeTree node. + * Visits an {@code IntersectionTypeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -469,7 +469,7 @@ R visitIntersectionType(IntersectionTypeTree node, P p); /** - * Visits an ArrayTypeTree node. + * Visits an {@code ArrayTypeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -477,7 +477,7 @@ R visitArrayType(ArrayTypeTree node, P p); /** - * Visits a TypeCastTree node. + * Visits a {@code TypeCastTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -485,7 +485,7 @@ R visitTypeCast(TypeCastTree node, P p); /** - * Visits a PrimitiveTypeTree node. + * Visits a {@code PrimitiveTypeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -493,7 +493,7 @@ R visitPrimitiveType(PrimitiveTypeTree node, P p); /** - * Visits a TypeParameterTree node. + * Visits a {@code TypeParameterTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -501,7 +501,7 @@ R visitTypeParameter(TypeParameterTree node, P p); /** - * Visits an InstanceOfTree node. + * Visits an {@code InstanceOfTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -509,7 +509,7 @@ R visitInstanceOf(InstanceOfTree node, P p); /** - * Visits a UnaryTree node. + * Visits a {@code UnaryTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -517,7 +517,7 @@ R visitUnary(UnaryTree node, P p); /** - * Visits a VariableTree node. + * Visits a {@code VariableTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -525,7 +525,7 @@ R visitVariable(VariableTree node, P p); /** - * Visits a WhileLoopTree node. + * Visits a {@code WhileLoopTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -533,7 +533,7 @@ R visitWhileLoop(WhileLoopTree node, P p); /** - * Visits a WithFieldTree node. + * Visits a {@code WithFieldTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -542,6 +542,7 @@ /** * Visits a WildcardTypeTree node. + * Visits a {@code WildcardTypeTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -549,7 +550,7 @@ R visitWildcard(WildcardTree node, P p); /** - * Visits a ModuleTree node. + * Visits a {@code ModuleTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -557,7 +558,7 @@ R visitModule(ModuleTree node, P p); /** - * Visits an ExportsTree node. + * Visits an {@code ExportsTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -565,7 +566,7 @@ R visitExports(ExportsTree node, P p); /** - * Visits an OpensTree node. + * Visits an {@code OpensTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -573,7 +574,7 @@ R visitOpens(OpensTree node, P p); /** - * Visits a ProvidesTree node. + * Visits a {@code ProvidesTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -581,7 +582,7 @@ R visitProvides(ProvidesTree node, P p); /** - * Visits a RequiresTree node. + * Visits a {@code RequiresTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -589,7 +590,7 @@ R visitRequires(RequiresTree node, P p); /** - * Visits a UsesTree node. + * Visits a {@code UsesTree} node. * @param node the node being visited * @param p a parameter value * @return a result value @@ -597,7 +598,7 @@ R visitUses(UsesTree node, P p); /** - * Visits an unknown type of Tree node. + * Visits an unknown type of {@code Tree} node. * This can occur if the language evolves and new kinds * of nodes are added to the {@code Tree} hierarchy. * @param node the node being visited @@ -607,7 +608,7 @@ R visitOther(Tree node, P p); /** - * Visits a YieldTree node. + * Visits a {@code YieldTree} node. * @param node the node being visited * @param p a parameter value * @return a result value diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java b/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java index 220df8ea039..b33117bc541 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -58,10 +58,10 @@ public abstract class Trees { public Trees() {} /** - * Returns a Trees object for a given CompilationTask. - * @param task the compilation task for which to get the Trees object - * @throws IllegalArgumentException if the task does not support the Trees API. - * @return the Trees object + * Returns a {@code Trees} object for a given {@code CompilationTask}. + * @param task the compilation task for which to get the {@code Trees} object + * @throws IllegalArgumentException if the task does not support the Tree API. + * @return the {@code Trees} object */ public static Trees instance(CompilationTask task) { String taskClassName = task.getClass().getName(); @@ -72,10 +72,10 @@ public static Trees instance(CompilationTask task) { } /** - * Returns a Trees object for a given ProcessingEnvironment. - * @param env the processing environment for which to get the Trees object - * @throws IllegalArgumentException if the env does not support the Trees API. - * @return the Trees object + * Returns a {code Trees} object for a given {@code ProcessingEnvironment}. + * @param env the processing environment for which to get the {@code Trees} object + * @throws IllegalArgumentException if the env does not support the Tree API. + * @return the {@code Trees} object */ public static Trees instance(ProcessingEnvironment env) { if (!env.getClass().getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment")) @@ -102,7 +102,7 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract SourcePositions getSourcePositions(); /** - * Returns the Tree node for a given Element. + * Returns the {@code Tree} node for a given {@code Element}. * Returns {@code null} if the node can not be found. * @param element the element * @return the tree node @@ -110,7 +110,7 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract Tree getTree(Element element); /** - * Returns the ClassTree node for a given TypeElement. + * Returns the {@code ClassTree} node for a given {@code TypeElement}. * Returns {@code null} if the node can not be found. * @param element the element * @return the class tree node @@ -118,7 +118,7 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract ClassTree getTree(TypeElement element); /** - * Returns the MethodTree node for a given ExecutableElement. + * Returns the {@code MethodTree} node for a given {@code ExecutableElement}. * Returns {@code null} if the node can not be found. * @param method the executable element * @return the method tree node @@ -126,7 +126,7 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract MethodTree getTree(ExecutableElement method); /** - * Returns the Tree node for an AnnotationMirror on a given Element. + * Returns the {@code Tree} node for an {@code AnnotationMirror} on a given {@code Element}. * Returns {@code null} if the node can not be found. * @param e the element * @param a the annotation mirror @@ -135,7 +135,7 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract Tree getTree(Element e, AnnotationMirror a); /** - * Returns the Tree node for an AnnotationValue for an AnnotationMirror on a given Element. + * Returns the {@code Tree} node for an {@code AnnotationValue} for an {@code AnnotationMirror} on a given {@code Element}. * Returns {@code null} if the node can not be found. * @param e the element * @param a the annotation mirror @@ -153,7 +153,7 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract TreePath getPath(CompilationUnitTree unit, Tree node); /** - * Returns the TreePath node for a given Element. + * Returns the {@code TreePath} node for a given {@code Element}. * Returns {@code null} if the node can not be found. * @param e the element * @return the tree path @@ -161,7 +161,7 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract TreePath getPath(Element e); /** - * Returns the TreePath node for an AnnotationMirror on a given Element. + * Returns the {@code TreePath} node for an {@code AnnotationMirror} on a given {@code Element}. * Returns {@code null} if the node can not be found. * @param e the element * @param a the annotation mirror @@ -170,7 +170,7 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract TreePath getPath(Element e, AnnotationMirror a); /** - * Returns the TreePath node for an AnnotationValue for an AnnotationMirror on a given Element. + * Returns the {@code TreePath} node for an {@code AnnotationValue} for an {@code AnnotationMirror} on a given {@code Element}. * Returns {@code null} if the node can not be found. * @param e the element * @param a the annotation mirror @@ -180,35 +180,35 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract TreePath getPath(Element e, AnnotationMirror a, AnnotationValue v); /** - * Returns the Element for the Tree node identified by a given TreePath. + * Returns the {@code Element} for the {@code Tree} node identified by a given {@code TreePath}. * Returns {@code null} if the element is not available. * @param path the tree path * @return the element - * @throws IllegalArgumentException is the TreePath does not identify - * a Tree node that might have an associated Element. + * @throws IllegalArgumentException is the {@code TreePath} does not identify + * a {@code Tree} node that might have an associated {@code Element}. */ public abstract Element getElement(TreePath path); /** - * Returns the TypeMirror for the Tree node identified by a given TreePath. - * Returns {@code null} if the TypeMirror is not available. + * Returns the {@code TypeMirror} for the {@code Tree} node identified by a given {@code TreePath}. + * Returns {@code null} if the {@code TypeMirror} is not available. * @param path the tree path * @return the type mirror - * @throws IllegalArgumentException is the TreePath does not identify - * a Tree node that might have an associated TypeMirror. + * @throws IllegalArgumentException is the {@code TreePath} does not identify + * a {@code Tree} node that might have an associated {@code TypeMirror}. */ public abstract TypeMirror getTypeMirror(TreePath path); /** - * Returns the Scope for the Tree node identified by a given TreePath. - * Returns {@code null} if the Scope is not available. + * Returns the {@code Scope} for the {@code Tree} node identified by a given {@code TreePath}. + * Returns {@code null} if the {@code Scope} is not available. * @param path the tree path * @return the scope */ public abstract Scope getScope(TreePath path); /** - * Returns the doc comment, if any, for the Tree node identified by a given TreePath. + * Returns the doc comment, if any, for the {@code Tree} node identified by a given {@code TreePath}. * Returns {@code null} if no doc comment was found. * @see DocTrees#getDocCommentTree(TreePath) * @param path the tree path @@ -235,9 +235,9 @@ static Trees getJavacTrees(Class argType, Object arg) { public abstract boolean isAccessible(Scope scope, Element member, DeclaredType type); /** - * Returns the original type from the ErrorType object. + * Returns the original type from the {@code ErrorType} object. * @param errorType the errorType for which we want to get the original type - * @return the type mirror corresponding to the original type, replaced by the ErrorType + * @return the type mirror corresponding to the original type, replaced by the {@code ErrorType} */ public abstract TypeMirror getOriginalType(ErrorType errorType); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index c50064b0e04..89229cc3214 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -2267,8 +2267,7 @@ public R accept(Symbol.Visitor v, P p) { @DefinedBy(Api.LANGUAGE_MODEL) public Type getReceiverType() { - Type result = asType().getReceiverType(); - return (result == null) ? Type.noType : result; + return asType().getReceiverType(); } @DefinedBy(Api.LANGUAGE_MODEL) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java index d6e36153bb7..63dbbe9e85d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java @@ -1791,7 +1791,9 @@ public String toString() { @DefinedBy(Api.LANGUAGE_MODEL) public Type getReturnType() { return restype; } @DefinedBy(Api.LANGUAGE_MODEL) - public Type getReceiverType() { return recvtype; } + public Type getReceiverType() { + return (recvtype == null) ? Type.noType : recvtype; + } @DefinedBy(Api.LANGUAGE_MODEL) public List getThrownTypes() { return thrown; } 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 e057f2eefcc..d11f20c09ae 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 @@ -2547,7 +2547,9 @@ public void visitApply(JCMethodInvocation tree) { localEnv.info.isSelfCall = true; // Attribute arguments, yielding list of argument types. + localEnv.info.constructorArgs = true; KindSelector kind = attribArgs(KindSelector.MTH, tree.args, localEnv, argtypesBuf); + localEnv.info.constructorArgs = false; argtypes = argtypesBuf.toList(); typeargtypes = attribTypes(tree.typeargs, localEnv); @@ -4488,7 +4490,7 @@ public void visitSelect(JCFieldAccess tree) { if (env.info.isSelfCall && ((sym.name == names._this && site.tsym == env.enclClass.sym) || - sym.name == names._super)) { + sym.name == names._super && env.info.constructorArgs)) { chk.earlyRefError(tree.pos(), sym); } } else { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java index 92506febaad..966865eebd7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java @@ -53,6 +53,10 @@ public class AttrContext { */ boolean isSelfCall = false; + /** are we analyzing the arguments for a constructor invocation? + */ + boolean constructorArgs = false; + /** Are we evaluating the selector of a `super' or type name? */ boolean selectSuper = false; @@ -134,6 +138,7 @@ AttrContext dup(WriteableScope scope) { info.scope = scope; info.staticLevel = staticLevel; info.isSelfCall = isSelfCall; + info.constructorArgs = constructorArgs; info.selectSuper = selectSuper; info.pendingResolutionPhase = pendingResolutionPhase; info.lint = lint; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java index cabe50a35d8..34c834d750a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -571,6 +571,12 @@ private void addMembers(WriteableScope scope, Type type) { } } + @DefinedBy(Api.LANGUAGE_MODEL) + public TypeElement getOutermostTypeElement(Element e) { + Symbol sym = cast(Symbol.class, e); + return sym.outermostClass(); + } + /** * Returns all annotations of an element, whether * inherited or directly present. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java index f60c12ddc03..71d3f9c5307 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -553,8 +553,13 @@ public static int getStartPos(JCTree tree) { } case ERRONEOUS: { JCErroneous node = (JCErroneous)tree; - if (node.errs != null && node.errs.nonEmpty()) - return getStartPos(node.errs.head); + if (node.errs != null && node.errs.nonEmpty()) { + int pos = getStartPos(node.errs.head); + if (pos != Position.NOPOS) { + return pos; + } + } + break; } } return tree.pos; diff --git a/src/jdk.compiler/share/man/javac.1 b/src/jdk.compiler/share/man/javac.1 index 8782020547a..c2a3190193c 100644 --- a/src/jdk.compiler/share/man/javac.1 +++ b/src/jdk.compiler/share/man/javac.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVAC" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JAVAC" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP @@ -360,6 +360,11 @@ Prints a synopsis of the set of extra options. .RS .RE .TP +.B \f[CB]\-\-help\-lint\f[R] +Prints the supported keys for the \f[CB]\-Xlint\f[R] option. +.RS +.RE +.TP .B \f[CB]\-implicit:\f[R][\f[CB]none\f[R], \f[CB]class\f[R]] Specifies whether or not to generate class files for implicitly referenced files: @@ -2111,18 +2116,18 @@ For example: 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 exception. +type of annotation. For example, the following is a simple annotation processor: .RS .PP -\f[B]Source file AnnocProc.java\f[R]: +\f[B]Source file AnnoProc.java\f[R]: .IP .nf \f[CB] import\ java.util.*; import\ javax.annotation.processing.*; import\ javax.lang.model.*; -import\ javaz.lang.model.element.*; +import\ javax.lang.model.element.*; \@SupportedAnnotationTypes("NotAnno") public\ class\ AnnoProc\ extends\ AbstractProcessor\ { diff --git a/src/jdk.compiler/share/man/serialver.1 b/src/jdk.compiler/share/man/serialver.1 index c1ec3ebcee6..7781a3cbb35 100644 --- a/src/jdk.compiler/share/man/serialver.1 +++ b/src/jdk.compiler/share/man/serialver.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "SERIALVER" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "SERIALVER" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java index 1884449fedf..63e0909346e 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java @@ -234,8 +234,7 @@ private void initJFrameCache() { // after printing stack trace. exp.printStackTrace(); } - JavaVFrame[] jvframes = new JavaVFrame[tmp.size()]; - System.arraycopy(tmp.toArray(), 0, jvframes, 0, jvframes.length); + JavaVFrame[] jvframes = tmp.toArray(new JavaVFrame[0]); jframeCache.put(cur.getThreadProxy(), jvframes); proxyToThread.put(cur.getThreadProxy(), cur); } @@ -286,8 +285,7 @@ private String[] getJavaNames(ThreadProxy th, Address fp) { names.add(sb.toString()); } } - String[] res = new String[names.size()]; - System.arraycopy(names.toArray(), 0, res, 0, res.length); + String[] res = names.toArray(new String[0]); return res; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java index 55e9dc2a0fb..3f9936536a7 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -65,9 +65,7 @@ public void visit(Klass k) { } }); - Object[] tmpArray = tmp.toArray(); - klasses = new InstanceKlass[tmpArray.length]; - System.arraycopy(tmpArray, 0, klasses, 0, tmpArray.length); + klasses = tmp.toArray(new InstanceKlass[0]); Arrays.sort(klasses, new Comparator<>() { public int compare(InstanceKlass k1, InstanceKlass k2) { Symbol s1 = k1.getName(); @@ -91,9 +89,7 @@ public static InstanceKlass[] findInstanceKlasses(String namePart) { } } - Object[] tmpArray = tmp.toArray(); - InstanceKlass[] searchResult = new InstanceKlass[tmpArray.length]; - System.arraycopy(tmpArray, 0, searchResult, 0, tmpArray.length); + InstanceKlass[] searchResult = tmp.toArray(new InstanceKlass[0]); return searchResult; } diff --git a/src/jdk.hotspot.agent/share/man/jhsdb.1 b/src/jdk.hotspot.agent/share/man/jhsdb.1 index bed1f554ceb..920c92a0377 100644 --- a/src/jdk.hotspot.agent/share/man/jhsdb.1 +++ b/src/jdk.hotspot.agent/share/man/jhsdb.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. .\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. .\" .\" This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JHSDB" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JHSDB" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP @@ -31,12 +31,12 @@ analyze the content of a core dump from a crashed Java Virtual Machine .SH SYNOPSIS .PP \f[CB]jhsdb\f[R] \f[CB]clhsdb\f[R] [\f[CB]\-\-pid\f[R] \f[I]pid\f[R] | -\f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] \f[I]coredump\f[R] | -\f[CB]\-\-connect\f[R] \f[I][serverid\@]debugd\-host[:registryport][/servername]\f[R]\] +\f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] +\f[I]coredump\f[R]] .PP \f[CB]jhsdb\f[R] \f[CB]hsdb\f[R] [\f[CB]\-\-pid\f[R] \f[I]pid\f[R] | -\f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] \f[I]coredump\f[R] | -\f[CB]\-\-connect\f[R] \f[I][serverid\@]debugd\-host[:registryport][/servername]\f[R]\] +\f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] +\f[I]coredump\f[R]] .PP \f[CB]jhsdb\f[R] \f[CB]debugd\f[R] (\f[CB]\-\-pid\f[R] \f[I]pid\f[R] | \f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] @@ -44,22 +44,22 @@ analyze the content of a core dump from a crashed Java Virtual Machine .PP \f[CB]jhsdb\f[R] \f[CB]jstack\f[R] (\f[CB]\-\-pid\f[R] \f[I]pid\f[R] | \f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] \f[I]coredump\f[R] -| \f[CB]\-\-connect\f[R] \f[I][serverid\@]debugd\-host[:registryport][/servername]\f[R]) +| \f[CB]\-\-connect\f[R] \f[I][server\-id\@]debugd\-host\f[R]) [\f[I]options\f[R]] .PP \f[CB]jhsdb\f[R] \f[CB]jmap\f[R] (\f[CB]\-\-pid\f[R] \f[I]pid\f[R] | \f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] \f[I]coredump\f[R] -| \f[CB]\-\-connect\f[R] \f[I][serverid\@]debugd\-host[:registryport][/servername]\f[R]) +| \f[CB]\-\-connect\f[R] \f[I][server\-id\@]debugd\-host\f[R]) [\f[I]options\f[R]] .PP \f[CB]jhsdb\f[R] \f[CB]jinfo\f[R] (\f[CB]\-\-pid\f[R] \f[I]pid\f[R] | \f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] \f[I]coredump\f[R] -| \f[CB]\-\-connect\f[R] \f[I][serverid\@]debugd\-host[:registryport][/servername]\f[R]) +| \f[CB]\-\-connect\f[R] \f[I][server\-id\@]debugd\-host\f[R]) [\f[I]options\f[R]] .PP \f[CB]jhsdb\f[R] \f[CB]jsnap\f[R] (\f[CB]\-\-pid\f[R] \f[I]pid\f[R] | \f[CB]\-\-exe\f[R] \f[I]executable\f[R] \f[CB]\-\-core\f[R] \f[I]coredump\f[R] -| \f[CB]\-\-connect\f[R] \f[I][serverid\@]debugd\-host[:registryport][/servername]\f[R]) +| \f[CB]\-\-connect\f[R] \f[I][server\-id\@]debugd\-host\f[R]) [\f[I]options\f[R]] .TP .B \f[I]pid\f[R] @@ -81,7 +81,7 @@ The core file to which the \f[CB]jhsdb\f[R] tool should attach. .RS .RE .TP -.B \f[I][serverid\@]debugd\-host[:registryport][/servername]\f[R] +.B \f[I][server\-id\@]debugd\-host\f[R] An optional server ID and the address of the remote debug server (debugd). .RS @@ -158,10 +158,9 @@ Displays the options available for the \f[I]command\f[R]. .RE .SH OPTIONS FOR THE DEBUGD MODE .TP -.B \f[CB]\-\-serverid\f[R] \f[I]serverid\f[R] +.B \f[CB]\-\-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 server instance. -It would be added to RMI object name for server instance. +This is required if multiple debug servers are run on the same machine. .RS .RE .TP @@ -180,16 +179,6 @@ If the system property is not set, the default port 1099 is used. .RS .RE .TP -.B \f[CB]\-\-disable-registry\f[R] -Disable starting RMI registry on startup. -This option overrides the system property -\[aq]sun.jvm.hotspot.rmi.startRegistry\[aq]. -If not specified, RMI registry will be started on startup. -Otherwise it will not be started, and the already started RMI registry -will be used instead. -.RS -.RE -.TP .B \f[CB]\-\-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. @@ -199,13 +188,6 @@ If not specified, the system property is used. If the system property is not set, a system hostname is used. .RS .RE -.TP -.B \f[CB]\-\-servername\f[R] \f[I]servername\f[R] -Sets the instance name of debugd server to distinguish SA debugee. -It is used for RMI object name for server instance. -If not specified, "SARemoteDebugger" will be used. -.RS -.RE .SH OPTIONS FOR THE JINFO MODE .TP .B \f[CB]\-\-flags\f[R] diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java index 1107d5ef469..b181cf7268f 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -66,11 +66,13 @@ public enum State {IDLE, REQUEST, RESPONSE}; volatile State state; public String toString() { - String s = null; + final var sb = new StringBuilder(HttpConnection.class.getSimpleName()); if (chan != null) { - s = chan.toString(); + sb.append(" ("); + sb.append(chan); + sb.append(")"); } - return s; + return sb.toString(); } HttpConnection () { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index c7613b2ff14..7f42edf8623 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java @@ -380,6 +380,18 @@ AbstractMask bTest(int cond, return maskFactory(bits); } + /*package-private*/ + @ForceInline + static byte rotateLeft(byte a, int n) { + return (byte)(((((byte)a) & Byte.toUnsignedInt((byte)-1)) << (n & Byte.SIZE-1)) | ((((byte)a) & Byte.toUnsignedInt((byte)-1)) >>> (Byte.SIZE - (n & Byte.SIZE-1)))); + } + + /*package-private*/ + @ForceInline + static byte rotateRight(byte a, int n) { + return (byte)(((((byte)a) & Byte.toUnsignedInt((byte)-1)) >>> (n & Byte.SIZE-1)) | ((((byte)a) & Byte.toUnsignedInt((byte)-1)) << (Byte.SIZE - (n & Byte.SIZE-1)))); + } + /*package-private*/ @Override abstract ByteSpecies vspecies(); @@ -600,12 +612,7 @@ ByteVector lanewiseTemplate(VectorOperators.Binary op, // This allows the JIT to ignore some ISA details. that = that.lanewise(AND, SHIFT_MASK); } - if (op == ROR || op == ROL) { // FIXME: JIT should do this - ByteVector neg = that.lanewise(NEG); - ByteVector hi = this.lanewise(LSHL, (op == ROR) ? neg : that); - ByteVector lo = this.lanewise(LSHR, (op == ROR) ? that : neg); - return hi.lanewise(OR, lo); - } else if (op == AND_NOT) { + if (op == AND_NOT) { // FIXME: Support this in the JIT. that = that.lanewise(NOT); op = AND; @@ -646,6 +653,10 @@ opc, getClass(), byte.class, length(), v0.bOp(v1, (i, a, n) -> (byte)(a >> n)); case VECTOR_OP_URSHIFT: return (v0, v1) -> v0.bOp(v1, (i, a, n) -> (byte)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateRight(a, (int)n)); default: return null; }})); } @@ -792,11 +803,6 @@ ByteVector lanewise(VectorOperators.Binary op, assert(opKind(op, VO_SHIFT)); // As per shift specification for Java, mask the shift count. e &= SHIFT_MASK; - if (op == ROR || op == ROL) { // FIXME: JIT should do this - ByteVector hi = this.lanewise(LSHL, (op == ROR) ? -e : e); - ByteVector lo = this.lanewise(LSHR, (op == ROR) ? e : -e); - return hi.lanewise(OR, lo); - } int opc = opCode(op); return VectorSupport.broadcastInt( opc, getClass(), byte.class, length(), @@ -809,6 +815,10 @@ opc, getClass(), byte.class, length(), v.uOp((i, a) -> (byte)(a >> n)); case VECTOR_OP_URSHIFT: return (v, n) -> v.uOp((i, a) -> (byte)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v, n) -> + v.uOp((i, a) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v, n) -> + v.uOp((i, a) -> rotateRight(a, (int)n)); default: return null; }})); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index 9dadb3f7b03..4c3746b745f 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -380,6 +380,7 @@ AbstractMask bTest(int cond, return maskFactory(bits); } + /*package-private*/ @Override abstract DoubleSpecies vspecies(); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index 1841b3e0dec..7a741cd2e5e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -380,6 +380,7 @@ AbstractMask bTest(int cond, return maskFactory(bits); } + /*package-private*/ @Override abstract FloatSpecies vspecies(); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index f23cdfa1149..6fdf612a255 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java @@ -380,6 +380,18 @@ AbstractMask bTest(int cond, return maskFactory(bits); } + /*package-private*/ + @ForceInline + static int rotateLeft(int a, int n) { + return Integer.rotateLeft(a, n); + } + + /*package-private*/ + @ForceInline + static int rotateRight(int a, int n) { + return Integer.rotateRight(a, n); + } + /*package-private*/ @Override abstract IntSpecies vspecies(); @@ -600,12 +612,7 @@ IntVector lanewiseTemplate(VectorOperators.Binary op, // This allows the JIT to ignore some ISA details. that = that.lanewise(AND, SHIFT_MASK); } - if (op == ROR || op == ROL) { // FIXME: JIT should do this - IntVector neg = that.lanewise(NEG); - IntVector hi = this.lanewise(LSHL, (op == ROR) ? neg : that); - IntVector lo = this.lanewise(LSHR, (op == ROR) ? that : neg); - return hi.lanewise(OR, lo); - } else if (op == AND_NOT) { + if (op == AND_NOT) { // FIXME: Support this in the JIT. that = that.lanewise(NOT); op = AND; @@ -646,6 +653,10 @@ opc, getClass(), int.class, length(), v0.bOp(v1, (i, a, n) -> (int)(a >> n)); case VECTOR_OP_URSHIFT: return (v0, v1) -> v0.bOp(v1, (i, a, n) -> (int)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateRight(a, (int)n)); default: return null; }})); } @@ -792,11 +803,6 @@ IntVector lanewise(VectorOperators.Binary op, assert(opKind(op, VO_SHIFT)); // As per shift specification for Java, mask the shift count. e &= SHIFT_MASK; - if (op == ROR || op == ROL) { // FIXME: JIT should do this - IntVector hi = this.lanewise(LSHL, (op == ROR) ? -e : e); - IntVector lo = this.lanewise(LSHR, (op == ROR) ? e : -e); - return hi.lanewise(OR, lo); - } int opc = opCode(op); return VectorSupport.broadcastInt( opc, getClass(), int.class, length(), @@ -809,6 +815,10 @@ opc, getClass(), int.class, length(), v.uOp((i, a) -> (int)(a >> n)); case VECTOR_OP_URSHIFT: return (v, n) -> v.uOp((i, a) -> (int)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v, n) -> + v.uOp((i, a) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v, n) -> + v.uOp((i, a) -> rotateRight(a, (int)n)); default: return null; }})); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index c1c1aea390a..f5069826d44 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java @@ -380,6 +380,18 @@ AbstractMask bTest(int cond, return maskFactory(bits); } + /*package-private*/ + @ForceInline + static long rotateLeft(long a, int n) { + return Long.rotateLeft(a, n); + } + + /*package-private*/ + @ForceInline + static long rotateRight(long a, int n) { + return Long.rotateRight(a, n); + } + /*package-private*/ @Override abstract LongSpecies vspecies(); @@ -558,12 +570,7 @@ LongVector lanewiseTemplate(VectorOperators.Binary op, // This allows the JIT to ignore some ISA details. that = that.lanewise(AND, SHIFT_MASK); } - if (op == ROR || op == ROL) { // FIXME: JIT should do this - LongVector neg = that.lanewise(NEG); - LongVector hi = this.lanewise(LSHL, (op == ROR) ? neg : that); - LongVector lo = this.lanewise(LSHR, (op == ROR) ? that : neg); - return hi.lanewise(OR, lo); - } else if (op == AND_NOT) { + if (op == AND_NOT) { // FIXME: Support this in the JIT. that = that.lanewise(NOT); op = AND; @@ -604,6 +611,10 @@ opc, getClass(), long.class, length(), v0.bOp(v1, (i, a, n) -> (long)(a >> n)); case VECTOR_OP_URSHIFT: return (v0, v1) -> v0.bOp(v1, (i, a, n) -> (long)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateRight(a, (int)n)); default: return null; }})); } @@ -710,11 +721,6 @@ LongVector lanewise(VectorOperators.Binary op, assert(opKind(op, VO_SHIFT)); // As per shift specification for Java, mask the shift count. e &= SHIFT_MASK; - if (op == ROR || op == ROL) { // FIXME: JIT should do this - LongVector hi = this.lanewise(LSHL, (op == ROR) ? -e : e); - LongVector lo = this.lanewise(LSHR, (op == ROR) ? e : -e); - return hi.lanewise(OR, lo); - } int opc = opCode(op); return VectorSupport.broadcastInt( opc, getClass(), long.class, length(), @@ -727,6 +733,10 @@ opc, getClass(), long.class, length(), v.uOp((i, a) -> (long)(a >> n)); case VECTOR_OP_URSHIFT: return (v, n) -> v.uOp((i, a) -> (long)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v, n) -> + v.uOp((i, a) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v, n) -> + v.uOp((i, a) -> rotateRight(a, (int)n)); default: return null; }})); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index a2ee13e6319..a02e981e809 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -380,6 +380,18 @@ AbstractMask bTest(int cond, return maskFactory(bits); } + /*package-private*/ + @ForceInline + static short rotateLeft(short a, int n) { + return (short)(((((short)a) & Short.toUnsignedInt((short)-1)) << (n & Short.SIZE-1)) | ((((short)a) & Short.toUnsignedInt((short)-1)) >>> (Short.SIZE - (n & Short.SIZE-1)))); + } + + /*package-private*/ + @ForceInline + static short rotateRight(short a, int n) { + return (short)(((((short)a) & Short.toUnsignedInt((short)-1)) >>> (n & Short.SIZE-1)) | ((((short)a) & Short.toUnsignedInt((short)-1)) << (Short.SIZE - (n & Short.SIZE-1)))); + } + /*package-private*/ @Override abstract ShortSpecies vspecies(); @@ -600,12 +612,7 @@ ShortVector lanewiseTemplate(VectorOperators.Binary op, // This allows the JIT to ignore some ISA details. that = that.lanewise(AND, SHIFT_MASK); } - if (op == ROR || op == ROL) { // FIXME: JIT should do this - ShortVector neg = that.lanewise(NEG); - ShortVector hi = this.lanewise(LSHL, (op == ROR) ? neg : that); - ShortVector lo = this.lanewise(LSHR, (op == ROR) ? that : neg); - return hi.lanewise(OR, lo); - } else if (op == AND_NOT) { + if (op == AND_NOT) { // FIXME: Support this in the JIT. that = that.lanewise(NOT); op = AND; @@ -646,6 +653,10 @@ opc, getClass(), short.class, length(), v0.bOp(v1, (i, a, n) -> (short)(a >> n)); case VECTOR_OP_URSHIFT: return (v0, v1) -> v0.bOp(v1, (i, a, n) -> (short)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateRight(a, (int)n)); default: return null; }})); } @@ -792,11 +803,6 @@ ShortVector lanewise(VectorOperators.Binary op, assert(opKind(op, VO_SHIFT)); // As per shift specification for Java, mask the shift count. e &= SHIFT_MASK; - if (op == ROR || op == ROL) { // FIXME: JIT should do this - ShortVector hi = this.lanewise(LSHL, (op == ROR) ? -e : e); - ShortVector lo = this.lanewise(LSHR, (op == ROR) ? e : -e); - return hi.lanewise(OR, lo); - } int opc = opCode(op); return VectorSupport.broadcastInt( opc, getClass(), short.class, length(), @@ -809,6 +815,10 @@ opc, getClass(), short.class, length(), v.uOp((i, a) -> (short)(a >> n)); case VECTOR_OP_URSHIFT: return (v, n) -> v.uOp((i, a) -> (short)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v, n) -> + v.uOp((i, a) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v, n) -> + v.uOp((i, a) -> rotateRight(a, (int)n)); default: return null; }})); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java index 8622449a59e..3562a2578ef 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorOperators.java @@ -551,9 +551,9 @@ static boolean opKind(Operator op, int bit) { /** Produce {@code a>>>(n&(ESIZE*8-1))}. Integral only. */ public static final /*bitwise*/ Binary LSHR = binary("LSHR", ">>>", VectorSupport.VECTOR_OP_URSHIFT, VO_SHIFT); /** Produce {@code rotateLeft(a,n)}. Integral only. */ - public static final /*bitwise*/ Binary ROL = binary("ROL", "rotateLeft", -1 /*VectorSupport.VECTOR_OP_LROTATE*/, VO_SHIFT | VO_SPECIAL); + public static final /*bitwise*/ Binary ROL = binary("ROL", "rotateLeft", VectorSupport.VECTOR_OP_LROTATE, VO_SHIFT); /** Produce {@code rotateRight(a,n)}. Integral only. */ - public static final /*bitwise*/ Binary ROR = binary("ROR", "rotateRight", -1 /*VectorSupport.VECTOR_OP_RROTATE*/, VO_SHIFT | VO_SPECIAL); + public static final /*bitwise*/ Binary ROR = binary("ROR", "rotateRight", VectorSupport.VECTOR_OP_RROTATE, VO_SHIFT); /** Produce {@code atan2(a,b)}. See Floating only. * Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 2fb3ae856cf..860ef572d67 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -384,6 +384,28 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { return maskFactory(bits); } +#if[BITWISE] + /*package-private*/ + @ForceInline + static $type$ rotateLeft($type$ a, int n) { +#if[intOrLong] + return $Boxtype$.rotateLeft(a, n); +#else[intOrLong] + return ($type$)((((($type$)a) & $Boxtype$.toUnsignedInt(($type$)-1)) << (n & $Boxtype$.SIZE-1)) | (((($type$)a) & $Boxtype$.toUnsignedInt(($type$)-1)) >>> ($Boxtype$.SIZE - (n & $Boxtype$.SIZE-1)))); +#end[intOrLong] + } + + /*package-private*/ + @ForceInline + static $type$ rotateRight($type$ a, int n) { +#if[intOrLong] + return $Boxtype$.rotateRight(a, n); +#else[intOrLong] + return ($type$)((((($type$)a) & $Boxtype$.toUnsignedInt(($type$)-1)) >>> (n & $Boxtype$.SIZE-1)) | (((($type$)a) & $Boxtype$.toUnsignedInt(($type$)-1)) << ($Boxtype$.SIZE - (n & $Boxtype$.SIZE-1)))); +#end[intOrLong] + } +#end[BITWISE] + /*package-private*/ @Override abstract $Type$Species vspecies(); @@ -657,12 +679,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { that = that.lanewise(AND, SHIFT_MASK); } #end[!FP] - if (op == ROR || op == ROL) { // FIXME: JIT should do this - $abstractvectortype$ neg = that.lanewise(NEG); - $abstractvectortype$ hi = this.lanewise(LSHL, (op == ROR) ? neg : that); - $abstractvectortype$ lo = this.lanewise(LSHR, (op == ROR) ? that : neg); - return hi.lanewise(OR, lo); - } else if (op == AND_NOT) { + if (op == AND_NOT) { // FIXME: Support this in the JIT. that = that.lanewise(NOT); op = AND; @@ -705,6 +722,10 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { v0.bOp(v1, (i, a, n) -> ($type$)(a >> n)); case VECTOR_OP_URSHIFT: return (v0, v1) -> v0.bOp(v1, (i, a, n) -> ($type$)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v0, v1) -> + v0.bOp(v1, (i, a, n) -> rotateRight(a, (int)n)); #end[BITWISE] #if[FP] case VECTOR_OP_ATAN2: return (v0, v1) -> @@ -869,11 +890,6 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { assert(opKind(op, VO_SHIFT)); // As per shift specification for Java, mask the shift count. e &= SHIFT_MASK; - if (op == ROR || op == ROL) { // FIXME: JIT should do this - $abstractvectortype$ hi = this.lanewise(LSHL, (op == ROR) ? -e : e); - $abstractvectortype$ lo = this.lanewise(LSHR, (op == ROR) ? e : -e); - return hi.lanewise(OR, lo); - } int opc = opCode(op); return VectorSupport.broadcastInt( opc, getClass(), $type$.class, length(), @@ -886,6 +902,10 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { v.uOp((i, a) -> ($type$)(a >> n)); case VECTOR_OP_URSHIFT: return (v, n) -> v.uOp((i, a) -> ($type$)((a & LSHR_SETUP_MASK) >>> n)); + case VECTOR_OP_LROTATE: return (v, n) -> + v.uOp((i, a) -> rotateLeft(a, (int)n)); + case VECTOR_OP_RROTATE: return (v, n) -> + v.uOp((i, a) -> rotateRight(a, (int)n)); default: return null; }})); } diff --git a/src/jdk.jartool/share/man/jar.1 b/src/jdk.jartool/share/man/jar.1 index 9bbc314f9df..4a8c8f4ae66 100644 --- a/src/jdk.jartool/share/man/jar.1 +++ b/src/jdk.jartool/share/man/jar.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAR" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JAR" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jartool/share/man/jarsigner.1 b/src/jdk.jartool/share/man/jarsigner.1 index 842a9a1fb92..592a64ed836 100644 --- a/src/jdk.jartool/share/man/jarsigner.1 +++ b/src/jdk.jartool/share/man/jarsigner.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 1998, 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 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JARSIGNER" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JARSIGNER" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP @@ -554,16 +554,19 @@ See Signature File. .PP One reason the hash of the manifest file that is stored in the \f[CB]\&.SF\f[R] file header might not equal the hash of the current -manifest file is that one or more files were added to the JAR file (with -the \f[CB]jar\f[R] tool) after the signature and \f[CB]\&.SF\f[R] file were -generated. -When the \f[CB]jar\f[R] tool is used to add files, the manifest file is -changed by adding sections to it for the new files, but the -\f[CB]\&.SF\f[R] file isn\[aq]t changed. -A verification is still considered successful when none of the files -that were in the JAR file when the signature was generated have been +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[CB]jar\f[R] tool) that already contains a signature and a +\f[CB]\&.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[CB]jarsigner\f[R] tool) and a new \f[CB]\&.SF\f[R] file is created, but +the original \f[CB]\&.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 happens when the hashes in the non\-header sections of the +This is because the hashes in the non\-header sections of the \f[CB]\&.SF\f[R] file equal the hashes of the corresponding sections in the manifest file. .RE diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java index c042fa71429..40100d6fd27 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -66,9 +66,8 @@ public AbstractOverviewIndexWriter(HtmlConfiguration configuration, */ protected void addOverviewHeader(Content main) { addConfigurationTitle(main); - if (!utils.getFullBody(configuration.overviewElement).isEmpty()) { - addOverviewComment(main); - } + addOverviewComment(main); + addOverviewTags(main); } /** @@ -84,6 +83,17 @@ protected void addOverviewComment(Content htmltree) { } } + /** + * Adds the block tags provided in the file specified by the "-overview" option. + * + * @param htmlTree the content tree to which the tags will be added + */ + protected void addOverviewTags(Content htmlTree) { + if (!utils.getFullBody(configuration.overviewElement).isEmpty()) { + addTagsInfo(configuration.overviewElement, htmlTree); + } + } + /** * Generate and prints the contents in the index file. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java index 7aa0d29c8d2..118cc73afb8 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java @@ -270,9 +270,6 @@ private void buildSummary(MemberSummaryWriter writer, new DocFinder.Input(utils, member)); if (inheritedDoc.holder != null && !utils.getFirstSentenceTrees(inheritedDoc.holder).isEmpty()) { - // let the comment helper know of the overridden element - CommentHelper ch = utils.getCommentHelper(member); - ch.setOverrideElement(inheritedDoc.holder); firstSentenceTags = utils.getFirstSentenceTrees(inheritedDoc.holder); } } @@ -486,7 +483,7 @@ private void addToPropertiesMap(ExecutableElement propertyMethod, VariableElement field, ExecutableElement getter, ExecutableElement setter) { - if (field == null || builder.utils.getDocCommentTree(field) == null) { + if (field == null || !builder.utils.hasDocCommentTree(field)) { addToPropertiesMap(propertyMethod, propertyMethod); addToPropertiesMap(getter, propertyMethod); addToPropertiesMap(setter, propertyMethod); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java index 03193f4de9d..24014e99494 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java @@ -31,6 +31,7 @@ import java.util.stream.Collectors; import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -87,7 +88,6 @@ public class CommentHelper { public final TreePath path; public final DocCommentTree dcTree; public final Element element; - private Element overriddenElement; public static final String SPACER = " "; @@ -106,13 +106,6 @@ public CommentHelper(BaseConfiguration configuration, Element element, TreePath this.dcTree = dcTree; } - public void setOverrideElement(Element ove) { - if (this.element == ove) { - throw new AssertionError("cannot set given element as overridden element"); - } - overriddenElement = ove; - } - public String getTagName(DocTree dtree) { switch (dtree.getKind()) { case AUTHOR: @@ -679,22 +672,28 @@ public ReferenceTree getType(DocTree dtree) { } public DocTreePath getDocTreePath(DocTree dtree) { - if (dcTree == null && overriddenElement != null) { - // This is an inherited comment, return path from ancestor. - return configuration.utils.getCommentHelper(overriddenElement).getDocTreePath(dtree); - } else if (path == null || dcTree == null || dtree == null) { + if (dcTree == null && element instanceof ExecutableElement ee) { + return getInheritedDocTreePath(dtree, ee); + } + if (path == null || dcTree == null || dtree == null) { return null; } DocTreePath dtPath = DocTreePath.getPath(path, dcTree, dtree); - if (dtPath == null && overriddenElement != null) { + if (dtPath == null && element instanceof ExecutableElement ee) { // The overriding element has a doc tree, but it doesn't contain what we're looking for. - return configuration.utils.getCommentHelper(overriddenElement).getDocTreePath(dtree); + return getInheritedDocTreePath(dtree, ee); } return dtPath; } - public Element getOverriddenElement() { - return overriddenElement; + private DocTreePath getInheritedDocTreePath(DocTree dtree, ExecutableElement ee) { + Utils utils = configuration.utils; + DocFinder.Output inheritedDoc = + DocFinder.search(configuration, + new DocFinder.Input(utils, ee)); + return inheritedDoc == null || inheritedDoc.holder == ee + ? null + : utils.getCommentHelper(inheritedDoc.holder).getDocTreePath(dtree); } /** @@ -708,14 +707,6 @@ public String toString() { sb.append(element.getEnclosingElement()); sb.append("::"); sb.append(element); - sb.append(", overriddenElement="); - if (overriddenElement != null) { - sb.append(overriddenElement.getEnclosingElement()); - sb.append("::"); - sb.append(overriddenElement); - } else { - sb.append(""); - } sb.append('}'); return sb.toString(); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java index ef0789139cc..5a44bf7a20a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java @@ -947,13 +947,14 @@ private void computeVisibleProperties(LocalMemberTable lmt) { Map> implementMethodsFinders = new HashMap<>(); private ImplementedMethods getImplementedMethodsFinder(ExecutableElement method) { - SoftReference imf = implementMethodsFinders.get(method); - // IMF does not exist or referent was gc'ed away ? - if (imf == null || imf.get() == null) { - imf = new SoftReference<>(new ImplementedMethods(method)); - implementMethodsFinders.put(method, imf); + SoftReference ref = implementMethodsFinders.get(method); + ImplementedMethods imf = ref == null ? null : ref.get(); + // imf does not exist or was gc'ed away? + if (imf == null) { + imf = new ImplementedMethods(method); + implementMethodsFinders.put(method, new SoftReference<>(imf)); } - return imf.get(); + return imf; } public List getImplementedMethods(ExecutableElement method) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java index 9dbc47d2cd4..1a3d3cd1ced 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java @@ -184,9 +184,25 @@ public Void scan(DocCommentTree tree, TreePath p) { } } else { if (tree == null) { - if (!isSynthetic() && !isOverridingMethod) + if (isDefaultConstructor()) { + if (isNormalClass(p.getParentPath())) { + reportMissing("dc.default.constructor"); + } + } else if (!isOverridingMethod) { reportMissing("dc.missing.comment"); + } return null; + } else if (tree.getFirstSentence().isEmpty() && !isOverridingMethod) { + if (tree.getBlockTags().isEmpty()) { + reportMissing("dc.empty.comment"); + return null; + } else { + // Don't report an empty description if the comment contains @deprecated, + // because javadoc will use the content of that tag in summary tables. + if (tree.getBlockTags().stream().allMatch(t -> t.getKind() != DocTree.Kind.DEPRECATED)) { + env.messages.report(MISSING, Kind.WARNING, tree, "dc.empty.description"); + } + } } } @@ -1142,7 +1158,7 @@ private boolean isCheckedException(TypeMirror t) { || env.types.isAssignable(t, env.java_lang_RuntimeException)); } - private boolean isSynthetic() { + private boolean isDefaultConstructor() { switch (env.currElement.getKind()) { case CONSTRUCTOR: // A synthetic default constructor has the same pos as the @@ -1153,6 +1169,14 @@ private boolean isSynthetic() { return false; } + private boolean isNormalClass(TreePath p) { + return switch (p.getLeaf().getKind()) { + case ENUM, RECORD -> false; + case CLASS -> true; + default -> throw new IllegalArgumentException(p.getLeaf().getKind().name()); + }; + } + void markEnclosingTag(Flag flag) { TagStackItem top = tagStack.peek(); if (top != null) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties index df56480fcc2..091316f0e29 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 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 @@ -37,7 +37,10 @@ dc.attr.table.border.not.number = invalid value for attribute "border": {0} dc.attr.unknown = unknown attribute: {0} dc.bad.option = bad option: {0} dc.bad.value.for.option = bad value for option: {0} {1} +dc.default.constructor = use of default constructor, which does not provide a comment dc.empty = no description for @{0} +dc.empty.comment = empty comment +dc.empty.description = no initial description dc.entity.invalid = invalid entity &{0}; dc.exception.not.thrown = exception not thrown: {0} dc.exists.param = @param "{0}" has already been specified diff --git a/src/jdk.javadoc/share/man/javadoc.1 b/src/jdk.javadoc/share/man/javadoc.1 index f3a9f50a5a1..c052a4ca136 100644 --- a/src/jdk.javadoc/share/man/javadoc.1 +++ b/src/jdk.javadoc/share/man/javadoc.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVADOC" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JAVADOC" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP @@ -1095,9 +1095,9 @@ Alternately, you can use the \f[CB]\-taglet\f[R] option in place of its .B \f[CB]\-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 a colon (\f[CB]:\f[R]). -The \f[CB]javadoc\f[R] tool searches all subdirectories of the specified -paths. +them with the platform path separator (\f[CB];\f[R] on Windows; \f[CB]:\f[R] +on other platforms.) The \f[CB]javadoc\f[R] tool searches all +subdirectories of the specified paths. .RS .RE .TP diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index 914b12c63a6..c3f49607d25 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JCMD" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JCMD" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP @@ -441,6 +441,8 @@ 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 \f[CB]%p\f[R] and/or \f[CB]%t\f[R] is specified in the filename, it +expands to the JVM\[aq]s PID and the current timestamp, respectively. (STRING, no default value) .IP \[bu] 2 \f[CB]maxage\f[R]: (Optional) Length of time for dumping the flight @@ -509,6 +511,8 @@ 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 \f[CB]%p\f[R] and/or \f[CB]%t\f[R] is specified in the filename, it +expands to the JVM\[aq]s PID and the current timestamp, respectively. (STRING, no default value) .IP \[bu] 2 \f[CB]maxage\f[R]: (Optional) Maximum time to keep the recorded data on @@ -563,21 +567,25 @@ Use \f[CB]none\f[R] to start a recording without a predefined configuration file. (STRING, \f[CB]JAVA\-HOME\f[R]/lib/jfr/default.jfc) .PP -Event settings and .jfc options can also be specified using the following +Event settings and .jfc options can be specified using the following syntax: -.TP -.B \f[CB]option=\f[R]\f[I]value\f[R] -Specifies the option value to modify. To list available options, use the -JAVA_HOME/bin/jfr tool. -.TP -.B \f[CB]event-setting=\f[R]\f[I]value\f[R] -Specifies the event setting value to modify. Use the form: -#= -To add a new event setting, prefix the event name with '+'. -.PP -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. +.IP \[bu] 2 +\f[CB]option\f[R]: (Optional) Specifies the option value to modify. +To list available options, use the \f[CB]JAVA_HOME\f[R]/bin/jfr tool. +.IP \[bu] 2 +\f[CB]event\-setting\f[R]: (Optional) Specifies the event setting value to +modify. +Use the form: #= 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 .B \f[CB]JFR.stop\f[R] [\f[I]options\f[R]] @@ -596,6 +604,8 @@ If no parameters are entered, then no recording is stopped. .IP \[bu] 2 \f[CB]filename\f[R]: (Optional) Name of the file to which the recording is written when the recording is stopped. +If \f[CB]%p\f[R] and/or \f[CB]%t\f[R] 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. (STRING, no default value) .IP \[bu] 2 diff --git a/src/jdk.jcmd/share/man/jinfo.1 b/src/jdk.jcmd/share/man/jinfo.1 index 3f2797c498f..30de6c16924 100644 --- a/src/jdk.jcmd/share/man/jinfo.1 +++ b/src/jdk.jcmd/share/man/jinfo.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JINFO" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JINFO" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jmap.1 b/src/jdk.jcmd/share/man/jmap.1 index 1e0d4ac82f6..82e16d0ae20 100644 --- a/src/jdk.jcmd/share/man/jmap.1 +++ b/src/jdk.jcmd/share/man/jmap.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JMAP" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JMAP" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jps.1 b/src/jdk.jcmd/share/man/jps.1 index 48a503e5321..a6d10fe911a 100644 --- a/src/jdk.jcmd/share/man/jps.1 +++ b/src/jdk.jcmd/share/man/jps.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JPS" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JPS" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jstack.1 b/src/jdk.jcmd/share/man/jstack.1 index 578fdc7dd26..302b9e5c24a 100644 --- a/src/jdk.jcmd/share/man/jstack.1 +++ b/src/jdk.jcmd/share/man/jstack.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTACK" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JSTACK" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jstat.1 b/src/jdk.jcmd/share/man/jstat.1 index 00adb8dcb2c..9996833ece9 100644 --- a/src/jdk.jcmd/share/man/jstat.1 +++ b/src/jdk.jcmd/share/man/jstat.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTAT" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JSTAT" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jconsole/share/man/jconsole.1 b/src/jdk.jconsole/share/man/jconsole.1 index de039960088..f9e29abb1ac 100644 --- a/src/jdk.jconsole/share/man/jconsole.1 +++ b/src/jdk.jconsole/share/man/jconsole.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JCONSOLE" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JCONSOLE" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/javap.1 b/src/jdk.jdeps/share/man/javap.1 index e1982398c38..02fc77a0e15 100644 --- a/src/jdk.jdeps/share/man/javap.1 +++ b/src/jdk.jdeps/share/man/javap.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVAP" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JAVAP" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/jdeprscan.1 b/src/jdk.jdeps/share/man/jdeprscan.1 index 53db8583a54..109e97890ef 100644 --- a/src/jdk.jdeps/share/man/jdeprscan.1 +++ b/src/jdk.jdeps/share/man/jdeprscan.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDEPRSCAN" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JDEPRSCAN" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/jdeps.1 b/src/jdk.jdeps/share/man/jdeps.1 index 46056c7899e..110a314af73 100644 --- a/src/jdk.jdeps/share/man/jdeps.1 +++ b/src/jdk.jdeps/share/man/jdeps.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDEPS" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JDEPS" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdi/share/man/jdb.1 b/src/jdk.jdi/share/man/jdb.1 index edf0ac6b4af..dfac04e3e27 100644 --- a/src/jdk.jdi/share/man/jdb.1 +++ b/src/jdk.jdi/share/man/jdb.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDB" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JDB" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java index 9949ca3689e..de668a56f8d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java @@ -30,6 +30,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -191,7 +192,7 @@ protected final void print(String s) { } protected final void print(String s, Object... args) { - currentLine.append(String.format(s, args)); + currentLine.append(args.length > 0 ? String.format(s, args) : s); } protected final void println(String s, Object... args) { @@ -269,4 +270,41 @@ protected final String exampleDirectory() { return "/directory/recordings"; } } + + static String expandFilename(String filename) { + if (filename == null || filename.indexOf('%') == -1) { + return filename; + } + + String pid = null; + String time = null; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < filename.length(); i++) { + char c = filename.charAt(i); + if (c == '%' && i < filename.length() - 1) { + char nc = filename.charAt(i + 1); + if (nc == '%') { // %% ==> % + sb.append('%'); + i++; + } else if (nc == 'p') { + if (pid == null) { + pid = JVM.getJVM().getPid(); + } + sb.append(pid); + i++; + } else if (nc == 't') { + if (time == null) { + time = Utils.formatDateTime(LocalDateTime.now()); + } + sb.append(time); + i++; + } else { + sb.append('%'); + } + } else { + sb.append(c); + } + } + return sb.toString(); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java index 5c910a87376..acd3389fc2c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java @@ -55,7 +55,7 @@ final class DCmdDump extends AbstractDCmd { public void execute(ArgumentParser parser) throws DCmdException { parser.checkUnknownArguments(); String name = parser.getOption("name"); - String filename = parser.getOption("filename"); + String filename = expandFilename(parser.getOption("filename")); Long maxAge = parser.getOption("maxage"); Long maxSize = parser.getOption("maxsize"); String begin = parser.getOption("begin"); @@ -232,6 +232,10 @@ public String[] printHelp() { case, the filename is generated from the PID and the current date in the specified directory. (STRING, no default value) + Note: If a filename is given, '%%p' in the filename will be + replaced by the PID, and '%%t' will be replaced by the time in + 'yyyy_MM_dd_HH_mm_ss' format. + 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) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java index 56e25a3e7ea..6a08a651338 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java @@ -76,7 +76,7 @@ public void execute(ArgumentParser parser) throws DCmdException { Long delay = parser.getOption("delay"); Long duration = parser.getOption("duration"); Boolean disk = parser.getOption("disk"); - String path = parser.getOption("filename"); + String path = expandFilename(parser.getOption("filename")); Long maxAge = parser.getOption("maxage"); Long maxSize = parser.getOption("maxsize"); Long flush = parser.getOption("flush-interval"); @@ -339,6 +339,10 @@ Virtual Machine (JVM) shuts down. If set to 'true' and no value generated from the PID and the current date in the specified directory. (STRING, no default value) + Note: If a filename is given, '%%p' in the filename will be + replaced by the PID, and '%%t' will be replaced by the time in + 'yyyy_MM_dd_HH_mm_ss' format. + 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' diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java index d567fc4addb..4e7e935fb21 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java @@ -44,7 +44,7 @@ final class DCmdStop extends AbstractDCmd { protected void execute(ArgumentParser parser) throws DCmdException { parser.checkUnknownArguments(); String name = parser.getOption("name"); - String filename = parser.getOption("filename"); + String filename = expandFilename(parser.getOption("filename")); try { Recording recording = findRecording(name); WriteableUserPath path = PrivateAccess.getInstance().getPlatformRecording(recording).getDestination(); @@ -82,6 +82,9 @@ public String[] printHelp() { recording is stopped. If no path is provided, the data from the recording is discarded. (STRING, no default value) + Note: If a path is given, '%%p' in the path will be replaced by the PID, + and '%%t' will be replaced by the time in 'yyyy_MM_dd_HH_mm_ss' format. + name Name of the recording (STRING, no default value) Options must be specified using the or = syntax. diff --git a/src/jdk.jfr/share/man/jfr.1 b/src/jdk.jfr/share/man/jfr.1 index cb63d227d6a..27e4e630dc1 100644 --- a/src/jdk.jfr/share/man/jfr.1 +++ b/src/jdk.jfr/share/man/jfr.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JFR" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JFR" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jlink/share/man/jlink.1 b/src/jdk.jlink/share/man/jlink.1 index 9fa2785fef6..f5324309efc 100644 --- a/src/jdk.jlink/share/man/jlink.1 +++ b/src/jdk.jlink/share/man/jlink.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JLINK" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JLINK" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jlink/share/man/jmod.1 b/src/jdk.jlink/share/man/jmod.1 index b512895990b..16f595782a5 100644 --- a/src/jdk.jlink/share/man/jmod.1 +++ b/src/jdk.jlink/share/man/jmod.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JMOD" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JMOD" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java index ae10e64abde..9d79baaa22b 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java @@ -35,6 +35,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.MAIN_CLASS; import static jdk.jpackage.internal.StandardBundlerParam.VERBOSE; import static jdk.jpackage.internal.StandardBundlerParam.VERSION; +import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE; public class MacAppBundler extends AppImageBundler { public MacAppBundler() { @@ -125,7 +126,7 @@ private static void doValidate(Map params) } // reject explicitly set sign to true and no valid signature key - if (Optional.ofNullable(MacAppImageBuilder. + if (Optional.ofNullable( SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) { String signingIdentity = DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params); diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java index 06af1ed2db0..f1eed5f5f15 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -66,6 +66,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE; import static jdk.jpackage.internal.StandardBundlerParam.VERSION; import static jdk.jpackage.internal.StandardBundlerParam.ADD_LAUNCHERS; +import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE; public class MacAppImageBuilder extends AbstractAppImageBuilder { @@ -143,16 +144,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder { }, (s, p) -> Path.of(s)); - public static final StandardBundlerParam SIGN_BUNDLE = - new StandardBundlerParam<>( - Arguments.CLIOptions.MAC_SIGN.getId(), - Boolean.class, - params -> false, - // valueOf(null) is false, we actually do want null in some cases - (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ? - null : Boolean.valueOf(s) - ); - public static final StandardBundlerParam APP_STORE = new StandardBundlerParam<>( Arguments.CLIOptions.MAC_APP_STORE.getId(), @@ -863,5 +854,4 @@ private static String extractBundleIdentifier(Map params) { return null; } - } 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 8e1bbfc5883..28eee6bdc4e 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java @@ -34,6 +34,7 @@ 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; @@ -41,6 +42,7 @@ 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; public abstract class MacBaseInstallerBundler extends AbstractBundler { @@ -134,6 +136,20 @@ protected void validateAppImageAndBundeler( I18N.getString( "message.app-image-requires-app-name.advice")); } + if (Optional.ofNullable( + SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) { + // if signing bundle with app-image, warn user if app-image + // is not allready signed. + try { + if (!(AppImageFile.load(applicationImage).isSigned())) { + Log.info(MessageFormat.format(I18N.getString( + "warning.unsigned.app.image"), getID())); + } + } catch (IOException ioe) { + // Ignore - In case of a forign or tampered with app-image, + // user is notified of this when the name is extracted. + } + } } else { appImageBundler.validate(params); } 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 2d436c244dc..df9755b08dd 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java @@ -46,6 +46,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME; import static jdk.jpackage.internal.StandardBundlerParam.LICENSE_FILE; import static jdk.jpackage.internal.StandardBundlerParam.VERSION; +import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE; import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN; import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER; import static jdk.jpackage.internal.MacAppImageBuilder.APP_STORE; @@ -499,7 +500,7 @@ private Path createPKG(Map params, commandLine.add(CONFIG_ROOT.fetchFrom(params).toAbsolutePath().toString()); // maybe sign - if (Optional.ofNullable(MacAppImageBuilder. + if (Optional.ofNullable( SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) { if (Platform.getMajorVersion() > 10 || (Platform.getMajorVersion() == 10 && @@ -603,7 +604,7 @@ public boolean validate(Map params) } // reject explicitly set sign to true and no valid signature key - if (Optional.ofNullable(MacAppImageBuilder. + if (Optional.ofNullable( SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) { String signingIdentity = DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params); diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties index 71075354542..23a4f9d0437 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 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 @@ -88,3 +88,4 @@ message.preparing-distribution-dist=Preparing distribution.dist: {0}. message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool. message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue. message.install-dir-ignored=Warning: "--install-dir" is not supported by DMG and will be default to /Applications. +warning.unsigned.app.image=Warning: Using unsigned app-image to build signed {0}. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties index 08cd0819495..d9da226ec92 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties @@ -87,3 +87,4 @@ message.preparing-distribution-dist=distribution.dist\u3092\u6E96\u5099\u3057\u3 message.signing.pkg=\u8B66\u544A: PKG\u3078\u306E\u7F72\u540D\u306E\u5834\u5408\u3001\u300C\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u30FB\u30A2\u30AF\u30BB\u30B9\u300D\u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u8A3C\u660E\u66F8\u306B\u300C\u5E38\u306B\u4FE1\u983C\u3059\u308B\u300D\u3092\u8A2D\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 message.setfile.dmg='SetFile'\u30E6\u30FC\u30C6\u30A3\u30EA\u30C6\u30A3\u304C\u898B\u3064\u304B\u3089\u306A\u3044\u305F\u3081\u3001DMG\u30D5\u30A1\u30A4\u30EB\u3067\u306E\u30AB\u30B9\u30BF\u30E0\u30FB\u30A2\u30A4\u30B3\u30F3\u306E\u8A2D\u5B9A\u304C\u30B9\u30AD\u30C3\u30D7\u3055\u308C\u307E\u3057\u305F\u3002Xcode\u3068\u30B3\u30DE\u30F3\u30C9\u30FB\u30E9\u30A4\u30F3\u30FB\u30C4\u30FC\u30EB\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3059\u308B\u3068\u3001\u3053\u306E\u554F\u984C\u306F\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002 message.install-dir-ignored=Warning: "--install-dir" is not supported by DMG and will be default to /Applications. +warning.unsigned.app.image=Warning: Using unsigned app-image to build signed {0}. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties index c2bfdf96963..d6f47a7bc85 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties @@ -87,3 +87,4 @@ message.preparing-distribution-dist=\u6B63\u5728\u51C6\u5907 distribution.dist: message.signing.pkg=\u8B66\u544A\uFF1A\u8981\u5BF9 PKG \u8FDB\u884C\u7B7E\u540D\uFF0C\u53EF\u80FD\u9700\u8981\u4F7F\u7528\u201C\u5BC6\u94A5\u94FE\u8BBF\u95EE\u201D\u5DE5\u5177\u4E3A\u8BC1\u4E66\u8BBE\u7F6E\u201C\u59CB\u7EC8\u4FE1\u4EFB\u201D\u3002 message.setfile.dmg=\u7531\u4E8E\u672A\u627E\u5230 'SetFile' \u5B9E\u7528\u7A0B\u5E8F\uFF0C\u8DF3\u8FC7\u4E86\u9488\u5BF9 DMG \u6587\u4EF6\u8BBE\u7F6E\u5B9A\u5236\u56FE\u6807\u7684\u64CD\u4F5C\u3002\u5B89\u88C5\u5E26\u547D\u4EE4\u884C\u5DE5\u5177\u7684 Xcode \u5E94\u80FD\u89E3\u51B3\u6B64\u95EE\u9898\u3002 message.install-dir-ignored=Warning: "--install-dir" is not supported by DMG and will be default to /Applications. +warning.unsigned.app.image=Warning: Using unsigned app-image to build signed {0}. 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 c9d293eb49d..647722f0df2 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java @@ -50,6 +50,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME; import static jdk.jpackage.internal.StandardBundlerParam.SHORTCUT_HINT; import static jdk.jpackage.internal.StandardBundlerParam.MENU_HINT; +import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE; public class AppImageFile { @@ -58,6 +59,7 @@ public class AppImageFile { private final String creatorPlatform; private final String launcherName; private final List addLauncherInfos; + private final boolean signed; private static final String FILENAME = ".jpackage.xml"; @@ -67,15 +69,16 @@ public class AppImageFile { private AppImageFile() { - this(null, null, null, null); + this(null, null, null, null, null); } private AppImageFile(String launcherName, List launcherInfos, - String creatorVersion, String creatorPlatform) { + String creatorVersion, String creatorPlatform, String signedStr) { this.launcherName = launcherName; this.addLauncherInfos = launcherInfos; this.creatorVersion = creatorVersion; this.creatorPlatform = creatorPlatform; + this.signed = "true".equals(signedStr); } /** @@ -94,6 +97,10 @@ String getLauncherName() { return launcherName; } + boolean isSigned() { + return signed; + } + void verifyCompatible() throws ConfigException { // Just do nothing for now. } @@ -129,6 +136,10 @@ static void save(Path appImageDir, Map params) xml.writeCharacters(APP_NAME.fetchFrom(params)); xml.writeEndElement(); + xml.writeStartElement("signed"); + xml.writeCharacters(SIGN_BUNDLE.fetchFrom(params).toString()); + xml.writeEndElement(); + List> addLaunchers = ADD_LAUNCHERS.fetchFrom(params); @@ -171,6 +182,9 @@ static AppImageFile load(Path appImageDir) throws IOException { String version = xpathQueryNullable(xPath, "/jpackage-state/@version", doc); + String signedStr = xpathQueryNullable(xPath, + "/jpackage-state/@signed", doc); + NodeList launcherNodes = (NodeList) xPath.evaluate( "/jpackage-state/add-launcher", doc, XPathConstants.NODESET); @@ -187,7 +201,7 @@ static AppImageFile load(Path appImageDir) throws IOException { } AppImageFile file = new AppImageFile( - mainLauncher, launcherInfos, version, platform); + mainLauncher, launcherInfos, version, platform, signedStr); if (!file.isValid()) { file = new AppImageFile(); } 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 c61e1c22b67..a097d5f01f8 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java @@ -485,6 +485,16 @@ private static Path findPathOfModule( List modulePath, String moduleName) (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(","))) ); + static final StandardBundlerParam SIGN_BUNDLE = + new StandardBundlerParam<>( + Arguments.CLIOptions.MAC_SIGN.getId(), + Boolean.class, + params -> false, + (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ? + null : Boolean.valueOf(s) + ); + + static boolean isRuntimeInstaller(Map params) { if (params.containsKey(MODULE.getID()) || params.containsKey(MAIN_JAR.getID()) || diff --git a/src/jdk.jpackage/share/man/jpackage.1 b/src/jdk.jpackage/share/man/jpackage.1 index b8ea1ae09d4..2b85c96cb46 100644 --- a/src/jdk.jpackage/share/man/jpackage.1 +++ b/src/jdk.jpackage/share/man/jpackage.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 2018, 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 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JPACKAGE" "1" "2019" "JDK 17\-ea" "JDK Commands" +.TH "JPACKAGE" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP @@ -50,7 +50,7 @@ customized in various ways. .SS Generic Options: .TP .B \f[CB]\@\f[R]\f[I]filename\f[R] -Read options and/or mode from a file. +Read options from a file. .RS .PP This option can be used multiple times. @@ -68,17 +68,17 @@ be created. .RE .TP .B \f[CB]\-\-app\-version\f[R] -Version of the application and/or package` +Version of the application and/or package .RS .RE .TP .B \f[CB]\-\-copyright\f[R] -Copyright for the application. +Copyright for the application .RS .RE .TP .B \f[CB]\-\-description\f[R] -Description of the application. +Description of the application .RS .RE .TP @@ -88,8 +88,14 @@ for the current platform to the output stream, and exit. .RS .RE .TP +.B \f[CB]\-\-icon\f[R] +Path of the icon of the application package (absolute path or relative +to the current directory) +.RS +.RE +.TP .B \f[CB]\-\-name\f[R] or \f[CB]\-n\f[R] -Name of the application and/or package. +Name of the application and/or package .RS .RE .TP @@ -101,9 +107,9 @@ Defaults to the current working directory. (absolute path or relative to the current directory). .RE .TP -.B \f[CB]\-\-temp\f[R] +.B \f[CB]\-\-temp\f[R] Path of a new or empty directory used to create temporary files -(absolute path or relative to the current directory). +(absolute path or relative to the current directory) .RS .PP If specified, the temp dir will not be removed upon the task completion @@ -114,7 +120,7 @@ the task completion. .RE .TP .B \f[CB]\-\-vendor\f[R] -Vendor of the application. +Vendor of the application .RS .RE .TP @@ -130,7 +136,7 @@ Print the product version to the output stream and exit. .SS Options for creating the runtime image: .TP .B \f[CB]\-\-add\-modules\f[R] [\f[CB],\f[R]...] -A comma (",") separated list of modules to add. +A comma (",") separated list of modules to add .RS .PP This module list, along with the main module (if specified) will be @@ -143,7 +149,7 @@ This option can be used multiple times. .RE .TP .B \f[CB]\-\-module\-path\f[R] or \f[CB]\-p\f[R] ... -A File.pathSeparator separated list of paths. +A File.pathSeparator separated list of paths .RS .PP Each path is either a directory of modules or the path to a modular jar, @@ -162,27 +168,19 @@ If not specified, defaults to "\-\-strip\-native\-commands This option can be used multiple times. .RE .TP -.B \f[CB]\-\-runtime\-image\f[R] +.B \f[CB]\-\-runtime\-image\f[R] Path of the predefined runtime image that will be copied into the -application image (absolute path or relative to the current directory). +application image (absolute path or relative to the current directory) .RS .PP If \-\-runtime\-image is not specified, jpackage will run jlink to -create the runtime image using options: \-\-strip\-debug, -\-\-no\-header\-files, \-\-no\-man\-pages, and -\-\-strip\-native\-commands. +create the runtime image using options specified by \-\-jlink\-options. .RE .SS Options for creating the application image: .TP -.B \f[CB]\-\-icon\f[R] -Path of the icon of the application bundle (absolute path or relative to -the current directory). -.RS -.RE -.TP .B \f[CB]\-\-input\f[R] or \f[CB]\-i\f[R] Path of the input directory that contains the files to be packaged -(absolute path or relative to the current directory). +(absolute path or relative to the current directory) .RS .PP All files in the input directory will be packaged into the application @@ -192,13 +190,12 @@ image. .TP .B \f[CB]\-\-add\-launcher\f[R] = 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). +of key, value pairs (absolute path or relative to the current directory) .RS .PP -The keys "module", "add\-modules", "main\-jar", "main\-class", -"arguments", "java\-options", "app\-version", "icon", and "win\-console" -can be used. +The keys "module", "main\-jar", "main\-class", "arguments", +"java\-options", "app\-version", "icon", "linux\-app\-category", +"linux\-app\-release", and "win\-console" can be used. .PP These options are added to, or used to overwrite, the original command line options to build an additional alternative launcher. @@ -211,21 +208,21 @@ launchers. .TP .B \f[CB]\-\-arguments\f[R]
Command line arguments to pass to the main class if no command line -arguments are given to the launcher. +arguments are given to the launcher .RS .PP This option can be used multiple times. .RE .TP .B \f[CB]\-\-java\-options\f[R] -Options to pass to the Java runtime. +Options to pass to the Java runtime .RS .PP This option can be used multiple times. .RE .TP .B \f[CB]\-\-main\-class\f[R] -Qualified name of the application main class to execute. +Qualified name of the application main class to execute .RS .PP This option can only be used if \-\-main\-jar is specified. @@ -233,17 +230,18 @@ This option can only be used if \-\-main\-jar is specified. .TP .B \f[CB]\-\-main\-jar\f[R]
The main JAR of the application; containing the main class (specified as -a path relative to the input path). +a path relative to the input path) .RS .PP Either \-\-module or \-\-main\-jar option can be specified but not both. .RE .TP .B \f[CB]\-\-module\f[R] or \f[CB]\-m\f[R] /
] -The main module (and optionally main class) of the application This -module must be located on the module path. +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. @@ -259,7 +257,7 @@ application which requires console interactions .SS macOS platform options (available only when running on macOS): .TP .B \f[CB]\-\-mac\-package\-identifier\f[R] -An identifier that uniquely identifies the application for macOSX. +An identifier that uniquely identifies the application for macOS .RS .PP Defaults to the the main class name. @@ -269,7 +267,7 @@ characters. .RE .TP .B \f[CB]\-\-mac\-package\-name\f[R] -Name of the application as it appears in the Menu Bar. +Name of the application as it appears in the Menu Bar .RS .PP This can be different from the application name. @@ -279,10 +277,10 @@ displaying in the menu bar and the application Info window. Defaults to the application name. .RE .TP -.B \f[CB]\-\-mac\-bundle\-signing\-prefix\f[R] -When signing the application bundle, this value is prefixed to all -components that need to be signed that don\[aq]t have an existing bundle -identifier. +.B \f[CB]\-\-mac\-package\-signing\-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. .RS .RE .TP @@ -291,34 +289,55 @@ Request that the bundle be signed. .RS .RE .TP -.B \f[CB]\-\-mac\-signing\-keychain\f[R] -Path of the keychain to search for the signing identity (absolute path -or relative to the current directory). +.B \f[CB]\-\-mac\-signing\-keychain\f[R] +Name of the keychain to search for the signing identity .RS .PP If not specified, the standard keychains are used. .RE .TP .B \f[CB]\-\-mac\-signing\-key\-user\-name\f[R] -Team name portion in Apple signing identities\[aq] names. +Team or user name portion in Apple signing identities +.RS +.RE +.TP +.B \f[CB]\-\-mac\-app\-store\f[R] +Indicates that the jpackage output is intended for the Mac App Store. +.RS +.RE +.TP +.B \f[CB]\-\-mac\-entitlements\f[R] +Path to file containing entitlements to use when signing executables and +libraries in the bundle +.RS +.RE +.TP +.B \f[CB]\-\-mac\-app\-category\f[R] +String used to construct LSApplicationCategoryType in application plist .RS .PP -For example "Developer ID Application: " +The default value is "utilities". .RE .SS Options for creating the application package: .TP -.B \f[CB]\-\-app\-image\f[R] +.B \f[CB]\-\-about\-url\f[R] +URL of the application\[aq]s home page +.RS +.RE +.TP +.B \f[CB]\-\-app\-image\f[R] Location of the predefined application image that is used to build an -installable package (absolute path or relative to the current -directory). +installable package .RS .PP +(absolute path or relative to the current directory). +.PP See create\-app\-image mode options to create the application image. .RE .TP .B \f[CB]\-\-file\-associations\f[R] Path to a Properties file that contains list of key, value pairs -(absolute path or relative to the current directory). +(absolute path or relative to the current directory) .RS .PP The keys "extension", "mime\-type", "icon", and "description" can be @@ -327,32 +346,31 @@ used to describe the association. This option can be used multiple times. .RE .TP -.B \f[CB]\-\-install\-dir\f[R] -Absolute path of the installation directory of the application on OS X -or Linux. -Relative sub\-path of the installation location of the application such -as "Program Files" or "AppData" on Windows. +.B \f[CB]\-\-install\-dir\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 +"Program Files" or "AppData" (on Windows) .RS .RE .TP .B \f[CB]\-\-license\-file\f[R] Path to the license file (absolute path or relative to the current -directory). +directory) .RS .RE .TP -.B \f[CB]\-\-resource\-dir\f[R] +.B \f[CB]\-\-resource\-dir\f[R] Path to override jpackage resources (absolute path or relative to the -current directory). +current directory) .RS .PP Icons, template files, and other resources of jpackage can be over\-ridden by adding replacement resources to this directory. .RE .TP -.B \f[CB]\-\-runtime\-image\f[R] +.B \f[CB]\-\-runtime\-image\f[R] Path of the predefined runtime image to install (absolute path or -relative to the current directory). +relative to the current directory) .RS .PP Option is required when creating a runtime installer. @@ -366,44 +384,62 @@ product is installed. .RS .RE .TP +.B \f[CB]\-\-win\-help\-url\f[R] +URL where user can obtain further information or technical support +.RS +.RE +.TP .B \f[CB]\-\-win\-menu\f[R] -Adds the application to the system menu. +Request to add a Start Menu shortcut for this application .RS .RE .TP .B \f[CB]\-\-win\-menu\-group\f[R] -Start Menu group this application is placed in. +Start Menu group this application is placed in .RS .RE .TP .B \f[CB]\-\-win\-per\-user\-install\f[R] -Request to perform an install on a per\-user basis. +Request to perform an install on a per\-user basis .RS .RE .TP .B \f[CB]\-\-win\-shortcut\f[R] -Creates a desktop shortcut for the application. +Request to create a desktop shortcut for this application +.RS +.RE +.TP +.B \f[CB]\-\-win\-shortcut\-prompt\f[R] +Adds a dialog to enable the user to choose if shortcuts will be created +by installer +.RS +.RE +.TP +.B \f[CB]\-\-win\-update\-url\f[R] +URL of available application update information .RS .RE .TP .B \f[CB]\-\-win\-upgrade\-uuid\f[R] -UUID associated with upgrades for this package. +UUID associated with upgrades for this package .RS .RE .SS Linux platform options (available only when running on Linux): .TP .B \f[CB]\-\-linux\-package\-name\f[R] -Name for Linux package, defaults to the application name. +Name for Linux package .RS +.PP +Defaults to the application name. .RE .TP .B \f[CB]\-\-linux\-deb\-maintainer\f[R] -Maintainer for .deb bundle. +Maintainer for .deb bundle .RS .RE .TP .B \f[CB]\-\-linux\-menu\-group\f[R] -Menu group this application is placed in. +Menu group this application is placed in .RS .RE .TP @@ -413,24 +449,24 @@ Required packages or capabilities for the application .RE .TP .B \f[CB]\-\-linux\-rpm\-license\-type\f[R] -Type of the license ("License: " of the RPM .spec). +Type of the license ("License: " of the RPM .spec) .RS .RE .TP .B \f[CB]\-\-linux\-app\-release\f[R] Release value of the RPM .spec file or Debian revision value of -the DEB control file. +the DEB control file .RS .RE .TP .B \f[CB]\-\-linux\-app\-category\f[R] Group value of the RPM .spec file or Section value of DEB control -file. +file .RS .RE .TP .B \f[CB]\-\-linux\-shortcut\f[R] -Creates a shortcut for the application +Creates a shortcut for the application. .RS .RE .SH JPACKAGE EXAMPLES @@ -468,7 +504,8 @@ 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\ \-m\ moduleName\ \\ +\ \ \ \ jlink\ \-\-output\ appRuntimeImage\ \-p\ modulePath\ \\ +\ \ \ \ \ \ \ \ \-\-add\-modules\ moduleName\ \\ \ \ \ \ \ \ \ \ \-\-no\-header\-files\ [...] \ \ \ \ jpackage\ \-\-type\ app\-image\ \-n\ name\ \\ \ \ \ \ \ \ \ \ \-m\ moduleName/className\ \-\-runtime\-image\ appRuntimeImage diff --git a/src/jdk.jpackage/share/native/applauncher/AppLauncher.cpp b/src/jdk.jpackage/share/native/applauncher/AppLauncher.cpp index 566c57fd9a5..8381facb488 100644 --- a/src/jdk.jpackage/share/native/applauncher/AppLauncher.cpp +++ b/src/jdk.jpackage/share/native/applauncher/AppLauncher.cpp @@ -91,6 +91,24 @@ tstring findJvmLib(const CfgFile& cfgFile, const tstring& defaultRuntimePath, } } // namespace +bool AppLauncher::libEnvVariableContainsAppDir() const { + tstring value = SysInfo::getEnvVariable(std::nothrow, + libEnvVarName, tstring()); +#ifdef _WIN32 + value = tstrings::toLower(value); +#endif + + const tstring_array tokens = tstrings::split(value, + tstring(1, FileUtils::pathSeparator)); + return tokens.end() != std::find(tokens.begin(), tokens.end(), +#ifdef _WIN32 + tstrings::toLower(appDirPath) +#else + appDirPath +#endif + ); +} + Jvm* AppLauncher::createJvmLauncher() const { const tstring cfgFilePath = FileUtils::mkpath() << appDirPath << FileUtils::stripExeSuffix( @@ -112,8 +130,12 @@ Jvm* AppLauncher::createJvmLauncher() const { PropertyName::arguments, args); } - SysInfo::setEnvVariable(libEnvVarName, SysInfo::getEnvVariable( - std::nothrow, libEnvVarName) + FileUtils::pathSeparator + appDirPath); + if (!libEnvVariableContainsAppDir()) { + SysInfo::setEnvVariable(libEnvVarName, SysInfo::getEnvVariable( + std::nothrow, libEnvVarName) + + FileUtils::pathSeparator + + appDirPath); + } std::unique_ptr jvm(new Jvm()); diff --git a/src/jdk.jpackage/share/native/applauncher/AppLauncher.h b/src/jdk.jpackage/share/native/applauncher/AppLauncher.h index a318d49ba70..306233a5d85 100644 --- a/src/jdk.jpackage/share/native/applauncher/AppLauncher.h +++ b/src/jdk.jpackage/share/native/applauncher/AppLauncher.h @@ -65,6 +65,8 @@ class AppLauncher { return *this; } + bool libEnvVariableContainsAppDir() const; + Jvm* createJvmLauncher() const; void launch() const; diff --git a/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp b/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp index ffc2572fd38..a3b8f150082 100644 --- a/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp +++ b/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp @@ -138,17 +138,55 @@ void launchApp() { const tstring launcherPath = SysInfo::getProcessModulePath(); const tstring appImageRoot = FileUtils::dirname(launcherPath); + const tstring appDirPath = FileUtils::mkpath() << appImageRoot << _T("app"); const tstring runtimeBinPath = FileUtils::mkpath() << appImageRoot << _T("runtime") << _T("bin"); - std::unique_ptr jvm(AppLauncher() - .setImageRoot(appImageRoot) + const AppLauncher appLauncher = AppLauncher().setImageRoot(appImageRoot) .addJvmLibName(_T("bin\\jli.dll")) - .setAppDir(FileUtils::mkpath() << appImageRoot << _T("app")) + .setAppDir(appDirPath) .setLibEnvVariableName(_T("PATH")) .setDefaultRuntimePath(FileUtils::mkpath() << appImageRoot - << _T("runtime")) - .createJvmLauncher()); + << _T("runtime")); + + const bool restart = !appLauncher.libEnvVariableContainsAppDir(); + + std::unique_ptr jvm(appLauncher.createJvmLauncher()); + + if (restart) { + jvm = std::unique_ptr(); + + STARTUPINFOW si; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(pi)); + + if (!CreateProcessW(launcherPath.c_str(), GetCommandLineW(), + NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + JP_THROW(SysError(tstrings::any() << "CreateProcessW() failed", + CreateProcessW)); + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + UniqueHandle childProcessHandle(pi.hProcess); + UniqueHandle childThreadHandle(pi.hThread); + + DWORD exitCode; + if (!GetExitCodeProcess(pi.hProcess, &exitCode)) { + JP_THROW(SysError(tstrings::any() << "GetExitCodeProcess() failed", + GetExitCodeProcess)); + } + + if (exitCode != 0) { + JP_THROW(tstrings::any() << "Child process exited with code " + << exitCode); + } + + return; + } // zip.dll may be loaded by java without full path // make sure it will look in runtime/bin diff --git a/src/jdk.jpackage/windows/native/common/WinSysInfo.cpp b/src/jdk.jpackage/windows/native/common/WinSysInfo.cpp index 9398fc67f22..55c0b7bee2d 100644 --- a/src/jdk.jpackage/windows/native/common/WinSysInfo.cpp +++ b/src/jdk.jpackage/windows/native/common/WinSysInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -122,10 +122,6 @@ void setEnvVariable(const tstring& name, const tstring& value) << name << ", " << value << ") failed", SetEnvironmentVariable)); } - - if (0 != _tputenv_s(name.c_str(), value.c_str())) { - JP_THROW(tstrings::any() << "_tputenv_s(" << name << ", " << value << ") failed: " << lastCRTError()); - } } tstring getCurrentModulePath() diff --git a/src/jdk.jshell/share/man/jshell.1 b/src/jdk.jshell/share/man/jshell.1 index 39d18e197ef..1865d30f90a 100644 --- a/src/jdk.jshell/share/man/jshell.1 +++ b/src/jdk.jshell/share/man/jshell.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSHELL" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JSHELL" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jstatd/share/man/jstatd.1 b/src/jdk.jstatd/share/man/jstatd.1 index 21388eb527a..ccfe6e000aa 100644 --- a/src/jdk.jstatd/share/man/jstatd.1 +++ b/src/jdk.jstatd/share/man/jstatd.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTATD" "1" "2021" "JDK 17\-ea" "JDK Commands" +.TH "JSTATD" "1" "2021" "JDK 18\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/test/hotspot/gtest/gtestMain.cpp b/test/hotspot/gtest/gtestMain.cpp index 9165a43d3bd..2fa875efaf5 100644 --- a/test/hotspot/gtest/gtestMain.cpp +++ b/test/hotspot/gtest/gtestMain.cpp @@ -61,8 +61,7 @@ static bool is_suffix(const char* suffix, const char* str) { return strncmp(str + (str_len - suffix_len), suffix, suffix_len) == 0; } - -static int init_jvm(int argc, char **argv, bool disable_error_handling) { +static int init_jvm(int argc, char **argv, bool disable_error_handling, JavaVM** jvm_ptr) { // don't care about the program name argc--; argv++; @@ -90,10 +89,9 @@ static int init_jvm(int argc, char **argv, bool disable_error_handling) { args.options = options; args.ignoreUnrecognized = JNI_FALSE; - JavaVM* jvm; JNIEnv* env; - int ret = JNI_CreateJavaVM(&jvm, (void**)&env, &args); + int ret = JNI_CreateJavaVM(jvm_ptr, (void**)&env, &args); if (ret == JNI_OK) { // CreateJavaVM leaves WXExec context, while gtests // calls internal functions assuming running in WXWwrite. @@ -111,26 +109,31 @@ class JVMInitializerListener : public ::testing::EmptyTestEventListener { private: int _argc; char** _argv; - bool _is_initialized; - - void initialize_jvm() { - } + JavaVM* _jvm; public: JVMInitializerListener(int argc, char** argv) : - _argc(argc), _argv(argv), _is_initialized(false) { + _argc(argc), _argv(argv), _jvm(nullptr) { } virtual void OnTestStart(const ::testing::TestInfo& test_info) { const char* name = test_info.name(); - if (!_is_initialized && is_same_vm_test(name)) { + if (_jvm == nullptr && is_same_vm_test(name)) { // we want to have hs_err and core files when we execute regular tests - int ret_val = init_jvm(_argc, _argv, false); + int ret_val = init_jvm(_argc, _argv, false, &_jvm); if (ret_val != 0) { - ADD_FAILURE() << "Could not initialize the JVM"; + ADD_FAILURE() << "Could not initialize the JVM: " << ret_val; exit(1); } - _is_initialized = true; + } + } + + void destroy_jvm() { + if (_jvm != NULL) { + int ret = _jvm->DestroyJavaVM(); + if (ret != 0) { + fprintf(stderr, "Warning: DestroyJavaVM error %d\n", ret); + } } } }; @@ -208,6 +211,18 @@ static char** remove_test_runner_arguments(int* argcp, char **argv) { return new_argv; } +// This is generally run once for a set of tests. But if that set includes a vm_assert or +// other_vm test, then a new process is forked, and runUnitTestsInner is called, passing +// just that test as the one to be executed. +// +// When we execute a vm_assert or other_vm test we create and initialize the JVM below. +// +// A vm_assert test crashes the VM so no cleanup is needed, but for other_vm we call +// DestroyJavaVM via the TEST_OTHER_VM macro prior to the call to exit(). +// +// For same_vm tests we use an event listener to create the JVM when the first same_vm +// test is executed. Once all tests are completed we can then call DestroyJavaVM on that +// JVM directly. static void runUnitTestsInner(int argc, char** argv) { ::testing::InitGoogleMock(&argc, argv); ::testing::GTEST_FLAG(death_test_style) = "threadsafe"; @@ -253,22 +268,38 @@ static void runUnitTestsInner(int argc, char** argv) { #endif // _WIN32 argv = remove_test_runner_arguments(&argc, argv); + + JVMInitializerListener* jvm_listener = NULL; + if (is_vmassert_test || is_othervm_test) { + JavaVM* jvm = NULL; // both vmassert and other vm tests require inited jvm // but only vmassert tests disable hs_err and core file generation - if (init_jvm(argc, argv, is_vmassert_test) != 0) { + int ret; + if ((ret = init_jvm(argc, argv, is_vmassert_test, &jvm)) != 0) { + fprintf(stderr, "ERROR: JNI_CreateJavaVM failed: %d\n", ret); abort(); } } else { ::testing::TestEventListeners& listeners = ::testing::UnitTest::GetInstance()->listeners(); - listeners.Append(new JVMInitializerListener(argc, argv)); + jvm_listener = new JVMInitializerListener(argc, argv); + listeners.Append(jvm_listener); } int result = RUN_ALL_TESTS(); + + // vm_assert and other_vm tests never reach this point as they either abort, or call + // exit() - see TEST_OTHER_VM macro. We will reach here when all same_vm tests have + // completed for this run, so we can terminate the VM used for that case. + if (result != 0) { fprintf(stderr, "ERROR: RUN_ALL_TESTS() failed. Error %d\n", result); exit(2); } + + if (jvm_listener != NULL) { + jvm_listener->destroy_jvm(); + } } // Thread support for -new-thread option diff --git a/test/hotspot/gtest/memory/test_arena.cpp b/test/hotspot/gtest/memory/test_arena.cpp index 148728c9864..363ee984503 100644 --- a/test/hotspot/gtest/memory/test_arena.cpp +++ b/test/hotspot/gtest/memory/test_arena.cpp @@ -366,3 +366,34 @@ TEST_VM(Arena, Arena_grows_large_unaligned) { } #endif // LP64 + +static size_t random_arena_chunk_size() { + // Return with a 50% rate a standard size, otherwise some random size + if (os::random() % 10 < 5) { + static const size_t standard_sizes[4] = { + Chunk::tiny_size, Chunk::init_size, Chunk::size, Chunk::medium_size + }; + return standard_sizes[os::random() % 4]; + } + return ARENA_ALIGN(os::random() % 1024); +} + +TEST_VM(Arena, different_chunk_sizes) { + // Test the creation/pooling of chunks; since ChunkPool is hidden, the + // only way to test this is to create/destroy arenas with different init sizes, + // which determines the initial chunk size. + // Note that since the chunk pools are global and get cleaned out periodically, + // there is no safe way to actually test their occupancy here. + for (int i = 0; i < 1000; i ++) { + // Unfortunately, Arenas cannot be newed, + // so we are left with awkwardly placing a few on the stack. + Arena ar0(mtTest, random_arena_chunk_size()); + Arena ar1(mtTest, random_arena_chunk_size()); + Arena ar2(mtTest, random_arena_chunk_size()); + Arena ar3(mtTest, random_arena_chunk_size()); + Arena ar4(mtTest, random_arena_chunk_size()); + Arena ar5(mtTest, random_arena_chunk_size()); + Arena ar6(mtTest, random_arena_chunk_size()); + Arena ar7(mtTest, random_arena_chunk_size()); + } +} diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index d19560730c7..3cf5d1c374b 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -413,7 +413,11 @@ struct NUMASwitcher { #endif #ifndef _AIX // JDK-8257041 -TEST_VM(os, release_multi_mappings) { +#if defined(__APPLE__) && !defined(AARCH64) // See JDK-8267341. + TEST_VM(os, DISABLED_release_multi_mappings) { +#else + TEST_VM(os, release_multi_mappings) { +#endif // With NMT enabled, this will trigger JDK-8263464. For now disable the test if NMT=on. if (MemTracker::tracking_level() > NMT_off) { diff --git a/test/hotspot/gtest/unittest.hpp b/test/hotspot/gtest/unittest.hpp index 140d14d25f2..16ee6220beb 100644 --- a/test/hotspot/gtest/unittest.hpp +++ b/test/hotspot/gtest/unittest.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -88,6 +88,15 @@ static void child_ ## category ## _ ## name ## _() { \ ::testing::GTEST_FLAG(throw_on_failure) = true; \ test_ ## category ## _ ## name ## _(); \ + JavaVM* jvm[1]; \ + jsize nVMs = 0; \ + JNI_GetCreatedJavaVMs(&jvm[0], 1, &nVMs); \ + if (nVMs == 1) { \ + int ret = jvm[0]->DestroyJavaVM(); \ + if (ret != 0) { \ + fprintf(stderr, "Warning: DestroyJavaVM error %d\n", ret); \ + } \ + } \ fprintf(stderr, "OKIDOKI"); \ exit(0); \ } \ diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index e0d6ef70dcd..37ed02d7fe5 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -38,7 +38,7 @@ serviceability/sa/ClhsdbFindPC.java#id1 8268722 macosx-x serviceability/sa/ClhsdbFindPC.java#id3 8268722 macosx-x64 serviceability/sa/ClhsdbPmap.java#id1 8268722 macosx-x64 serviceability/sa/ClhsdbPstack.java#id1 8268722 macosx-x64 -serviceability/sa/TestJmapCore.java 8268722,8268283 macosx-x64,linux-aarch64 +serviceability/sa/TestJmapCore.java 8268722,8268283,8270202 macosx-x64,linux-aarch64,linux-x64 serviceability/sa/TestJmapCoreMetaspace.java 8268722,8268636 generic-all serviceability/sa/TestJhsdbJstackMixed.java 8248912 generic-all diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index dc4301fcda9..db23dc5dba9 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -69,6 +69,7 @@ compiler/whitebox/EnqueueMethodForCompilationTest.java 8265360 macosx-aarch64 compiler/whitebox/MakeMethodNotCompilableTest.java 8265360 macosx-aarch64 compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-x64 +compiler/codecache/TestStressCodeBuffers.java 8272094 generic-aarch64 ############################################################################# diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestIllegalArrayCopyBeforeInfiniteLoop.java b/test/hotspot/jtreg/compiler/arraycopy/TestIllegalArrayCopyBeforeInfiniteLoop.java new file mode 100644 index 00000000000..33c0506a278 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/TestIllegalArrayCopyBeforeInfiniteLoop.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 8272131 + * @requires vm.compiler2.enabled + * @summary ArrayCopy with negative index before infinite loop + * @run main/othervm -Xbatch -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,"*TestIllegalArrayCopyBeforeInfiniteLoop::foo" + * compiler.arraycopy.TestIllegalArrayCopyBeforeInfiniteLoop + */ + +package compiler.arraycopy; + +import java.util.Arrays; + +public class TestIllegalArrayCopyBeforeInfiniteLoop { + private static char src[] = new char[10]; + private static int count = 0; + private static final int iter = 10_000; + + public static void main(String[] args) throws Exception { + for (int i = 0; i < iter; ++i) { + foo(); + } + if (count != iter) { + throw new RuntimeException("test failed"); + } + } + + static void foo() { + try { + Arrays.copyOfRange(src, -1, 128); + do { + } while (true); + } catch (ArrayIndexOutOfBoundsException ex) { + count++; + } + } +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestObjectArrayClone.java b/test/hotspot/jtreg/compiler/arraycopy/TestObjectArrayClone.java index 705f2cdb5bf..e4fac6c78df 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestObjectArrayClone.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestObjectArrayClone.java @@ -23,21 +23,33 @@ /* * @test - * @bug 8155643 8268125 8270461 + * @bug 8155643 8268125 8270461 8270098 * @summary Test Object.clone() intrinsic. + * @modules java.base/java.lang:+open * * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-ReduceInitialCardMarks * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone* + * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke * compiler.arraycopy.TestObjectArrayClone * @run main/othervm -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone* + * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke * compiler.arraycopy.TestObjectArrayClone * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedClassPointers -Xmx128m * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone* + * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke + * compiler.arraycopy.TestObjectArrayClone + * @run main/othervm -Xbatch -XX:-UseTypeProfile + * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone* + * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke * compiler.arraycopy.TestObjectArrayClone */ package compiler.arraycopy; +import java.lang.invoke.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + class Payload implements Cloneable { boolean b; int i; @@ -59,7 +71,7 @@ public Payload(boolean b, int i, char c, String str, short s, int i2) { public Payload clonep() { try { return (Payload) super.clone(); - } catch(CloneNotSupportedException e) { + } catch (CloneNotSupportedException e) { return null; } } @@ -136,6 +148,17 @@ public static String[] testCloneShortObjectArray() { return arr.clone(); } + public static String[] testCloneShortObjectArray2(Method clone) throws Exception { + String[] arr = new String[5]; + arr[0] = str1; + arr[1] = str2; + arr[2] = str3; + arr[3] = str4; + arr[4] = str5; + escape_arr = arr; + return (String[]) testCloneObject(clone, arr); + } + public static String[] testCloneShortObjectArrayCopy() { String[] arr = new String[5]; arr[0] = str1; @@ -161,7 +184,14 @@ public static Object testCloneOop2(Payload2 p) { return p.clonep(); } - public static void main(String[] args) { + public static Object testCloneObject(Method clone, Object obj) throws Exception { + return clone.invoke(obj); + } + + public static void main(String[] args) throws Exception { + Method clone = Object.class.getDeclaredMethod("clone"); + clone.setAccessible(true); + String[] arr1 = new String[42]; for (int j = 0; j < arr1.length; j++) { arr1[j] = new String(Integer.toString(j)); @@ -178,6 +208,20 @@ public static void main(String[] args) { verifyStr(arr1, arr2); } + for (int i = 0; i < 50_000; i++) { + for (int j = 0; j < arr1.length; j++) { + arr1[j] = new String(Integer.toString(j)); + } + String[] arr2 = (String[]) testCloneObject(clone, arr1); + verifyStr(arr1, arr2); + String[] arr3 = (String[]) testCloneObject(clone, arr1); + verifyStr(arr1, arr3); + String[] arr4 = (String[]) testCloneObject(clone, arr1); + verifyStr(arr1, arr4); + verifyStr(arr1, arr3); + verifyStr(arr1, arr2); + } + for (int i = 0; i < 50_000; i++) { String[] value = testCloneShortObjectArray(); verifyStr(value, escape_arr); @@ -185,6 +229,9 @@ public static void main(String[] args) { verifyStr(value2, escape_arr); String[] value3 = testCloneShortObjectArray(); verifyStr(value3, escape_arr); + String[] value4 = testCloneShortObjectArray2(clone); + verifyStr(value4, escape_arr); + verifyStr(value, value4); verifyStr(value, value3); verifyStr(value, value2); } @@ -211,8 +258,21 @@ public static void main(String[] args) { verifyStr(value, value2); } + int[] arr2 = new int[42]; + for (int i = 0; i < arr2.length; i++) { + arr2[i] = i; + } for (int i = 0; i < 50_000; i++) { - testClonePrimitiveArray(new int[42]); + int[] res1 = testClonePrimitiveArray(arr2); + int[] res2 = (int[])testCloneObject(clone, arr2); + for (int j = 0; j < arr2.length; j++) { + if (res1[j] != j) { + throw new RuntimeException("Unexpected result: " + res1[j] + " != " + j); + } + if (res2[j] != j) { + throw new RuntimeException("Unexpected result: " + res2[j] + " != " + j); + } + } } Payload ref = new Payload(false, -1, 'c', str1, (short) 5, -1); @@ -227,6 +287,17 @@ public static void main(String[] args) { verifyPayload(p1, p3); } + for (int i = 0; i < 50_000; i++) { + Payload p1 = (Payload) testCloneObject(clone, ref); + verifyPayload(ref, p1); + Payload p2 = (Payload) testCloneObject(clone, ref); + verifyPayload(ref, p2); + Payload p3 = (Payload) testCloneObject(clone, ref); + verifyPayload(ref, p3); + verifyPayload(p2, p3); + verifyPayload(p1, p3); + } + Payload2 ref2 = new Payload2(false, -1, 'c', str1, (short) 5, -1, false, 0, 'k', str2, (short)-1, 0); for (int i = 0; i < 50_000; i++) { Payload2 p1 = (Payload2) testCloneOop2(ref2); @@ -238,6 +309,17 @@ public static void main(String[] args) { verifyPayload2(p2, p3); verifyPayload2(p1, p3); } + + for (int i = 0; i < 50_000; i++) { + Payload2 p1 = (Payload2) testCloneObject(clone, ref2); + verifyPayload2(ref2, p1); + Payload2 p2 = (Payload2) testCloneObject(clone, ref2); + verifyPayload2(ref2, p2); + Payload2 p3 = (Payload2) testCloneObject(clone, ref2); + verifyPayload2(ref2, p3); + verifyPayload2(p2, p3); + verifyPayload2(p1, p3); + } } public static void verifyPayload(Payload p1, Payload p2) { @@ -323,7 +405,6 @@ public static void verifyStr(String[] arr1, String[] arr2) { if (!arr1[i].equals(arr2[i])) { throw new RuntimeException("Fail cloned element content not the same"); } - } } } diff --git a/test/hotspot/jtreg/compiler/c2/LongCountedLoopAsUnswitchIff.java b/test/hotspot/jtreg/compiler/c2/LongCountedLoopAsUnswitchIff.java new file mode 100644 index 00000000000..953c8e27d5e --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/LongCountedLoopAsUnswitchIff.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 8271203 + * @summary C2: assert(iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_RangeCheck) failed: Check this code when new subtype is added + * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:CompileOnly=compiler.c2.LongCountedLoopAsUnswitchIff::test compiler.c2.LongCountedLoopAsUnswitchIff + */ + +package compiler.c2; + +public class LongCountedLoopAsUnswitchIff { + static int iArrFld[] = new int[400]; + + public static void main(String[] strArr) { + for (int i = 0; i < 10; i++) { + test(); + } + } + + static void test() { + int i = 56, i2 = 22257; + + do { + do { + int i24 = 1; + while (++i24 < 2) { + } + for (long l1 = i; l1 < 2; ++l1) { + iArrFld[0] += 5; + } + } while ((i2 -= 2) > 0); + for (long l3 = 8; l3 < 194; ++l3) { + } + } while (--i > 0); + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVectRotate.java b/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVectRotate.java index 0af06bd7e10..2b8e0f64e3b 100644 --- a/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVectRotate.java +++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVectRotate.java @@ -37,6 +37,7 @@ public class TestIntVectRotate { private static final int ARRLEN = 997; + private static final int REPCOUNT = 16; private static final int ITERS = 11000; private static final int ADD_INIT = Integer.MAX_VALUE-500; private static final int VALUE = 15; @@ -44,6 +45,15 @@ public class TestIntVectRotate { private static final int SHIFT_LT_IMM8 = -128; private static final int SHIFT_GT_IMM8 = 128; + private static final int [] rolRes = { + 15, 32, 68, 144, 304, 640, 1344, 2816, 5888, 12288, 25600, 53248, 110592, 229376, 475136, 983040 + }; + + private static final int [] rorRes = { + 15, 8, 1073741828, 1073741826, 805306369, -1610612736, 1409286144, 738197504, 385875968, 201326592, + 104857600, 54525952, 28311552, 14680064, 7602176, 3932160 + }; + public static void main(String args[]) { System.out.println("Testing Integer Rotate vectors"); test(); @@ -58,12 +68,16 @@ public static void main(String args[]) { static int[] a0 = new int[ARRLEN]; static int[] a1 = new int[ARRLEN]; + static int[] a2 = new int[ARRLEN]; + static int[] a3 = new int[ARRLEN]; static void test() { // Initialize for (int i=0; i>>SHIFT)); } - + test_rolv_vec(a0, a2, a3); + for (int i=0; i>>(-SHIFT)) | (int)(ADD_INIT+i)<>> Check stdout for compilation output of the failed methods") .append(System.lineSeparator()).append(System.lineSeparator()); - throw new IRViolationException(failuresBuilder.toString(), compilationsBuilder.toString()); + + // In some very rare cases, the VM output to regex match on contains "" + // (emitted by ttyLocker::break_tty_for_safepoint) which might be the reason for a matching error. + // Do not throw an exception in this case (i.e. bailout). + String compilations = compilationsBuilder.toString(); + if (!compilations.contains(SAFEPOINT_WHILE_PRINTING_MESSAGE)) { + throw new IRViolationException(failuresBuilder.toString(), compilationsBuilder.toString()); + } else { + System.out.println("Found " + SAFEPOINT_WHILE_PRINTING_MESSAGE + ", bail out of IR matching"); + } } } } diff --git a/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java b/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java index c9f02dd0bd3..79e76ab4d54 100644 --- a/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java +++ b/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Red Hat Inc. + * Copyright (c) 2020, 2021, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,6 +105,7 @@ public class CgroupSubsystemFactory { "devices 0 1 1\n" + "freezer 0 1 1\n" + "net_cls 0 1 1\n" + + "pids 0 1 1\n" + "blkio 0 1 1\n" + "perf_event 0 1 1 "; private String cgroupsNonZeroJoinControllers = @@ -168,7 +169,7 @@ public class CgroupSubsystemFactory { "perf_event 4 1 1\n" + "net_prio 5 1 1\n" + "hugetlb 6 1 1\n" + - "pids 3 80 1"; + "pids 9 80 1"; // hierarchy has to match procSelfCgroupHybridContent private String mntInfoCgroupsV2Only = "28 21 0:25 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 none rw,seclabel,nsdelegate"; private String mntInfoCgroupsV1SystemdOnly = diff --git a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java index 792418f074d..bcbd2ffa21d 100644 --- a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java +++ b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java @@ -48,7 +48,7 @@ public static void main(String[] args) throws Exception { return; } - DockerTestUtils.buildJdkDockerImage(imageNameAndTag, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(imageNameAndTag); try { testJavaVersion(); diff --git a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java index c29181e8b36..d8246bfc2c5 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java @@ -52,7 +52,7 @@ public static void main(String[] args) throws Exception { } System.out.println("Test Environment: detected availableCPUs = " + availableCPUs); - DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(imageName); try { // cpuset, period, shares, expected Active Processor Count diff --git a/test/hotspot/jtreg/containers/docker/TestCPUSets.java b/test/hotspot/jtreg/containers/docker/TestCPUSets.java index f00fb42dbd1..c2bf6ac6446 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUSets.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUSets.java @@ -57,7 +57,7 @@ public static void main(String[] args) throws Exception { Common.prepareWhiteBox(); - DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(imageName); try { // Sanity test the cpu sets reader and parser diff --git a/test/hotspot/jtreg/containers/docker/TestJFREvents.java b/test/hotspot/jtreg/containers/docker/TestJFREvents.java index 8e252d16d25..787a05ebbdb 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java @@ -58,7 +58,7 @@ public static void main(String[] args) throws Exception { return; } - DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(imageName); try { diff --git a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java index 2f9f6305a00..54ffff4e60e 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java @@ -51,7 +51,7 @@ public static void main(String[] args) throws Exception { return; } - DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(imageName); try { runTest("jdk.SocketWrite"); diff --git a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java index bb31d448afc..61fad4f86be 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java @@ -80,7 +80,7 @@ public static void main(String[] args) throws Exception { throw new SkippedException("test cannot be run under rootless podman configuration"); } - DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(imageName); try { test(); diff --git a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java index 5fb106516f0..6d48811b7e8 100644 --- a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java +++ b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java @@ -65,7 +65,7 @@ public static void main(String[] args) throws Exception { return; } - DockerTestUtils.buildJdkDockerImage(IMAGE_NAME, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(IMAGE_NAME); try { // Start the loop process in the "main" container, then run test cases diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java index 8e217c5e6f3..f40963c9420 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java @@ -50,7 +50,7 @@ public static void main(String[] args) throws Exception { } Common.prepareWhiteBox(); - DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(imageName); try { testMemoryLimit("100m", "104857600"); diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index 0db883b68d0..dfb95dfdd05 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -50,7 +50,7 @@ public static void main(String[] args) throws Exception { } Common.prepareWhiteBox(); - DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); + DockerTestUtils.buildJdkContainerImage(imageName); try { testMinusContainerSupport(); @@ -105,7 +105,8 @@ private static void checkContainerInfo(OutputAnalyzer out) throws Exception { "Memory Soft Limit", "Memory Usage", "Maximum Memory Usage", - "memory_max_usage_in_bytes" + "memory_max_usage_in_bytes", + "maximum number of tasks" }; for (String s : expectedToContain) { diff --git a/test/hotspot/jtreg/containers/docker/TestPids.java b/test/hotspot/jtreg/containers/docker/TestPids.java new file mode 100644 index 00000000000..df31b2ad091 --- /dev/null +++ b/test/hotspot/jtreg/containers/docker/TestPids.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @key cgroups + * @summary Test JVM's awareness of pids controller + * @requires docker.support + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build sun.hotspot.WhiteBox PrintContainerInfo + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox + * @run driver TestPids + */ +import java.util.List; +import jdk.test.lib.containers.docker.Common; +import jdk.test.lib.containers.docker.DockerRunOptions; +import jdk.test.lib.containers.docker.DockerTestUtils; +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import jdk.test.lib.Utils; + +public class TestPids { + private static final String imageName = Common.imageName("pids"); + + public static void main(String[] args) throws Exception { + if (!DockerTestUtils.canTestDocker()) { + return; + } + + Common.prepareWhiteBox(); + DockerTestUtils.buildJdkContainerImage(imageName); + + try { + testPids(); + } finally { + if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { + DockerTestUtils.removeDockerImage(imageName); + } + } + } + + private static void testPids() throws Exception { + System.out.println("Testing pids controller ..."); + testPids("400"); + testPids("800"); + testPids("2000"); + testPids("Unlimited"); + } + + private static DockerRunOptions commonOpts() { + DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "PrintContainerInfo"); + opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); + opts.addJavaOpts("-Xlog:os+container=trace", "-cp", "/test-classes/"); + Common.addWhiteBoxOpts(opts); + return opts; + } + + private static void checkResult(List lines, String lineMarker, String expectedValue) { + boolean lineMarkerFound = false; + + for (String line : lines) { + if (line.contains("WARNING: Your kernel does not support pids limit capabilities")) { + System.out.println("Docker pids limitation seems not to work, avoiding check"); + return; + } + + if (line.contains(lineMarker)) { + lineMarkerFound = true; + String[] parts = line.split(":"); + System.out.println("DEBUG: line = " + line); + System.out.println("DEBUG: parts.length = " + parts.length); + + Asserts.assertEquals(parts.length, 2); + String actual = parts[1].replaceAll("\\s",""); + // Unlimited pids leads on some setups not to "max" in the output, but to a high number + if (expectedValue.equals("max")) { + if (actual.equals("max")) { + System.out.println("Found expected max for unlimited pids value."); + } else { + try { + int ai = Integer.parseInt(actual); + if (ai > 20000) { + System.out.println("Limit value " + ai + " got accepted as unlimited, log line was " + line); + } else { + throw new RuntimeException("Limit value " + ai + " is not accepted as unlimited, log line was " + line); + } + } catch (NumberFormatException ex) { + throw new RuntimeException("Could not convert " + actual + " to an integer, log line was " + line); + } + } + } else { + Asserts.assertEquals(actual, expectedValue); + } + break; + } + } + Asserts.assertTrue(lineMarkerFound); + } + + private static void testPids(String value) throws Exception { + Common.logNewTestCase("pids controller test, limiting value = " + value); + + DockerRunOptions opts = commonOpts(); + if (value.equals("Unlimited")) { + opts.addDockerOpts("--pids-limit=-1"); + } else { + opts.addDockerOpts("--pids-limit="+value); + } + + List lines = Common.run(opts).asLines(); + if (value.equals("Unlimited")) { + checkResult(lines, "Maximum number of tasks is: ", "max"); + } else { + checkResult(lines, "Maximum number of tasks is: ", value); + } + } + +} diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index 6be0f94ef24..2b2658ab8d9 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -156,6 +156,10 @@ public boolean isAvailable() { // TLAB handling new LogMessageWithLevel("Prepare TLABs", Level.DEBUG), new LogMessageWithLevel("Resize TLABs", Level.DEBUG), + + // NMethod List Cleanup + new LogMessageWithLevel("NMethod List Cleanup", Level.DEBUG), + // Reference Processing new LogMessageWithLevel("Reference Processing", Level.DEBUG), // VM internal reference processing diff --git a/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java b/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java index a12a83d9127..6c5c03e68f7 100644 --- a/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java +++ b/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java @@ -99,6 +99,8 @@ private static OutputAnalyzer testWithMixedGCLiveThresholdPercent(int percent) t "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:+WhiteBoxAPI", + // Parallel full gc can distribute live objects into different regions. + "-XX:ParallelGCThreads=1", "-Xlog:gc+remset+tracking=trace", "-Xms10M", "-Xmx10M"}); diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationAgeThreshold.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationAgeThreshold.java index ae57bf7df98..23261c9bea7 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationAgeThreshold.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationAgeThreshold.java @@ -49,6 +49,19 @@ * @run driver gc.stringdedup.TestStringDeduplicationAgeThreshold Shenandoah */ +/* + * @test TestStringDeduplicationAgeThreshold + * @summary Test string deduplication age threshold + * @bug 8029075 + * @requires vm.gc.Z + * @library /test/lib + * @library / + * @modules java.base/jdk.internal.misc:open + * @modules java.base/java.lang:open + * java.management + * @run driver gc.stringdedup.TestStringDeduplicationAgeThreshold Z + */ + public class TestStringDeduplicationAgeThreshold { public static void main(String[] args) throws Exception { TestStringDeduplicationTools.selectGC(args); diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationFullGC.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationFullGC.java index 7e5bb9ae58c..e189cb8a1fb 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationFullGC.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationFullGC.java @@ -49,6 +49,19 @@ * @run driver gc.stringdedup.TestStringDeduplicationFullGC Shenandoah */ +/* + * @test TestStringDeduplicationFullGC + * @summary Test string deduplication during full GC + * @bug 8029075 + * @requires vm.gc.Z + * @library /test/lib + * @library / + * @modules java.base/jdk.internal.misc:open + * @modules java.base/java.lang:open + * java.management + * @run driver gc.stringdedup.TestStringDeduplicationFullGC Z + */ + public class TestStringDeduplicationFullGC { public static void main(String[] args) throws Exception { TestStringDeduplicationTools.selectGC(args); diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationInterned.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationInterned.java index 072f10e1058..e3cd39baf40 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationInterned.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationInterned.java @@ -36,6 +36,19 @@ * @run driver gc.stringdedup.TestStringDeduplicationInterned G1 */ +/* + * @test TestStringDeduplicationInterned + * @summary Test string deduplication of interned strings + * @bug 8029075 + * @requires vm.gc.Z + * @library /test/lib + * @library / + * @modules java.base/jdk.internal.misc:open + * @modules java.base/java.lang:open + * java.management + * @run driver gc.stringdedup.TestStringDeduplicationInterned Z + */ + public class TestStringDeduplicationInterned { public static void main(String[] args) throws Exception { TestStringDeduplicationTools.selectGC(args); diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationPrintOptions.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationPrintOptions.java index d57e726a544..6f75448bd0b 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationPrintOptions.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationPrintOptions.java @@ -49,6 +49,19 @@ * @run driver gc.stringdedup.TestStringDeduplicationPrintOptions Shenandoah */ +/* + * @test TestStringDeduplicationPrintOptions + * @summary Test string deduplication print options + * @bug 8029075 + * @requires vm.gc.Z + * @library /test/lib + * @library / + * @modules java.base/jdk.internal.misc:open + * @modules java.base/java.lang:open + * java.management + * @run driver gc.stringdedup.TestStringDeduplicationPrintOptions Z + */ + public class TestStringDeduplicationPrintOptions { public static void main(String[] args) throws Exception { TestStringDeduplicationTools.selectGC(args); diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTableResize.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTableResize.java index 53c71f1ec4c..0b2071f514c 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTableResize.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTableResize.java @@ -49,6 +49,19 @@ * @run driver gc.stringdedup.TestStringDeduplicationTableResize Shenandoah */ +/* + * @test TestStringDeduplicationTableResize + * @summary Test string deduplication table resize + * @bug 8029075 + * @requires vm.gc.Z + * @library /test/lib + * @library / + * @modules java.base/jdk.internal.misc:open + * @modules java.base/java.lang:open + * java.management + * @run driver gc.stringdedup.TestStringDeduplicationTableResize Z + */ + public class TestStringDeduplicationTableResize { public static void main(String[] args) throws Exception { TestStringDeduplicationTools.selectGC(args); diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationYoungGC.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationYoungGC.java index 02cf647e476..9fc98056def 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationYoungGC.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationYoungGC.java @@ -49,6 +49,19 @@ * @run driver gc.stringdedup.TestStringDeduplicationYoungGC Shenandoah */ +/* + * @test TestStringDeduplicationYoungGC + * @summary Test string deduplication during young GC + * @bug 8029075 + * @requires vm.gc.Z + * @library /test/lib + * @library / + * @modules java.base/jdk.internal.misc:open + * @modules java.base/java.lang:open + * java.management + * @run driver gc.stringdedup.TestStringDeduplicationYoungGC Z + */ + public class TestStringDeduplicationYoungGC { public static void main(String[] args) throws Exception { TestStringDeduplicationTools.selectGC(args); diff --git a/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java b/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java index 3daf28d5c30..be97d1cf056 100644 --- a/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java +++ b/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,6 +25,7 @@ * @test * @requires vm.cds * @requires vm.bits == 64 + * @requires vm.flagless * @bug 8003424 * @summary Testing UseCompressedClassPointers with CDS * @library /test/lib diff --git a/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/XShareAuto.java b/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/XShareAuto.java index 7fce01009e8..19c4128f460 100644 --- a/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/XShareAuto.java +++ b/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/XShareAuto.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /** * @test * @requires vm.cds + * @requires vm.flagless * @bug 8005933 * @summary -Xshare:auto is the default when -Xshare is not specified * @library /test/lib diff --git a/test/hotspot/jtreg/runtime/ClassFile/FormatCheckingTest.java b/test/hotspot/jtreg/runtime/ClassFile/FormatCheckingTest.java index a4655915d36..0ff1f0a65be 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/FormatCheckingTest.java +++ b/test/hotspot/jtreg/runtime/ClassFile/FormatCheckingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,6 +25,7 @@ * @test * @bug 8148854 * @summary Ensure class name loaded by app class loader is format checked by default + * @requires vm.flagless * @library /test/lib * @compile BadHelloWorld.jcod * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/ClassFile/JsrRewriting.java b/test/hotspot/jtreg/runtime/ClassFile/JsrRewriting.java index 5f52754d598..92a9c74c276 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/JsrRewriting.java +++ b/test/hotspot/jtreg/runtime/ClassFile/JsrRewriting.java @@ -32,6 +32,7 @@ * @bug 7053586 * @bug 7185550 * @bug 7149464 + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.misc * java.desktop diff --git a/test/hotspot/jtreg/runtime/ClassFile/OomWhileParsingRepeatedJsr.java b/test/hotspot/jtreg/runtime/ClassFile/OomWhileParsingRepeatedJsr.java index d63be2c41af..3f1d04c3d6d 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/OomWhileParsingRepeatedJsr.java +++ b/test/hotspot/jtreg/runtime/ClassFile/OomWhileParsingRepeatedJsr.java @@ -33,6 +33,7 @@ * @bug 7037122 * @bug 7123945 * @bug 8016029 + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.misc * java.desktop diff --git a/test/hotspot/jtreg/runtime/ClassFile/TestCheckedExceptions.java b/test/hotspot/jtreg/runtime/ClassFile/TestCheckedExceptions.java index bbe905d1b2d..a6f64e96bb6 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/TestCheckedExceptions.java +++ b/test/hotspot/jtreg/runtime/ClassFile/TestCheckedExceptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -29,6 +29,7 @@ * clause does not cause the JVM to assert nor throw an exception. * Also, test that logging can be used to print a message about bogus * classes in method throws clauses. + * @requires vm.flagless * @library /test/lib * @compile CheckedExceptions.jcod * @run driver TestCheckedExceptions diff --git a/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java b/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java new file mode 100644 index 00000000000..2e8921253c3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java @@ -0,0 +1,134 @@ +/* + * 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. + */ + +/** + * @test + * @bug 8048190 + * @summary Test that the NCDFE saves the stack trace for the original exception + * during class initialization with ExceptionInInitializationError, + * and doesn't prevent the classes in the stacktrace to be unloaded. + * @requires vm.opt.final.ClassUnloading + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -Xlog:class+unload -XX:+WhiteBoxAPI InitExceptionUnloadTest + */ + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import sun.hotspot.WhiteBox; +import jdk.test.lib.classloader.ClassUnloadCommon; + +public class InitExceptionUnloadTest { + static public class ThrowsRuntimeException { static int x = 1/0; } + static public class ThrowsError { static { if (true) throw new Error(); } } + static public class SpecialException extends RuntimeException { + SpecialException(int count, String message) { + super(message + count); + } + } + static public class ThrowsSpecialException { + static { + if (true) throw new SpecialException(3, "Very Special "); + } + } + + static public class ThrowsOOM { + static { + if (true) { + // Actually getting an OOM might be fragile but it was tested. + throw new OutOfMemoryError("Java heap space"); + } + } + } + + private static void verify_stack(Throwable e, String expected, String cause) throws Exception { + ByteArrayOutputStream byteOS = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(byteOS); + e.printStackTrace(printStream); + printStream.close(); + String stackTrace = byteOS.toString("ASCII"); + if (!stackTrace.contains(expected) || (cause != null && !stackTrace.contains(cause))) { + throw new RuntimeException(expected + " and " + cause + " missing from stacktrace"); + } + } + + static String[] expected = new String[] { + "java.lang.ExceptionInInitializerError", + "Caused by: java.lang.ArithmeticException: / by zero", + "java.lang.NoClassDefFoundError: Could not initialize class InitExceptionUnloadTest$ThrowsRuntimeException", + "Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.ArithmeticException: / by zero [in thread", + "java.lang.Error", + null, + "java.lang.NoClassDefFoundError: Could not initialize class InitExceptionUnloadTest$ThrowsError", + "Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.Error [in thread", + "java.lang.ExceptionInInitializerError", + "Caused by: InitExceptionUnloadTest$SpecialException: Very Special 3", + "java.lang.NoClassDefFoundError: Could not initialize class InitExceptionUnloadTest$ThrowsSpecialException", + "Caused by: java.lang.ExceptionInInitializerError: Exception InitExceptionUnloadTest$SpecialException: Very Special 3", + "java.lang.OutOfMemoryError", + "Java heap space", + "java.lang.NoClassDefFoundError: Could not initialize class InitExceptionUnloadTest$ThrowsOOM", + "Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.OutOfMemoryError: Java heap space [in thread" + }; + + static String[] classNames = new String[] { + "InitExceptionUnloadTest$ThrowsRuntimeException", + "InitExceptionUnloadTest$ThrowsError", + "InitExceptionUnloadTest$ThrowsSpecialException", + "InitExceptionUnloadTest$ThrowsOOM" }; + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + + static void test() throws Throwable { + ClassLoader cl = ClassUnloadCommon.newClassLoader(); + int i = 0; + for (String className : classNames) { + for (int tries = 2; tries-- > 0; ) { + System.err.println("--- try to load " + className); + try { + Class c = cl.loadClass(className); + Object inst = c.newInstance(); + } catch (Throwable t) { + t.printStackTrace(); + System.err.println(); + System.err.println("Check results"); + verify_stack(t, expected[i], expected[i+1]); + i += 2; + System.err.println(); + } + } + } + cl = null; + ClassUnloadCommon.triggerUnloading(); // should unload these classes + for (String className : classNames) { + ClassUnloadCommon.failIf(wb.isClassAlive(className), "should be unloaded"); + } + } + public static void main(java.lang.String[] unused) throws Throwable { + test(); + test(); + } +} diff --git a/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java b/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java index bbb70f8067a..6b54e0b49ef 100644 --- a/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java +++ b/test/hotspot/jtreg/runtime/Dictionary/CleanProtectionDomain.java @@ -24,6 +24,7 @@ /* * @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 sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java b/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java index 88a10c1feb2..756bff98ffb 100644 --- a/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java +++ b/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java @@ -26,6 +26,7 @@ * @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 diff --git a/test/hotspot/jtreg/runtime/InvocationTests/invocationC1Tests.java b/test/hotspot/jtreg/runtime/InvocationTests/invocationC1Tests.java index 759f7440840..c2bb6fdb200 100644 --- a/test/hotspot/jtreg/runtime/InvocationTests/invocationC1Tests.java +++ b/test/hotspot/jtreg/runtime/InvocationTests/invocationC1Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -26,6 +26,7 @@ * @test * @bug 8226956 * @summary Run invocation tests against C1 compiler + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/InvocationTests/invocationOldCHATests.java b/test/hotspot/jtreg/runtime/InvocationTests/invocationOldCHATests.java index 3326a72bb7d..3b0811859bd 100644 --- a/test/hotspot/jtreg/runtime/InvocationTests/invocationOldCHATests.java +++ b/test/hotspot/jtreg/runtime/InvocationTests/invocationOldCHATests.java @@ -25,6 +25,7 @@ /* * @test * @summary Run invocation tests with old CHA (-XX:-UseVtableBasedCHA) + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/InvocationTests/invokeinterfaceTests.java b/test/hotspot/jtreg/runtime/InvocationTests/invokeinterfaceTests.java index 5efccfeaa19..1ccd5e86873 100644 --- a/test/hotspot/jtreg/runtime/InvocationTests/invokeinterfaceTests.java +++ b/test/hotspot/jtreg/runtime/InvocationTests/invokeinterfaceTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -26,6 +26,7 @@ * @test * @bug 8224137 * @summary Run invokeinterface invocation tests + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/InvocationTests/invokespecialTests.java b/test/hotspot/jtreg/runtime/InvocationTests/invokespecialTests.java index a37cca5681c..aaed97f2d3c 100644 --- a/test/hotspot/jtreg/runtime/InvocationTests/invokespecialTests.java +++ b/test/hotspot/jtreg/runtime/InvocationTests/invokespecialTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -26,6 +26,7 @@ * @test * @bug 8224137 * @summary Run invokespecial invocation tests + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/InvocationTests/invokevirtualTests.java b/test/hotspot/jtreg/runtime/InvocationTests/invokevirtualTests.java index a8892ad42d7..6f34a928c27 100644 --- a/test/hotspot/jtreg/runtime/InvocationTests/invokevirtualTests.java +++ b/test/hotspot/jtreg/runtime/InvocationTests/invokevirtualTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -26,6 +26,7 @@ * @test * @bug 8224137 * @summary Run invokevirtual invocation tests + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.org.objectweb.asm * java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeEnvVarTest.java b/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeEnvVarTest.java index 1ee57875588..eb8698295f9 100644 --- a/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeEnvVarTest.java +++ b/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeEnvVarTest.java @@ -25,6 +25,7 @@ * @test * @bug 8260349 * @summary test that setting via the env-var and options file shows up as expected + * @requires vm.flagless * @library /test/lib * @run driver MaxMetaspaceSizeEnvVarTest */ diff --git a/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeTest.java b/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeTest.java index fd589cba0a0..32aaa34db50 100644 --- a/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeTest.java +++ b/test/hotspot/jtreg/runtime/Metaspace/MaxMetaspaceSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -27,6 +27,7 @@ /* * @test MaxMetaspaceSizeTest * @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true + * @requires vm.flagless * @bug 8087291 * @library /test/lib * @run driver MaxMetaspaceSizeTest diff --git a/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java b/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java index 1260234f164..6bae009a84d 100644 --- a/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java @@ -29,6 +29,7 @@ * @test * @bug 8226416 * @summary Test the MonitorUsedDeflationThreshold and NoAsyncDeflationProgressMax options. + * @requires vm.flagless * @modules java.base/jdk.internal.misc * @library /test/lib * @run driver MonitorUsedDeflationThresholdTest diff --git a/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java b/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java index ffa05b01bc0..394a92c0398 100644 --- a/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java @@ -30,6 +30,7 @@ * @test * @bug 8242263 * @summary Exercise DiagnoseSyncOnValueBasedClasses diagnostic flag + * @requires vm.flagless * @library /test/lib * @run driver/timeout=180000 SyncOnValueBasedClassTest */ diff --git a/test/hotspot/jtreg/runtime/PerfMemDestroy/PerfMemDestroy.java b/test/hotspot/jtreg/runtime/PerfMemDestroy/PerfMemDestroy.java index a2e3362644e..2040c755576 100644 --- a/test/hotspot/jtreg/runtime/PerfMemDestroy/PerfMemDestroy.java +++ b/test/hotspot/jtreg/runtime/PerfMemDestroy/PerfMemDestroy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,6 +25,7 @@ * @test * @bug 8030955 * @summary Allow multiple calls to PerfMemory::destroy() without asserting. + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/runtime/PrintStringTableStats/PrintStringTableStatsTest.java b/test/hotspot/jtreg/runtime/PrintStringTableStats/PrintStringTableStatsTest.java index f72a8088896..1425e3e6eb1 100644 --- a/test/hotspot/jtreg/runtime/PrintStringTableStats/PrintStringTableStatsTest.java +++ b/test/hotspot/jtreg/runtime/PrintStringTableStats/PrintStringTableStatsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -27,6 +27,7 @@ /* * @test PrintStringTableStatsTest * @bug 8211821 + * @requires vm.flagless * @library /test/lib * @run driver PrintStringTableStatsTest */ diff --git a/test/hotspot/jtreg/runtime/Safepoint/TestAbortOnVMOperationTimeout.java b/test/hotspot/jtreg/runtime/Safepoint/TestAbortOnVMOperationTimeout.java index 004df31f2f0..5518f76c5bf 100644 --- a/test/hotspot/jtreg/runtime/Safepoint/TestAbortOnVMOperationTimeout.java +++ b/test/hotspot/jtreg/runtime/Safepoint/TestAbortOnVMOperationTimeout.java @@ -28,6 +28,7 @@ * @test TestAbortOnVMOperationTimeout * @bug 8181143 8269523 * @summary Check abort on VM timeout is working + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/runtime/Safepoint/TestAbortVMOnSafepointTimeout.java b/test/hotspot/jtreg/runtime/Safepoint/TestAbortVMOnSafepointTimeout.java index ee51458757c..a06c5ba007d 100644 --- a/test/hotspot/jtreg/runtime/Safepoint/TestAbortVMOnSafepointTimeout.java +++ b/test/hotspot/jtreg/runtime/Safepoint/TestAbortVMOnSafepointTimeout.java @@ -30,6 +30,7 @@ * @test TestAbortVMOnSafepointTimeout * @summary Check if VM can kill thread which doesn't reach safepoint. * @bug 8219584 8227528 + * @requires vm.flagless * @library /testlibrary /test/lib * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/runtime/Thread/Fibonacci.java b/test/hotspot/jtreg/runtime/Thread/Fibonacci.java index 271295a73cc..a7ff3f76879 100644 --- a/test/hotspot/jtreg/runtime/Thread/Fibonacci.java +++ b/test/hotspot/jtreg/runtime/Thread/Fibonacci.java @@ -28,6 +28,7 @@ * This test is skipped on 32-bit Windows: limited virtual space on Win-32 * make this test inherently unstable on Windows with 32-bit VM data model. * @requires !(os.family == "windows" & sun.arch.data.model == "32") + * @requires !(os.family == "linux" & os.maxMemory < 512M) * @modules java.base/jdk.internal.misc * @library /test/lib * @run main/othervm Fibonacci 15 diff --git a/test/hotspot/jtreg/runtime/cds/MaxMetaspaceSize.java b/test/hotspot/jtreg/runtime/cds/MaxMetaspaceSize.java index cbae5d22e3c..c59449d6b1c 100644 --- a/test/hotspot/jtreg/runtime/cds/MaxMetaspaceSize.java +++ b/test/hotspot/jtreg/runtime/cds/MaxMetaspaceSize.java @@ -24,6 +24,7 @@ /** * @test * @requires vm.cds + * @requires vm.flagless * @bug 8067187 8200078 * @summary Testing CDS dumping with the -XX:MaxMetaspaceSize= option * @library /test/lib diff --git a/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java b/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java index efaa18b9734..e832fa600b7 100644 --- a/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java +++ b/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -49,9 +49,9 @@ public static void main(String[] args) throws Exception { CDSTestUtils.createArchiveAndCheck(opts); // Some mach5 tiers run with -vmoptions:-Xlog:cds=debug. This would cause the outputs to mismatch. - // Force -Xlog:cds=warning to supress the CDS logs. + // Force the log level to warning for all tags to supressed the CDS logs. Also disable the timestamp. opts.setUseVersion(false); - opts.addSuffix("-showversion", "-Xlog:cds=warning", "ServiceLoaderApp"); + opts.addSuffix("-showversion", "-Xlog:all=warning::level,tags", "ServiceLoaderApp"); OutputAnalyzer out1 = CDSTestUtils.runWithArchive(opts); opts.setXShareMode("off"); diff --git a/test/hotspot/jtreg/runtime/cds/SharedStrings.java b/test/hotspot/jtreg/runtime/cds/SharedStrings.java index 92d210c429e..c314ea89218 100644 --- a/test/hotspot/jtreg/runtime/cds/SharedStrings.java +++ b/test/hotspot/jtreg/runtime/cds/SharedStrings.java @@ -26,6 +26,7 @@ * @summary Check to make sure that shared strings in the bootstrap CDS archive * are actually shared * @requires vm.cds.archived.java.heap + * @requires vm.flagless * @library /test/lib * @build SharedStringsWb sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/runtime/cds/SharedStringsWb.java b/test/hotspot/jtreg/runtime/cds/SharedStringsWb.java index 735731872e9..f3932e94021 100644 --- a/test/hotspot/jtreg/runtime/cds/SharedStringsWb.java +++ b/test/hotspot/jtreg/runtime/cds/SharedStringsWb.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,8 +29,8 @@ public class SharedStringsWb { public static void main(String[] args) throws Exception { WhiteBox wb = WhiteBox.getWhiteBox(); - if (wb.areSharedStringsIgnored()) { - System.out.println("Shared strings are ignored, assuming PASS"); + if (!wb.areSharedStringsMapped()) { + System.out.println("Shared strings are not mapped, assuming PASS"); return; } @@ -43,7 +43,7 @@ public static void main(String[] args) throws Exception { throw new RuntimeException("Shared string is not a valid String: FAIL"); } - if (wb.isShared(internedS)) { + if (wb.isSharedInternedString(internedS)) { System.out.println("Found shared string, result: PASS"); } else { throw new RuntimeException("String is not shared, result: FAIL"); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/DumpClassList.java b/test/hotspot/jtreg/runtime/cds/appcds/DumpClassList.java index aa7e9d07822..cad0baa8c9f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/DumpClassList.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/DumpClassList.java @@ -27,8 +27,9 @@ * @summary DumpLoadedClassList should exclude generated classes, classes in bootclasspath/a and * --patch-module. * @requires vm.cds + * @modules jdk.jfr * @library /test/lib - * @compile test-classes/ArrayListTest.java + * @compile test-classes/DumpClassListApp.java * @run driver DumpClassList */ @@ -40,25 +41,25 @@ public class DumpClassList { public static void main(String[] args) throws Exception { // build The app - String[] appClass = new String[] {"ArrayListTest"}; + String[] appClass = new String[] {"DumpClassListApp"}; String classList = "app.list"; JarBuilder.build("app", appClass[0]); String appJar = TestCommon.getTestJar("app.jar"); // build patch-module - String source = "package java.lang; " + + String source = "package jdk.jfr; " + "public class NewClass { " + " static { " + " System.out.println(\"NewClass\"); "+ " } " + "}"; - ClassFileInstaller.writeClassToDisk("java/lang/NewClass", - InMemoryJavaCompiler.compile("java.lang.NewClass", source, "--patch-module=java.base"), + ClassFileInstaller.writeClassToDisk("jdk/jfr/NewClass", + InMemoryJavaCompiler.compile("jdk.jfr.NewClass", source, "--patch-module=jdk.jfr"), System.getProperty("test.classes")); - String patchJar = JarBuilder.build("javabase", "java/lang/NewClass"); + String patchJar = JarBuilder.build("jdk_jfr", "jdk/jfr/NewClass"); // build bootclasspath/a String source2 = "package boot.append; " + @@ -76,7 +77,7 @@ public static void main(String[] args) throws Exception { // dump class list CDSTestUtils.dumpClassList(classList, - "--patch-module=java.base=" + patchJar, + "--patch-module=jdk.jfr=" + patchJar, "-Xbootclasspath/a:" + appendJar, "-cp", appJar, @@ -90,10 +91,14 @@ public static void main(String[] args) throws Exception { .addPrefix("-cp", appJar, "-Xbootclasspath/a:" + appendJar, "-Xlog:class+load", + "-Xlog:cds+class=debug", "-XX:SharedClassListFile=" + classList); CDSTestUtils.createArchiveAndCheck(opts) .shouldNotContain("Preload Warning: Cannot find java/lang/invoke/LambdaForm") .shouldNotContain("Preload Warning: Cannot find boot/append/Foo") - .shouldContain("[info][class,load] boot.append.Foo"); + .shouldNotContain("Preload Warning: Cannot find jdk/jfr/NewClass") + .shouldMatch("class,load *. boot.append.Foo") // from -Xlog:class+load + .shouldMatch("cds,class.*boot boot.append.Foo") // from -Xlog:cds+class + .shouldNotMatch("class,load *. jdk.jfr.NewClass"); // from -Xlog:class+load } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/MoveJDKTest.java b/test/hotspot/jtreg/runtime/cds/appcds/MoveJDKTest.java index fc4ac4ee9be..c5ad8e53873 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/MoveJDKTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/MoveJDKTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -25,17 +25,16 @@ /* * @test * @summary Test that CDS still works when the JDK is moved to a new directory + * @bug 8272345 * @requires vm.cds - * @requires os.family == "linux" + * @requires vm.flagless + * @comment This test doesn't work on Windows because it depends on symlinks + * @requires os.family != "windows" * @library /test/lib * @compile test-classes/Hello.java * @run driver MoveJDKTest */ -// This test works only on Linux because it depends on symlinks and the name of the hotspot DLL (libjvm.so). -// It probably doesn't work on Windows. -// TODO: change libjvm.so to libjvm.dylib on MacOS, before adding "@requires os.family == mac" - import java.io.File; import java.nio.file.Files; import java.nio.file.Path; @@ -54,7 +53,8 @@ public static void main(String[] args) throws Exception { String jsaOpt = "-XX:SharedArchiveFile=" + jsaFile; { ProcessBuilder pb = makeBuilder(java_home_src + "/bin/java", "-Xshare:dump", jsaOpt); - TestCommon.executeAndLog(pb, "dump"); + TestCommon.executeAndLog(pb, "dump") + .shouldHaveExitValue(0); } { ProcessBuilder pb = makeBuilder(java_home_src + "/bin/java", @@ -63,6 +63,7 @@ public static void main(String[] args) throws Exception { "-Xlog:class+path=info", "-version"); OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-src"); + out.shouldHaveExitValue(0); out.shouldNotContain("shared class paths mismatch"); out.shouldNotContain("BOOT classpath mismatch"); } @@ -78,6 +79,7 @@ public static void main(String[] args) throws Exception { "-Xlog:class+path=info", "-version"); OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-dst"); + out.shouldHaveExitValue(0); out.shouldNotContain("shared class paths mismatch"); out.shouldNotContain("BOOT classpath mismatch"); } @@ -91,7 +93,8 @@ public static void main(String[] args) throws Exception { "-Xshare:dump", dumptimeBootAppendOpt, jsaOpt); - TestCommon.executeAndLog(pb, "dump"); + TestCommon.executeAndLog(pb, "dump") + .shouldHaveExitValue(0); } { String runtimeBootAppendOpt = dumptimeBootAppendOpt + System.getProperty("path.separator") + helloJar; @@ -102,6 +105,7 @@ public static void main(String[] args) throws Exception { "-Xlog:class+path=info", "-version"); OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-dst"); + out.shouldHaveExitValue(0); out.shouldNotContain("shared class paths mismatch"); out.shouldNotContain("BOOT classpath mismatch"); } @@ -129,6 +133,7 @@ static void clone(File src, File dst) throws Exception { throw new RuntimeException("Cannot create directory: " + dst); } } + final String jvmLib = System.mapLibraryName("jvm"); for (String child : src.list()) { if (child.equals(".") || child.equals("..")) { continue; @@ -140,7 +145,7 @@ static void clone(File src, File dst) throws Exception { throw new RuntimeException("Already exists: " + child_dst); } if (child_src.isFile()) { - if (child.equals("libjvm.so") || child.equals("java")) { + if (child.equals(jvmLib) || child.equals("java")) { Files.copy(child_src.toPath(), /* copy data to -> */ child_dst.toPath()); } else { Files.createSymbolicLink(child_dst.toPath(), /* link to -> */ child_src.toPath()); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/VerifyWithDefaultArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/VerifyWithDefaultArchive.java index 0ac2d0b8f15..aa65bb38b1c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/VerifyWithDefaultArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/VerifyWithDefaultArchive.java @@ -26,6 +26,7 @@ * @test * @bug 8264337 * @summary test default cds archive when turning on VerifySharedSpaces + * @requires vm.flagless * @requires vm.cds * @library /test/lib * @run driver VerifyWithDefaultArchive diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java index 19e0f36daa1..1469dd4dd17 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java @@ -25,6 +25,7 @@ * @test * @summary Test archived module graph with custom runtime image * @requires vm.cds.archived.java.heap + * @requires vm.flagless * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @build sun.hotspot.WhiteBox * @compile CheckArchivedModuleApp.java diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/GCStressApp.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/GCStressApp.java index 824c88be2da..0f8f4af34df 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/GCStressApp.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/GCStressApp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -62,8 +62,8 @@ public static void main(String args[]) throws Exception { return; } - if (wb.areSharedStringsIgnored()) { - System.out.println("Shared strings are ignored."); + if (!wb.areSharedStringsMapped()) { + System.out.println("Shared strings are not mapped."); return; } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/RedefineClassApp.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/RedefineClassApp.java index 2441cf47085..8286aa7bda1 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/RedefineClassApp.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/RedefineClassApp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -55,7 +55,7 @@ public String get() { static Instrumentation instrumentation; public static void main(String args[]) throws Throwable { - if (wb.areSharedStringsIgnored()) { + if (!wb.areSharedStringsMapped()) { System.out.println("Shared strings are ignored."); return; } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomClassListDump.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomClassListDump.java new file mode 100644 index 00000000000..625ef1fbc92 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomClassListDump.java @@ -0,0 +1,127 @@ +/* + * 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. + * + */ + +/* + * @test + * @summary -XX:DumpLoadedClassList should support custom loaders + * @bug 8265602 + * @requires vm.cds + * @requires vm.cds.custom.loaders + * @library /test/lib + * /test/hotspot/jtreg/runtime/cds/appcds + * /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * test-classes + * @build CustomLoaderApp OldClass CustomLoadee CustomLoadee2 + * CustomLoadee3Child CustomLoadee4WithLambda + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar CustomLoaderApp + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar custom.jar + * OldClass CustomLoadee + * CustomLoadee2 CustomInterface2_ia CustomInterface2_ib + * CustomLoadee3 CustomLoadee3Child + * CustomLoadee4WithLambda + * @run driver CustomClassListDump + */ + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class CustomClassListDump { + private static String appJar = ClassFileInstaller.getJarPath("app.jar"); + private static String customJar = ClassFileInstaller.getJarPath("custom.jar"); + private static String classList = "app.list"; + private static String commandLine[] = { + "-cp", appJar, + "CustomLoaderApp", + customJar, + "unregistered", + "CustomLoadee", + "CustomLoadee2", + "CustomLoadee3Child", + "CustomLoadee4WithLambda", + "OldClass", + }; + + public static void main(String[] args) throws Exception { + // Dump the classlist and check that custom-loader classes are in there. + CDSTestUtils.dumpClassList(classList, commandLine) + .assertNormalExit(); + + String listData = new String(Files.readAllBytes(Paths.get(classList))); + check(listData, true, "CustomLoaderApp id: [0-9]+"); + check(listData, true, "CustomLoadee id: [0-9]+ super: [0-9]+ source: .*/custom.jar"); + check(listData, true, "CustomInterface2_ia id: [0-9]+ super: [0-9]+ source: .*/custom.jar"); + check(listData, true, "CustomInterface2_ib id: [0-9]+ super: [0-9]+ source: .*/custom.jar"); + check(listData, true, "CustomLoadee2 id: [0-9]+ super: [0-9]+ interfaces: [0-9]+ [0-9]+ source: .*/custom.jar"); + check(listData, true, "CustomLoadee3 id: [0-9]+ super: [0-9]+ source: .*/custom.jar"); + check(listData, true, "CustomLoadee3Child id: [0-9]+ super: [0-9]+ source: .*/custom.jar"); + check(listData, true, "CustomLoadee4WithLambda id: [0-9]+ super: [0-9]+ source: .*/custom.jar"); + + // We don't support archiving of Lambda proxies for custom loaders. + check(listData, false, "@lambda-proxy.*CustomLoadee4WithLambda"); + + // Dump the static archive + CDSOptions opts = (new CDSOptions()) + .addPrefix("-cp", appJar, + "-Xlog:cds+class=debug", + "-XX:SharedClassListFile=" + classList); + CDSTestUtils.createArchiveAndCheck(opts) + .shouldContain("unreg CustomLoadee") + .shouldContain("unreg CustomLoadee2") + .shouldContain("unreg CustomLoadee3Child") + .shouldContain("unreg OldClass ** unlinked"); + + // Use the dumped static archive + opts = (new CDSOptions()) + .setUseVersion(false) + .addPrefix("-cp", appJar) + .addSuffix("-Xlog:class+load,verification") + .addSuffix(commandLine); + CDSTestUtils.run(opts) + .assertNormalExit("CustomLoadee source: shared objects file", + "CustomLoadee2 source: shared objects file", + "CustomLoadee3Child source: shared objects file", + "OldClass source: shared objects file", + "Verifying class OldClass with old format"); + } + + static void check(String listData, boolean mustMatch, String regexp) throws Exception { + Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE); + Matcher matcher = pattern.matcher(listData); + boolean found = matcher.find(); + if (mustMatch && !found) { + System.out.println(listData); + throw new RuntimeException("Pattern \"" + regexp + "\" not found in classlist"); + } + + if (!mustMatch && found) { + throw new RuntimeException("Pattern \"" + regexp + "\" found in in classlist: \"" + + matcher.group() + "\""); + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomLoaderApp.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomLoaderApp.java index 9db26328140..e6bc33997ba 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomLoaderApp.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/CustomLoaderApp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -63,15 +63,18 @@ public static void main(String[] args) throws Exception { String loaderType = args[1]; log("loaderType = " + loaderType); - String testClass = args[2]; - log("testClass = " + testClass); - switch(loaderType) { - case "unregistered": - loadAndUseWithUnregisteredLoader(urls, testClass); - break; - default: - throw new IllegalArgumentException("loader type is wrong: " + loaderType); + for (int i = 2; i < args.length; i++) { + String testClass = args[i]; + log("testClass = " + testClass); + + switch(loaderType) { + case "unregistered": + loadAndUseWithUnregisteredLoader(urls, testClass); + break; + default: + throw new IllegalArgumentException("loader type is wrong: " + loaderType); + } } } @@ -87,7 +90,7 @@ private static void loadAndUseWithUnregisteredLoader(URL[] urls, String testClas private static Class loadAndCheck(ClassLoader loader, String className) throws ClassNotFoundException { Class c = loader.loadClass(className); - log("class =" + c); + log("class = " + c); log("loader = " + c.getClassLoader()); // Check that c is defined by the correct loader diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/CustomLoadee4WithLambda.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/CustomLoadee4WithLambda.java new file mode 100644 index 00000000000..1cf916a5360 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/CustomLoadee4WithLambda.java @@ -0,0 +1,35 @@ +/* + * 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. + * + */ + +public class CustomLoadee4WithLambda { + public static void test() { + doit(() -> { + System.out.println("Hello inside a Lambda expression"); + }); + } + + static void doit(Runnable r) { + r.run(); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCSharedStringsDuringDumpWb.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCSharedStringsDuringDumpWb.java index f0cbc1dc495..93ec0c78a26 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCSharedStringsDuringDumpWb.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCSharedStringsDuringDumpWb.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -38,7 +38,7 @@ public static void main(String[] args) throws Exception { } public static void CheckString(WhiteBox wb, String s) { - if (!wb.areSharedStringsIgnored() && !wb.isShared(s)) { + if (wb.areSharedStringsMapped() && !wb.isSharedInternedString(s)) { throw new RuntimeException("String is not shared."); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java index 974c32e57ca..febc70aea0e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java @@ -27,6 +27,7 @@ * @bug 8259070 * @summary Test jcmd to dump dynamic shared archive. * @requires vm.cds + * @requires vm.flagless * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @modules jdk.jcmd/sun.tools.common:+open * @compile ../test-classes/Hello.java JCmdTestDumpBase.java diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/ExerciseGC.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/ExerciseGC.java index 966ba40cd96..95677d66a6c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/ExerciseGC.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/ExerciseGC.java @@ -26,6 +26,7 @@ * @test * @summary Exercise GC with shared strings * @requires vm.cds.archived.java.heap + * @requires vm.gc == null * @library /test/hotspot/jtreg/runtime/cds/appcds /test/lib * @build HelloStringGC sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/FlagCombo.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/FlagCombo.java index 886a46f1c17..f25c488223d 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/FlagCombo.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/FlagCombo.java @@ -26,6 +26,7 @@ * @test * @summary Test relevant combinations of command line flags with shared strings * @requires vm.cds.archived.java.heap & vm.hasJFR + * @requires vm.gc == null * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @build HelloString * @run driver FlagCombo @@ -36,6 +37,7 @@ * @summary Test relevant combinations of command line flags with shared strings * @comment A special test excluding the case that requires JFR * @requires vm.cds.archived.java.heap & !vm.hasJFR + * @requires vm.gc == null * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @build HelloString * @run driver FlagCombo noJfr diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/HelloStringGC.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/HelloStringGC.java index 74327128138..90f66565e97 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/HelloStringGC.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/HelloStringGC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -33,7 +33,7 @@ public static void main(String args[]) throws RuntimeException { String testString2 = "test123"; WhiteBox wb = WhiteBox.getWhiteBox(); - if (!wb.isShared(testString1) && !wb.areSharedStringsIgnored()) { + if (wb.areSharedStringsMapped() && !wb.isSharedInternedString(testString1)) { throw new RuntimeException("testString1 is not shared"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/HelloStringPlus.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/HelloStringPlus.java index 1449cfb1645..e6156b3b18b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/HelloStringPlus.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/HelloStringPlus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -34,7 +34,7 @@ public static void main(String args[]) { System.out.println("Hello String: " + testString1); WhiteBox wb = WhiteBox.getWhiteBox(); - if (!wb.isShared(testString1) && !wb.areSharedStringsIgnored()) { + if (wb.areSharedStringsMapped() && !wb.isSharedInternedString(testString1)) { throw new RuntimeException("testString1 is not shared"); } @@ -66,7 +66,7 @@ public static void main(String args[]) { // Check intern() method for "" string String empty = ""; String empty_interned = empty.intern(); - if (!wb.isShared(empty)) { + if (wb.areSharedStringsMapped() && !wb.isSharedInternedString(empty)) { throw new RuntimeException("Empty string should be shared"); } if (empty_interned != empty) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java index 58bfdcf8c7f..ec05d0b06b0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java @@ -26,6 +26,7 @@ * @test * @summary Test shared strings together with string intern operation * @requires vm.cds.archived.java.heap + * @requires vm.gc == null * @library /test/hotspot/jtreg/runtime/cds/appcds /test/lib * @compile InternStringTest.java * @build sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternStringTest.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternStringTest.java index a49bf839cab..0f26a75a2e1 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternStringTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -38,10 +38,12 @@ public static void main(String[] args) throws Exception { // All string literals are shared. String shared1 = "LiveOak"; String interned1 = shared1.intern(); - if (wb.areSharedStringsIgnored() || wb.isShared(interned1)) { - System.out.println(passed_output1); - } else { - throw new RuntimeException("Failed: String is not shared."); + if (wb.areSharedStringsMapped()) { + if (wb.isSharedInternedString(interned1)) { + System.out.println(passed_output1); + } else { + throw new RuntimeException("Failed: String is not shared."); + } } // Test 2: shared_string1.intern() == shared_string2.intern() @@ -58,10 +60,12 @@ public static void main(String[] args) throws Exception { String a = "X" + latin1Sup.substring(1); String b = a.intern(); - if (wb.areSharedStringsIgnored() || wb.isShared(b)) { - System.out.println(passed_output3); - } else { - throw new RuntimeException("Failed: expected shared string with latin1-supplement chars."); + if (wb.areSharedStringsMapped()) { + if (wb.isSharedInternedString(b)) { + System.out.println(passed_output3); + } else { + throw new RuntimeException("Failed: expected shared string with latin1-supplement chars."); + } } } @@ -69,10 +73,12 @@ public static void main(String[] args) throws Exception { { String a = "X" + nonWestern.substring(1); String b = a.intern(); - if (wb.areSharedStringsIgnored() || wb.isShared(b)) { - System.out.println(passed_output4); - } else { - throw new RuntimeException("Failed: expected shared string with non-western chars."); + if (wb.areSharedStringsMapped()) { + if (wb.isSharedInternedString(b)) { + System.out.println(passed_output4); + } else { + throw new RuntimeException("Failed: expected shared string with non-western chars."); + } } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LargePages.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LargePages.java index 0a7d4d0a57b..630592bb9ae 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LargePages.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LargePages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,6 +26,7 @@ * @test * @summary Basic shared string test with large pages * @requires vm.cds.archived.java.heap + * @requires vm.gc == null * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @build HelloString * @run driver LargePages diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockSharedStrings.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockSharedStrings.java index d29a79854d4..1c8f3ed75bd 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockSharedStrings.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockSharedStrings.java @@ -26,6 +26,7 @@ * @test * @summary Test locking on shared strings * @requires vm.cds.archived.java.heap + * @requires vm.gc == null * @library /test/hotspot/jtreg/runtime/cds/appcds /test/lib * @compile LockStringTest.java LockStringValueTest.java * @build sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockStringTest.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockStringTest.java index 026368097ed..8c25445fe95 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockStringTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -31,13 +31,13 @@ public class LockStringTest extends Thread { public static void main(String[] args) throws Exception { - if (wb.areSharedStringsIgnored()) { - System.out.println("The shared strings are ignored"); + if (!wb.areSharedStringsMapped()) { + System.out.println("The shared strings are not mapped"); System.out.println("LockStringTest: PASS"); return; } - if (!wb.isShared(LockStringTest.class)) { + if (!wb.isSharedClass(LockStringTest.class)) { throw new RuntimeException("Failed: LockStringTest class is not shared."); } @@ -57,7 +57,7 @@ private static void doTest(String s, boolean hasZeroHashCode) throws Exception { lock = s; done = false; - if (!wb.isShared(lock)) { + if (!wb.isSharedInternedString(lock)) { throw new RuntimeException("Failed: String \"" + lock + "\" is not shared."); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockStringValueTest.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockStringValueTest.java index dc46faea878..c3898f82449 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockStringValueTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/LockStringValueTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -33,13 +33,13 @@ public static void main(String args[]) { String s = "LiveOak"; WhiteBox wb = WhiteBox.getWhiteBox(); - if (wb.areSharedStringsIgnored()) { - System.out.println("The shared strings are ignored"); + if (!wb.areSharedStringsMapped()) { + System.out.println("The shared strings are not mapped"); System.out.println("LockStringValueTest: PASS"); return; } - if (!wb.isShared(s)) { + if (!wb.isSharedInternedString(s)) { throw new RuntimeException("LockStringValueTest Failed: String is not shared."); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsBasicPlus.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsBasicPlus.java index 25ebe9c20c7..6209706a859 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsBasicPlus.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsBasicPlus.java @@ -26,6 +26,7 @@ * @test * @summary Basic plus test for shared strings * @requires vm.cds.archived.java.heap + * @requires vm.gc == null * @library /test/hotspot/jtreg/runtime/cds/appcds /test/lib * @build HelloStringPlus sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsWb.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsWb.java index c622a5f9766..8ed3374852b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsWb.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsWb.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -29,10 +29,12 @@ public static void main(String[] args) throws Exception { WhiteBox wb = WhiteBox.getWhiteBox(); String s = "shared_test_string_unique_14325"; s = s.intern(); - if (wb.areSharedStringsIgnored() || wb.isShared(s)) { - System.out.println("Found shared string."); - } else { - throw new RuntimeException("String is not shared."); + if (wb.areSharedStringsMapped()) { + if (wb.isSharedInternedString(s)) { + System.out.println("Found shared string."); + } else { + throw new RuntimeException("String is not shared."); + } } } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsWbTest.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsWbTest.java index 9f45997813a..dc486786b75 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsWbTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SharedStringsWbTest.java @@ -26,6 +26,7 @@ * @test * @summary White box test for shared strings * @requires vm.cds.archived.java.heap + * @requires vm.gc == null * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @build sun.hotspot.WhiteBox SharedStringsWb * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SysDictCrash.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SysDictCrash.java index ab3473777f4..2d45f7f8d59 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SysDictCrash.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SysDictCrash.java @@ -27,6 +27,7 @@ * @summary Regression test for JDK-8098821 * @bug 8098821 * @requires vm.cds.archived.java.heap + * @requires vm.gc == null * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds * @run driver SysDictCrash */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/ArrayListTest.java b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/DumpClassListApp.java similarity index 88% rename from test/hotspot/jtreg/runtime/cds/appcds/test-classes/ArrayListTest.java rename to test/hotspot/jtreg/runtime/cds/appcds/test-classes/DumpClassListApp.java index 5c441e9c30e..deab312e106 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/ArrayListTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/DumpClassListApp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,7 +26,7 @@ // This is a test case executed by DumpClassList.java to load classes // from various places to ensure that they are not written to the class list. -public class ArrayListTest { +public class DumpClassListApp { public static void main(String args[]) throws Exception { // The following lambda usage should generate various classes like // java.lang.invoke.LambdaForm$MH/1146743572. All of them should be excluded from @@ -35,7 +35,7 @@ public static void main(String args[]) throws Exception { a.add("hello world."); a.forEach(str -> System.out.println(str)); - System.out.println(Class.forName("java.lang.NewClass")); // should be excluded from the class list. + System.out.println(Class.forName("jdk.jfr.NewClass")); // should be excluded from the class list. System.out.println(Class.forName("boot.append.Foo")); // should be excluded from the class list. } } diff --git a/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java b/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java index cb9b03f77bb..e4153a8f392 100644 --- a/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java +++ b/test/hotspot/jtreg/runtime/logging/ClassInitializationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,6 +25,7 @@ /* * @test ClassInitializationTest * @bug 8142976 + * @requires vm.flagless * @modules java.base/jdk.internal.misc * @library /test/lib * @compile BadMap50.jasm @@ -45,6 +46,7 @@ public static void main(String... args) throws Exception { "-Xmx128m", "BadMap50"); OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldNotHaveExitValue(0); out.shouldContain("Start class verification for:"); out.shouldContain("End class verification for:"); out.shouldContain("Initializing"); @@ -69,6 +71,7 @@ public static void main(String... args) throws Exception { "-Xmx128m", "BadMap50"); out = new OutputAnalyzer(pb.start()); + out.shouldNotHaveExitValue(0); out.shouldNotContain("[class,init]"); out.shouldNotContain("Fail over class verification to old verifier for: BadMap50"); diff --git a/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java b/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java index eadbc94a1bd..3fd76953377 100644 --- a/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java +++ b/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java @@ -25,7 +25,7 @@ /* * @test ClassLoadUnloadTest * @bug 8142506 - * @requires vm.opt.final.ClassUnloading + * @requires vm.flagless * @modules java.base/jdk.internal.misc * @library /test/lib * @library classes @@ -78,6 +78,7 @@ static ProcessBuilder exec(String... args) throws Exception { Collections.addAll(argsList, args); Collections.addAll(argsList, "-Xmn8m"); Collections.addAll(argsList, "-Dtest.class.path=" + System.getProperty("test.class.path", ".")); + Collections.addAll(argsList, "-XX:+ClassUnloading"); Collections.addAll(argsList, ClassUnloadTestMain.class.getName()); return ProcessTools.createJavaProcessBuilder(argsList); } diff --git a/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java b/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java index 18b74e26353..05155e5108f 100644 --- a/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java +++ b/test/hotspot/jtreg/runtime/logging/ClassResolutionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,6 +25,7 @@ /* * @test ClassResolutionTest * @bug 8144874 + * @requires vm.flagless * @modules java.base/jdk.internal.misc * @library /test/lib * @run driver ClassResolutionTest @@ -62,6 +63,7 @@ public static void main(String... args) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:class+resolve=debug", ClassResolutionTestMain.class.getName()); OutputAnalyzer o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldContain("[class,resolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1"); o.shouldContain("[class,resolve] resolve JVM_CONSTANT_MethodHandle"); @@ -70,6 +72,7 @@ public static void main(String... args) throws Exception { "-Xlog:class+resolve=off", ClassResolutionTestMain.class.getName()); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldNotContain("[class,resolve]"); }; diff --git a/test/hotspot/jtreg/runtime/logging/CompressedOopsTest.java b/test/hotspot/jtreg/runtime/logging/CompressedOopsTest.java index c04734ebc4b..ee1a4997900 100644 --- a/test/hotspot/jtreg/runtime/logging/CompressedOopsTest.java +++ b/test/hotspot/jtreg/runtime/logging/CompressedOopsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -24,7 +24,8 @@ /* * @test * @bug 8149991 - * @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true + * @requires vm.bits == 64 + * @requires vm.flagless * @summary -Xlog:gc+heap+coops=info should have output from the code * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java b/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java index 61c0996b079..f94f5e5cb20 100644 --- a/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java +++ b/test/hotspot/jtreg/runtime/logging/CondyIndyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -24,6 +24,7 @@ /* * @test * @summary Test -Xlog:methodhandles with a test that contains both a condy and indy. + * @requires vm.flagless * @modules java.base/jdk.internal.misc * @library /test/lib * @compile CondyIndyMathOperation.jasm @@ -42,6 +43,7 @@ public static void main(String... args) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:methodhandles", "CondyIndy"); OutputAnalyzer o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldContain("[info][methodhandles"); o.shouldNotContain("[debug][methodhandles,indy"); o.shouldNotContain("[debug][methodhandles,condy"); @@ -50,6 +52,7 @@ public static void main(String... args) throws Exception { pb = ProcessTools.createJavaProcessBuilder("-Xlog:methodhandles+condy=debug", "CondyIndy"); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldNotContain("[info ][methodhandles"); o.shouldNotContain("[debug][methodhandles,indy"); o.shouldContain("[debug][methodhandles,condy"); @@ -58,6 +61,7 @@ public static void main(String... args) throws Exception { pb = ProcessTools.createJavaProcessBuilder("-Xlog:methodhandles+indy=debug", "CondyIndy"); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldNotContain("[info ][methodhandles"); o.shouldContain("[debug][methodhandles,indy"); o.shouldNotContain("[debug][methodhandles,condy"); @@ -68,6 +72,7 @@ public static void main(String... args) throws Exception { "-Xlog:methodhandles+indy=debug", "CondyIndy"); o = new OutputAnalyzer(pb.start()); + o.shouldHaveExitValue(0); o.shouldContain("[info ][methodhandles"); o.shouldContain("[debug][methodhandles,indy"); o.shouldContain("[debug][methodhandles,condy"); diff --git a/test/hotspot/jtreg/runtime/logging/DefaultMethodsTest.java b/test/hotspot/jtreg/runtime/logging/DefaultMethodsTest.java index 1f5ed9b5f6e..2ea7e6bb07a 100644 --- a/test/hotspot/jtreg/runtime/logging/DefaultMethodsTest.java +++ b/test/hotspot/jtreg/runtime/logging/DefaultMethodsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,6 +25,7 @@ * @test * @bug 8139564 8203960 * @summary defaultmethods=debug should have logging from each of the statements in the code + * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java b/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java index ab61fb8b7c3..976478253ee 100644 --- a/test/hotspot/jtreg/runtime/logging/ExceptionsTest.ja