mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-15 22:09:41 +01:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
532b1c732e | ||
|
|
1de8943731 | ||
|
|
50751da562 | ||
|
|
21cb2acda0 | ||
|
|
0e4422b284 | ||
|
|
1e985168d6 | ||
|
|
b8965318c1 | ||
|
|
afe6bd6910 | ||
|
|
b3b5595362 | ||
|
|
5e716fd7d1 | ||
|
|
3e93b98baf | ||
|
|
9a73987f9b | ||
|
|
8707167ef3 | ||
|
|
e3bd9c6e1c | ||
|
|
993215f3dd | ||
|
|
8a98738f44 | ||
|
|
ab01396209 | ||
|
|
92268e17be | ||
|
|
a98a5e54fc | ||
|
|
b245c517e3 | ||
|
|
0a151c68d6 | ||
|
|
554e38dd5a | ||
|
|
b5b0b3a33a | ||
|
|
0dc9e8447b | ||
|
|
12ffb0c131 | ||
|
|
eaaaae5be9 | ||
|
|
926c900efa | ||
|
|
658f80e392 | ||
|
|
274a2dd729 | ||
|
|
a84946dde4 | ||
|
|
fdb3e37c71 | ||
|
|
80cb773b7e | ||
|
|
a576952039 | ||
|
|
b89f364842 | ||
|
|
0694cc1d52 | ||
|
|
a3abaadc15 | ||
|
|
7cc1f82b84 | ||
|
|
636b56374e | ||
|
|
fe9efb75b0 | ||
|
|
ca6b165003 | ||
|
|
d5aa225451 | ||
|
|
79a85df074 | ||
|
|
41928aed7d | ||
|
|
3f6b0c69c3 | ||
|
|
36b185a930 | ||
|
|
c832f001e4 | ||
|
|
e5ac75a35b | ||
|
|
b79ca5f03b | ||
|
|
5bcea92eaa | ||
|
|
cc4e9716ac | ||
|
|
46cfc1e194 | ||
|
|
ae71782e77 | ||
|
|
753700182d | ||
|
|
eb727dcb51 | ||
|
|
b6cacfcbc8 | ||
|
|
d870a48880 | ||
|
|
2ea2f74f92 | ||
|
|
077ce2edc7 | ||
|
|
2a3294571a | ||
|
|
3877746eb9 | ||
|
|
3bd80fe3ba | ||
|
|
03232d4a5d | ||
|
|
4111730845 | ||
|
|
74ea38e406 | ||
|
|
839a91e14b | ||
|
|
aa4f79eaec | ||
|
|
c7df72ff0f | ||
|
|
80e066e733 |
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@@ -310,7 +310,7 @@ jobs:
|
||||
uses: ./.github/workflows/build-windows.yml
|
||||
with:
|
||||
platform: windows-x64
|
||||
msvc-toolset-version: '14.43'
|
||||
msvc-toolset-version: '14.44'
|
||||
msvc-toolset-architecture: 'x86.x64'
|
||||
configure-arguments: ${{ github.event.inputs.configure-arguments }}
|
||||
make-arguments: ${{ github.event.inputs.make-arguments }}
|
||||
@@ -322,7 +322,7 @@ jobs:
|
||||
uses: ./.github/workflows/build-windows.yml
|
||||
with:
|
||||
platform: windows-aarch64
|
||||
msvc-toolset-version: '14.43'
|
||||
msvc-toolset-version: '14.44'
|
||||
msvc-toolset-architecture: 'arm64'
|
||||
make-target: 'hotspot'
|
||||
extra-conf-options: '--openjdk-target=aarch64-unknown-cygwin'
|
||||
|
||||
4
make/autoconf/configure
vendored
4
make/autoconf/configure
vendored
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -366,7 +366,7 @@ EOT
|
||||
|
||||
# Print additional help, e.g. a list of toolchains and JVM features.
|
||||
# This must be done by the autoconf script.
|
||||
( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $generated_script PRINTF=printf )
|
||||
( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $generated_script PRINTF=printf ECHO=echo )
|
||||
|
||||
cat <<EOT
|
||||
|
||||
|
||||
@@ -456,13 +456,13 @@ SliderDemo.horizontal=Horizontal
|
||||
SliderDemo.vertical=Vertikal
|
||||
SliderDemo.plain=Einfach
|
||||
SliderDemo.a_plain_slider=Ein einfacher Schieberegler
|
||||
SliderDemo.majorticks=Grobteilungen
|
||||
SliderDemo.majorticksdescription=Ein Schieberegler mit Grobteilungsmarkierungen
|
||||
SliderDemo.ticks=Feinteilungen, Teilungen zum Einrasten und Labels
|
||||
SliderDemo.minorticks=Feinteilungen
|
||||
SliderDemo.minorticksdescription=Ein Schieberegler mit Grob- und Feinteilungen, mit Teilungen, in die der Schieberegler einrastet, wobei einige Teilungen mit einem sichtbaren Label versehen sind
|
||||
SliderDemo.majorticks=Hauptteilstriche
|
||||
SliderDemo.majorticksdescription=Ein Schieberegler mit Hauptteilstrichen
|
||||
SliderDemo.ticks=Hilfsteilstriche, zum Einrasten und Beschriften
|
||||
SliderDemo.minorticks=Hilfsteilstriche
|
||||
SliderDemo.minorticksdescription=Ein Schieberegler mit Haupt- und Hilfsteilstrichen, in die der Schieberegler einrastet, wobei einige Teilstriche mit einer sichtbaren Beschriftung versehen sind
|
||||
SliderDemo.disabled=Deaktiviert
|
||||
SliderDemo.disableddescription=Ein Schieberegler mit Grob- und Feinteilungen, der nicht aktiviert ist (kann nicht bearbeitet werden)
|
||||
SliderDemo.disableddescription=Ein Schieberegler mit Haupt- und Hilfsteilstrichen, der nicht aktiviert ist (kann nicht bearbeitet werden)
|
||||
|
||||
### SplitPane Demo ###
|
||||
|
||||
|
||||
@@ -3928,8 +3928,10 @@ void MacroAssembler::kernel_crc32_vpmsum_aligned(Register crc, Register buf, Reg
|
||||
Label L_outer_loop, L_inner_loop, L_last;
|
||||
|
||||
// Set DSCR pre-fetch to deepest.
|
||||
load_const_optimized(t0, VM_Version::_dscr_val | 7);
|
||||
mtdscr(t0);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
load_const_optimized(t0, VM_Version::_dscr_val | 7);
|
||||
mtdscr(t0);
|
||||
}
|
||||
|
||||
mtvrwz(VCRC, crc); // crc lives in VCRC, now
|
||||
|
||||
@@ -4073,8 +4075,10 @@ void MacroAssembler::kernel_crc32_vpmsum_aligned(Register crc, Register buf, Reg
|
||||
// ********** Main loop end **********
|
||||
|
||||
// Restore DSCR pre-fetch value.
|
||||
load_const_optimized(t0, VM_Version::_dscr_val);
|
||||
mtdscr(t0);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
load_const_optimized(t0, VM_Version::_dscr_val);
|
||||
mtdscr(t0);
|
||||
}
|
||||
|
||||
// ********** Simple loop for remaining 16 byte blocks **********
|
||||
{
|
||||
|
||||
@@ -952,8 +952,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address start_pc = __ pc();
|
||||
Register tmp1 = R6_ARG4;
|
||||
// probably copy stub would have changed value reset it.
|
||||
__ load_const_optimized(tmp1, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp1);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp1, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp1);
|
||||
}
|
||||
__ li(R3_RET, 0); // return 0
|
||||
__ blr();
|
||||
return start_pc;
|
||||
@@ -1070,9 +1072,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ dcbt(R3_ARG1, 0);
|
||||
|
||||
// If supported set DSCR pre-fetch to deepest.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
__ li(tmp1, 16);
|
||||
|
||||
// Backbranch target aligned to 32-byte. Not 16-byte align as
|
||||
@@ -1092,8 +1095,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ bdnz(l_10); // Dec CTR and loop if not zero.
|
||||
|
||||
// Restore DSCR pre-fetch value.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
|
||||
} // FasterArrayCopy
|
||||
|
||||
@@ -1344,8 +1349,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ dcbt(R3_ARG1, 0);
|
||||
|
||||
// If supported set DSCR pre-fetch to deepest.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
__ li(tmp1, 16);
|
||||
|
||||
// Backbranch target aligned to 32-byte. It's not aligned 16-byte
|
||||
@@ -1365,8 +1372,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ bdnz(l_9); // Dec CTR and loop if not zero.
|
||||
|
||||
// Restore DSCR pre-fetch value.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
|
||||
} // FasterArrayCopy
|
||||
__ bind(l_6);
|
||||
|
||||
@@ -1527,9 +1537,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ dcbt(R3_ARG1, 0);
|
||||
|
||||
// Set DSCR pre-fetch to deepest.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
__ li(tmp1, 16);
|
||||
|
||||
// Backbranch target aligned to 32-byte. Not 16-byte align as
|
||||
@@ -1549,9 +1560,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ bdnz(l_7); // Dec CTR and loop if not zero.
|
||||
|
||||
// Restore DSCR pre-fetch value.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
|
||||
} // FasterArrayCopy
|
||||
|
||||
@@ -1672,9 +1684,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ dcbt(R3_ARG1, 0);
|
||||
|
||||
// Set DSCR pre-fetch to deepest.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
__ li(tmp1, 16);
|
||||
|
||||
// Backbranch target aligned to 32-byte. Not 16-byte align as
|
||||
@@ -1694,8 +1707,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ bdnz(l_4);
|
||||
|
||||
// Restore DSCR pre-fetch value.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
|
||||
__ cmpwi(CR0, R5_ARG3, 0);
|
||||
__ beq(CR0, l_6);
|
||||
@@ -1788,9 +1803,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ dcbt(R3_ARG1, 0);
|
||||
|
||||
// Set DSCR pre-fetch to deepest.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
__ li(tmp1, 16);
|
||||
|
||||
// Backbranch target aligned to 32-byte. Not 16-byte align as
|
||||
@@ -1810,8 +1826,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ bdnz(l_5); // Dec CTR and loop if not zero.
|
||||
|
||||
// Restore DSCR pre-fetch value.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
|
||||
} // FasterArrayCopy
|
||||
|
||||
@@ -1910,9 +1928,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ dcbt(R3_ARG1, 0);
|
||||
|
||||
// Set DSCR pre-fetch to deepest.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
__ li(tmp1, 16);
|
||||
|
||||
// Backbranch target aligned to 32-byte. Not 16-byte align as
|
||||
@@ -1932,8 +1951,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ bdnz(l_4);
|
||||
|
||||
// Restore DSCR pre-fetch value.
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
__ load_const_optimized(tmp2, VM_Version::_dscr_val);
|
||||
__ mtdscr(tmp2);
|
||||
}
|
||||
|
||||
__ cmpwi(CR0, R5_ARG3, 0);
|
||||
__ beq(CR0, l_1);
|
||||
|
||||
@@ -80,7 +80,9 @@ void VM_Version::initialize() {
|
||||
"%zu on this machine", PowerArchitecturePPC64);
|
||||
|
||||
// Power 8: Configure Data Stream Control Register.
|
||||
config_dscr();
|
||||
if (VM_Version::has_mfdscr()) {
|
||||
config_dscr();
|
||||
}
|
||||
|
||||
if (!UseSIGTRAP) {
|
||||
MSG(TrapBasedICMissChecks);
|
||||
@@ -170,7 +172,8 @@ void VM_Version::initialize() {
|
||||
// Create and print feature-string.
|
||||
char buf[(num_features+1) * 16]; // Max 16 chars per feature.
|
||||
jio_snprintf(buf, sizeof(buf),
|
||||
"ppc64 sha aes%s%s",
|
||||
"ppc64 sha aes%s%s%s",
|
||||
(has_mfdscr() ? " mfdscr" : ""),
|
||||
(has_darn() ? " darn" : ""),
|
||||
(has_brw() ? " brw" : "")
|
||||
// Make sure number of %s matches num_features!
|
||||
@@ -488,6 +491,7 @@ void VM_Version::determine_features() {
|
||||
uint32_t *code = (uint32_t *)a->pc();
|
||||
// Keep R3_ARG1 unmodified, it contains &field (see below).
|
||||
// Keep R4_ARG2 unmodified, it contains offset = 0 (see below).
|
||||
a->mfdscr(R0);
|
||||
a->darn(R7);
|
||||
a->brw(R5, R6);
|
||||
a->blr();
|
||||
@@ -524,6 +528,7 @@ void VM_Version::determine_features() {
|
||||
|
||||
// determine which instructions are legal.
|
||||
int feature_cntr = 0;
|
||||
if (code[feature_cntr++]) features |= mfdscr_m;
|
||||
if (code[feature_cntr++]) features |= darn_m;
|
||||
if (code[feature_cntr++]) features |= brw_m;
|
||||
|
||||
|
||||
@@ -32,12 +32,14 @@
|
||||
class VM_Version: public Abstract_VM_Version {
|
||||
protected:
|
||||
enum Feature_Flag {
|
||||
mfdscr,
|
||||
darn,
|
||||
brw,
|
||||
num_features // last entry to count features
|
||||
};
|
||||
enum Feature_Flag_Set {
|
||||
unknown_m = 0,
|
||||
mfdscr_m = (1 << mfdscr ),
|
||||
darn_m = (1 << darn ),
|
||||
brw_m = (1 << brw ),
|
||||
all_features_m = (unsigned long)-1
|
||||
@@ -67,8 +69,9 @@ public:
|
||||
|
||||
static bool is_determine_features_test_running() { return _is_determine_features_test_running; }
|
||||
// CPU instruction support
|
||||
static bool has_darn() { return (_features & darn_m) != 0; }
|
||||
static bool has_brw() { return (_features & brw_m) != 0; }
|
||||
static bool has_mfdscr() { return (_features & mfdscr_m) != 0; } // Power8, but may be unavailable (QEMU)
|
||||
static bool has_darn() { return (_features & darn_m) != 0; }
|
||||
static bool has_brw() { return (_features & brw_m) != 0; }
|
||||
|
||||
// Assembler testing
|
||||
static void allow_all();
|
||||
|
||||
@@ -2170,15 +2170,13 @@ void C2_MacroAssembler::enc_cmove_cmp_fp(int cmpFlag, FloatRegister op1, FloatRe
|
||||
cmov_cmp_fp_le(op1, op2, dst, src, is_single);
|
||||
break;
|
||||
case BoolTest::ge:
|
||||
assert(false, "Should go to BoolTest::le case");
|
||||
ShouldNotReachHere();
|
||||
cmov_cmp_fp_ge(op1, op2, dst, src, is_single);
|
||||
break;
|
||||
case BoolTest::lt:
|
||||
cmov_cmp_fp_lt(op1, op2, dst, src, is_single);
|
||||
break;
|
||||
case BoolTest::gt:
|
||||
assert(false, "Should go to BoolTest::lt case");
|
||||
ShouldNotReachHere();
|
||||
cmov_cmp_fp_gt(op1, op2, dst, src, is_single);
|
||||
break;
|
||||
default:
|
||||
assert(false, "unsupported compare condition");
|
||||
|
||||
@@ -1268,12 +1268,19 @@ void MacroAssembler::cmov_gtu(Register cmp1, Register cmp2, Register dst, Regist
|
||||
}
|
||||
|
||||
// ----------- cmove, compare float -----------
|
||||
//
|
||||
// For CmpF/D + CMoveI/L, ordered ones are quite straight and simple,
|
||||
// so, just list behaviour of unordered ones as follow.
|
||||
//
|
||||
// Set dst (CMoveI (Binary cop (CmpF/D op1 op2)) (Binary dst src))
|
||||
// (If one or both inputs to the compare are NaN, then)
|
||||
// 1. (op1 lt op2) => true => CMove: dst = src
|
||||
// 2. (op1 le op2) => true => CMove: dst = src
|
||||
// 3. (op1 gt op2) => false => CMove: dst = dst
|
||||
// 4. (op1 ge op2) => false => CMove: dst = dst
|
||||
// 5. (op1 eq op2) => false => CMove: dst = dst
|
||||
// 6. (op1 ne op2) => true => CMove: dst = src
|
||||
|
||||
// Move src to dst only if cmp1 == cmp2,
|
||||
// otherwise leave dst unchanged, including the case where one of them is NaN.
|
||||
// Clarification:
|
||||
// java code : cmp1 != cmp2 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 eq cmp2), dst, src
|
||||
void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
|
||||
if (UseZicond) {
|
||||
if (is_single) {
|
||||
@@ -1289,7 +1296,7 @@ void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
Label no_set;
|
||||
if (is_single) {
|
||||
// jump if cmp1 != cmp2, including the case of NaN
|
||||
// not jump (i.e. move src to dst) if cmp1 == cmp2
|
||||
// fallthrough (i.e. move src to dst) if cmp1 == cmp2
|
||||
float_bne(cmp1, cmp2, no_set);
|
||||
} else {
|
||||
double_bne(cmp1, cmp2, no_set);
|
||||
@@ -1298,11 +1305,6 @@ void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// Keep dst unchanged only if cmp1 == cmp2,
|
||||
// otherwise move src to dst, including the case where one of them is NaN.
|
||||
// Clarification:
|
||||
// java code : cmp1 == cmp2 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 ne cmp2), dst, src
|
||||
void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
|
||||
if (UseZicond) {
|
||||
if (is_single) {
|
||||
@@ -1318,7 +1320,7 @@ void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
Label no_set;
|
||||
if (is_single) {
|
||||
// jump if cmp1 == cmp2
|
||||
// not jump (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN
|
||||
// fallthrough (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN
|
||||
float_beq(cmp1, cmp2, no_set);
|
||||
} else {
|
||||
double_beq(cmp1, cmp2, no_set);
|
||||
@@ -1327,14 +1329,6 @@ void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// When cmp1 <= cmp2 or any of them is NaN then dst = src, otherwise, dst = dst
|
||||
// Clarification
|
||||
// scenario 1:
|
||||
// java code : cmp2 < cmp1 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 le cmp2), dst, src
|
||||
// scenario 2:
|
||||
// java code : cmp1 > cmp2 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 le cmp2), dst, src
|
||||
void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
|
||||
if (UseZicond) {
|
||||
if (is_single) {
|
||||
@@ -1350,7 +1344,7 @@ void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
Label no_set;
|
||||
if (is_single) {
|
||||
// jump if cmp1 > cmp2
|
||||
// not jump (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN
|
||||
// fallthrough (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN
|
||||
float_bgt(cmp1, cmp2, no_set);
|
||||
} else {
|
||||
double_bgt(cmp1, cmp2, no_set);
|
||||
@@ -1359,14 +1353,30 @@ void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// When cmp1 < cmp2 or any of them is NaN then dst = src, otherwise, dst = dst
|
||||
// Clarification
|
||||
// scenario 1:
|
||||
// java code : cmp2 <= cmp1 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src
|
||||
// scenario 2:
|
||||
// java code : cmp1 >= cmp2 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src
|
||||
void MacroAssembler::cmov_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
|
||||
if (UseZicond) {
|
||||
if (is_single) {
|
||||
fle_s(t0, cmp2, cmp1);
|
||||
} else {
|
||||
fle_d(t0, cmp2, cmp1);
|
||||
}
|
||||
czero_nez(dst, dst, t0);
|
||||
czero_eqz(t0 , src, t0);
|
||||
orr(dst, dst, t0);
|
||||
return;
|
||||
}
|
||||
Label no_set;
|
||||
if (is_single) {
|
||||
// jump if cmp1 < cmp2 or either is NaN
|
||||
// fallthrough (i.e. move src to dst) if cmp1 >= cmp2
|
||||
float_blt(cmp1, cmp2, no_set, false, true);
|
||||
} else {
|
||||
double_blt(cmp1, cmp2, no_set, false, true);
|
||||
}
|
||||
mv(dst, src);
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
|
||||
if (UseZicond) {
|
||||
if (is_single) {
|
||||
@@ -1382,7 +1392,7 @@ void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
Label no_set;
|
||||
if (is_single) {
|
||||
// jump if cmp1 >= cmp2
|
||||
// not jump (i.e. move src to dst) if cmp1 < cmp2 or either is NaN
|
||||
// fallthrough (i.e. move src to dst) if cmp1 < cmp2 or either is NaN
|
||||
float_bge(cmp1, cmp2, no_set);
|
||||
} else {
|
||||
double_bge(cmp1, cmp2, no_set);
|
||||
@@ -1391,6 +1401,30 @@ void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
|
||||
if (UseZicond) {
|
||||
if (is_single) {
|
||||
flt_s(t0, cmp2, cmp1);
|
||||
} else {
|
||||
flt_d(t0, cmp2, cmp1);
|
||||
}
|
||||
czero_nez(dst, dst, t0);
|
||||
czero_eqz(t0 , src, t0);
|
||||
orr(dst, dst, t0);
|
||||
return;
|
||||
}
|
||||
Label no_set;
|
||||
if (is_single) {
|
||||
// jump if cmp1 <= cmp2 or either is NaN
|
||||
// fallthrough (i.e. move src to dst) if cmp1 > cmp2
|
||||
float_ble(cmp1, cmp2, no_set, false, true);
|
||||
} else {
|
||||
double_ble(cmp1, cmp2, no_set, false, true);
|
||||
}
|
||||
mv(dst, src);
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// Float compare branch instructions
|
||||
|
||||
#define INSN(NAME, FLOATCMP, BRANCH) \
|
||||
|
||||
@@ -660,7 +660,9 @@ class MacroAssembler: public Assembler {
|
||||
void cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
|
||||
void cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
|
||||
void cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
|
||||
void cmov_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
|
||||
void cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
|
||||
void cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
|
||||
|
||||
public:
|
||||
// We try to follow risc-v asm menomics.
|
||||
|
||||
@@ -4655,6 +4655,7 @@ static void convertF2I_slowpath(C2_MacroAssembler& masm, C2GeneralStub<Register,
|
||||
__ subptr(rsp, 8);
|
||||
__ movdbl(Address(rsp), src);
|
||||
__ call(RuntimeAddress(target));
|
||||
// APX REX2 encoding for pop(dst) increases the stub size by 1 byte.
|
||||
__ pop(dst);
|
||||
__ jmp(stub.continuation());
|
||||
#undef __
|
||||
@@ -4687,7 +4688,9 @@ void C2_MacroAssembler::convertF2I(BasicType dst_bt, BasicType src_bt, Register
|
||||
}
|
||||
}
|
||||
|
||||
auto stub = C2CodeStub::make<Register, XMMRegister, address>(dst, src, slowpath_target, 23, convertF2I_slowpath);
|
||||
// Using the APX extended general purpose registers increases the instruction encoding size by 1 byte.
|
||||
int max_size = 23 + (UseAPX ? 1 : 0);
|
||||
auto stub = C2CodeStub::make<Register, XMMRegister, address>(dst, src, slowpath_target, max_size, convertF2I_slowpath);
|
||||
jcc(Assembler::equal, stub->entry());
|
||||
bind(stub->continuation());
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_blob(final, 31000 \
|
||||
do_arch_blob(final, 33000 \
|
||||
WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)) \
|
||||
|
||||
#endif // CPU_X86_STUBDECLARATIONS_HPP
|
||||
|
||||
@@ -46,6 +46,12 @@
|
||||
//
|
||||
/******************************************************************************/
|
||||
|
||||
/* Represents 0x7FFFFFFFFFFFFFFF double precision in lower 64 bits*/
|
||||
ATTRIBUTE_ALIGNED(16) static const juint _ABS_MASK[] =
|
||||
{
|
||||
4294967295, 2147483647, 0, 0
|
||||
};
|
||||
|
||||
ATTRIBUTE_ALIGNED(4) static const juint _SIG_MASK[] =
|
||||
{
|
||||
0, 1032192
|
||||
@@ -188,10 +194,10 @@ address StubGenerator::generate_libmCbrt() {
|
||||
StubCodeMark mark(this, stub_id);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_2TAG_PACKET_0_0_1, L_2TAG_PACKET_1_0_1, L_2TAG_PACKET_2_0_1, L_2TAG_PACKET_3_0_1;
|
||||
Label L_2TAG_PACKET_4_0_1, L_2TAG_PACKET_5_0_1, L_2TAG_PACKET_6_0_1;
|
||||
Label L_2TAG_PACKET_0_0_1, L_2TAG_PACKET_1_0_1, L_2TAG_PACKET_2_0_1;
|
||||
Label B1_1, B1_2, B1_4;
|
||||
|
||||
address ABS_MASK = (address)_ABS_MASK;
|
||||
address SIG_MASK = (address)_SIG_MASK;
|
||||
address EXP_MASK = (address)_EXP_MASK;
|
||||
address EXP_MSK2 = (address)_EXP_MSK2;
|
||||
@@ -208,8 +214,12 @@ address StubGenerator::generate_libmCbrt() {
|
||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||
|
||||
__ bind(B1_1);
|
||||
__ subq(rsp, 24);
|
||||
__ movsd(Address(rsp), xmm0);
|
||||
__ ucomisd(xmm0, ExternalAddress(ZERON), r11 /*rscratch*/);
|
||||
__ jcc(Assembler::equal, L_2TAG_PACKET_1_0_1); // Branch only if x is +/- zero or NaN
|
||||
__ movq(xmm1, xmm0);
|
||||
__ andpd(xmm1, ExternalAddress(ABS_MASK), r11 /*rscratch*/);
|
||||
__ ucomisd(xmm1, ExternalAddress(INF), r11 /*rscratch*/);
|
||||
__ jcc(Assembler::equal, B1_4); // Branch only if x is +/- INF
|
||||
|
||||
__ bind(B1_2);
|
||||
__ movq(xmm7, xmm0);
|
||||
@@ -228,8 +238,6 @@ address StubGenerator::generate_libmCbrt() {
|
||||
__ andl(rdx, rax);
|
||||
__ cmpl(rdx, 0);
|
||||
__ jcc(Assembler::equal, L_2TAG_PACKET_0_0_1); // Branch only if |x| is denormalized
|
||||
__ cmpl(rdx, 524032);
|
||||
__ jcc(Assembler::equal, L_2TAG_PACKET_1_0_1); // Branch only if |x| is INF or NaN
|
||||
__ shrl(rdx, 8);
|
||||
__ shrq(r9, 8);
|
||||
__ andpd(xmm2, xmm0);
|
||||
@@ -297,8 +305,6 @@ address StubGenerator::generate_libmCbrt() {
|
||||
__ andl(rdx, rax);
|
||||
__ shrl(rdx, 8);
|
||||
__ shrq(r9, 8);
|
||||
__ cmpl(rdx, 0);
|
||||
__ jcc(Assembler::equal, L_2TAG_PACKET_3_0_1); // Branch only if |x| is zero
|
||||
__ andpd(xmm2, xmm0);
|
||||
__ andpd(xmm0, xmm5);
|
||||
__ orpd(xmm3, xmm2);
|
||||
@@ -322,41 +328,10 @@ address StubGenerator::generate_libmCbrt() {
|
||||
__ psllq(xmm7, 52);
|
||||
__ jmp(L_2TAG_PACKET_2_0_1);
|
||||
|
||||
__ bind(L_2TAG_PACKET_3_0_1);
|
||||
__ cmpq(r9, 0);
|
||||
__ jcc(Assembler::notEqual, L_2TAG_PACKET_4_0_1); // Branch only if x is negative zero
|
||||
__ xorpd(xmm0, xmm0);
|
||||
__ jmp(B1_4);
|
||||
|
||||
__ bind(L_2TAG_PACKET_4_0_1);
|
||||
__ movsd(xmm0, ExternalAddress(ZERON), r11 /*rscratch*/);
|
||||
__ jmp(B1_4);
|
||||
|
||||
__ bind(L_2TAG_PACKET_1_0_1);
|
||||
__ movl(rax, Address(rsp, 4));
|
||||
__ movl(rdx, Address(rsp));
|
||||
__ movl(rcx, rax);
|
||||
__ andl(rcx, 2147483647);
|
||||
__ cmpl(rcx, 2146435072);
|
||||
__ jcc(Assembler::above, L_2TAG_PACKET_5_0_1); // Branch only if |x| is NaN
|
||||
__ cmpl(rdx, 0);
|
||||
__ jcc(Assembler::notEqual, L_2TAG_PACKET_5_0_1); // Branch only if |x| is NaN
|
||||
__ cmpl(rax, 2146435072);
|
||||
__ jcc(Assembler::notEqual, L_2TAG_PACKET_6_0_1); // Branch only if x is negative INF
|
||||
__ movsd(xmm0, ExternalAddress(INF), r11 /*rscratch*/);
|
||||
__ jmp(B1_4);
|
||||
|
||||
__ bind(L_2TAG_PACKET_6_0_1);
|
||||
__ movsd(xmm0, ExternalAddress(NEG_INF), r11 /*rscratch*/);
|
||||
__ jmp(B1_4);
|
||||
|
||||
__ bind(L_2TAG_PACKET_5_0_1);
|
||||
__ movsd(xmm0, Address(rsp));
|
||||
__ addsd(xmm0, xmm0);
|
||||
__ movq(Address(rsp, 8), xmm0);
|
||||
|
||||
__ bind(B1_4);
|
||||
__ addq(rsp, 24);
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
|
||||
@@ -2111,7 +2111,7 @@ bool VM_Version::is_intel_cascade_lake() {
|
||||
// has improved implementation of 64-byte load/stores and so the default
|
||||
// threshold is set to 0 for these platforms.
|
||||
int VM_Version::avx3_threshold() {
|
||||
return (is_intel_family_core() &&
|
||||
return (is_intel_server_family() &&
|
||||
supports_serialize() &&
|
||||
FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold;
|
||||
}
|
||||
|
||||
@@ -10527,7 +10527,8 @@ instruct xorI_rReg_im1_ndd(rRegI dst, rRegI src, immI_M1 imm)
|
||||
// Xor Register with Immediate
|
||||
instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
// Strict predicate check to make selection of xorI_rReg_im1 cost agnostic if immI src is -1.
|
||||
predicate(!UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1);
|
||||
match(Set dst (XorI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
@@ -10541,7 +10542,8 @@ instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
|
||||
|
||||
instruct xorI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
// Strict predicate check to make selection of xorI_rReg_im1_ndd cost agnostic if immI src2 is -1.
|
||||
predicate(UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1);
|
||||
match(Set dst (XorI src1 src2));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
@@ -10559,6 +10561,7 @@ instruct xorI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
|
||||
predicate(UseAPX);
|
||||
match(Set dst (XorI (LoadI src1) src2));
|
||||
effect(KILL cr);
|
||||
ins_cost(150);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
|
||||
@@ -11201,7 +11204,8 @@ instruct xorL_rReg_im1_ndd(rRegL dst,rRegL src, immL_M1 imm)
|
||||
// Xor Register with Immediate
|
||||
instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
// Strict predicate check to make selection of xorL_rReg_im1 cost agnostic if immL32 src is -1.
|
||||
predicate(!UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L);
|
||||
match(Set dst (XorL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
@@ -11215,7 +11219,8 @@ instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
|
||||
|
||||
instruct xorL_rReg_rReg_imm(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
// Strict predicate check to make selection of xorL_rReg_im1_ndd cost agnostic if immL32 src2 is -1.
|
||||
predicate(UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L);
|
||||
match(Set dst (XorL src1 src2));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
@@ -11234,6 +11239,7 @@ instruct xorL_rReg_mem_imm(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
|
||||
match(Set dst (XorL (LoadL src1) src2));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
ins_cost(150);
|
||||
|
||||
format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
|
||||
ins_encode %{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,13 @@ class ValueNumberingVisitor: public InstructionVisitor {
|
||||
void do_Convert (Convert* x) { /* nothing to do */ }
|
||||
void do_NullCheck (NullCheck* x) { /* nothing to do */ }
|
||||
void do_TypeCast (TypeCast* x) { /* nothing to do */ }
|
||||
void do_NewInstance (NewInstance* x) { /* nothing to do */ }
|
||||
void do_NewInstance (NewInstance* x) {
|
||||
ciInstanceKlass* c = x->klass();
|
||||
if (c != nullptr && !c->is_initialized() &&
|
||||
(!c->is_loaded() || c->has_class_initializer())) {
|
||||
kill_memory();
|
||||
}
|
||||
}
|
||||
void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }
|
||||
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }
|
||||
void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
product(bool, AOTVerifyTrainingData, trueInDebug, DIAGNOSTIC, \
|
||||
"Verify archived training data") \
|
||||
\
|
||||
product(bool, AOTCompileEagerly, false, DIAGNOSTIC, \
|
||||
product(bool, AOTCompileEagerly, false, EXPERIMENTAL, \
|
||||
"Compile methods as soon as possible") \
|
||||
\
|
||||
/* AOT Code flags */ \
|
||||
|
||||
@@ -837,11 +837,10 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
|
||||
struct stat st;
|
||||
if (os::stat(AOTCache, &st) != 0) {
|
||||
tty->print_cr("AOTCache creation failed: %s", AOTCache);
|
||||
vm_exit(0);
|
||||
} else {
|
||||
tty->print_cr("AOTCache creation is complete: %s " INT64_FORMAT " bytes", AOTCache, (int64_t)(st.st_size));
|
||||
vm_exit(0);
|
||||
}
|
||||
vm_direct_exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,6 +549,11 @@ bool ciInstanceKlass::compute_has_trusted_loader() {
|
||||
return java_lang_ClassLoader::is_trusted_loader(loader_oop);
|
||||
}
|
||||
|
||||
bool ciInstanceKlass::has_class_initializer() {
|
||||
VM_ENTRY_MARK;
|
||||
return get_instanceKlass()->class_initializer() != nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciInstanceKlass::find_method
|
||||
//
|
||||
|
||||
@@ -231,6 +231,8 @@ public:
|
||||
ciInstanceKlass* unique_concrete_subklass();
|
||||
bool has_finalizable_subclass();
|
||||
|
||||
bool has_class_initializer();
|
||||
|
||||
bool contains_field_offset(int offset);
|
||||
|
||||
// Get the instance of java.lang.Class corresponding to
|
||||
|
||||
@@ -3738,6 +3738,7 @@ void ClassFileParser::apply_parsed_class_metadata(
|
||||
_cp->set_pool_holder(this_klass);
|
||||
this_klass->set_constants(_cp);
|
||||
this_klass->set_fieldinfo_stream(_fieldinfo_stream);
|
||||
this_klass->set_fieldinfo_search_table(_fieldinfo_search_table);
|
||||
this_klass->set_fields_status(_fields_status);
|
||||
this_klass->set_methods(_methods);
|
||||
this_klass->set_inner_classes(_inner_classes);
|
||||
@@ -3747,6 +3748,8 @@ void ClassFileParser::apply_parsed_class_metadata(
|
||||
this_klass->set_permitted_subclasses(_permitted_subclasses);
|
||||
this_klass->set_record_components(_record_components);
|
||||
|
||||
DEBUG_ONLY(FieldInfoStream::validate_search_table(_cp, _fieldinfo_stream, _fieldinfo_search_table));
|
||||
|
||||
// Delay the setting of _local_interfaces and _transitive_interfaces until after
|
||||
// initialize_supers() in fill_instance_klass(). It is because the _local_interfaces could
|
||||
// be shared with _transitive_interfaces and _transitive_interfaces may be shared with
|
||||
@@ -5054,6 +5057,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
|
||||
// note that is not safe to use the fields in the parser from this point on
|
||||
assert(nullptr == _cp, "invariant");
|
||||
assert(nullptr == _fieldinfo_stream, "invariant");
|
||||
assert(nullptr == _fieldinfo_search_table, "invariant");
|
||||
assert(nullptr == _fields_status, "invariant");
|
||||
assert(nullptr == _methods, "invariant");
|
||||
assert(nullptr == _inner_classes, "invariant");
|
||||
@@ -5274,6 +5278,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
||||
_super_klass(),
|
||||
_cp(nullptr),
|
||||
_fieldinfo_stream(nullptr),
|
||||
_fieldinfo_search_table(nullptr),
|
||||
_fields_status(nullptr),
|
||||
_methods(nullptr),
|
||||
_inner_classes(nullptr),
|
||||
@@ -5350,6 +5355,7 @@ void ClassFileParser::clear_class_metadata() {
|
||||
// deallocated if classfile parsing returns an error.
|
||||
_cp = nullptr;
|
||||
_fieldinfo_stream = nullptr;
|
||||
_fieldinfo_search_table = nullptr;
|
||||
_fields_status = nullptr;
|
||||
_methods = nullptr;
|
||||
_inner_classes = nullptr;
|
||||
@@ -5372,6 +5378,7 @@ ClassFileParser::~ClassFileParser() {
|
||||
if (_fieldinfo_stream != nullptr) {
|
||||
MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_stream);
|
||||
}
|
||||
MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_search_table);
|
||||
|
||||
if (_fields_status != nullptr) {
|
||||
MetadataFactory::free_array<FieldStatus>(_loader_data, _fields_status);
|
||||
@@ -5772,6 +5779,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
|
||||
_fieldinfo_stream =
|
||||
FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count,
|
||||
injected_fields_count, loader_data(), CHECK);
|
||||
_fieldinfo_search_table = FieldInfoStream::create_search_table(_cp, _fieldinfo_stream, _loader_data, CHECK);
|
||||
_fields_status =
|
||||
MetadataFactory::new_array<FieldStatus>(_loader_data, _temp_field_info->length(),
|
||||
FieldStatus(0), CHECK);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -123,6 +123,7 @@ class ClassFileParser {
|
||||
const InstanceKlass* _super_klass;
|
||||
ConstantPool* _cp;
|
||||
Array<u1>* _fieldinfo_stream;
|
||||
Array<u1>* _fieldinfo_search_table;
|
||||
Array<FieldStatus>* _fields_status;
|
||||
Array<Method*>* _methods;
|
||||
Array<u2>* _inner_classes;
|
||||
|
||||
@@ -301,7 +301,7 @@ void FieldLayout::reconstruct_layout(const InstanceKlass* ik, bool& has_instance
|
||||
BasicType last_type;
|
||||
int last_offset = -1;
|
||||
while (ik != nullptr) {
|
||||
for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) {
|
||||
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
||||
BasicType type = Signature::basic_type(fs.signature());
|
||||
// distinction between static and non-static fields is missing
|
||||
if (fs.access_flags().is_static()) continue;
|
||||
@@ -461,7 +461,7 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas
|
||||
bool found = false;
|
||||
const InstanceKlass* ik = super;
|
||||
while (!found && ik != nullptr) {
|
||||
for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) {
|
||||
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
||||
if (fs.offset() == b->offset()) {
|
||||
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
||||
b->offset(),
|
||||
|
||||
@@ -967,6 +967,13 @@ void java_lang_Class::fixup_mirror(Klass* k, TRAPS) {
|
||||
Array<u1>* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, k->class_loader_data(), CHECK);
|
||||
ik->set_fieldinfo_stream(new_fis);
|
||||
MetadataFactory::free_array<u1>(k->class_loader_data(), old_stream);
|
||||
|
||||
Array<u1>* old_table = ik->fieldinfo_search_table();
|
||||
Array<u1>* search_table = FieldInfoStream::create_search_table(ik->constants(), new_fis, k->class_loader_data(), CHECK);
|
||||
ik->set_fieldinfo_search_table(search_table);
|
||||
MetadataFactory::free_array<u1>(k->class_loader_data(), old_table);
|
||||
|
||||
DEBUG_ONLY(FieldInfoStream::validate_search_table(ik->constants(), new_fis, search_table));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/vmClasses.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/oopStorage.inline.hpp"
|
||||
#include "gc/shared/oopStorageSet.hpp"
|
||||
@@ -115,6 +116,7 @@ OopStorage* StringTable::_oop_storage;
|
||||
|
||||
static size_t _current_size = 0;
|
||||
static volatile size_t _items_count = 0;
|
||||
DEBUG_ONLY(static bool _disable_interning_during_cds_dump = false);
|
||||
|
||||
volatile bool _alt_hash = false;
|
||||
|
||||
@@ -346,6 +348,10 @@ bool StringTable::has_work() {
|
||||
return Atomic::load_acquire(&_has_work);
|
||||
}
|
||||
|
||||
size_t StringTable::items_count_acquire() {
|
||||
return Atomic::load_acquire(&_items_count);
|
||||
}
|
||||
|
||||
void StringTable::trigger_concurrent_work() {
|
||||
// Avoid churn on ServiceThread
|
||||
if (!has_work()) {
|
||||
@@ -504,6 +510,9 @@ oop StringTable::intern(const char* utf8_string, TRAPS) {
|
||||
}
|
||||
|
||||
oop StringTable::intern(const StringWrapper& name, TRAPS) {
|
||||
assert(!Atomic::load_acquire(&_disable_interning_during_cds_dump),
|
||||
"All threads that may intern strings should have been stopped before CDS starts copying the interned string table");
|
||||
|
||||
// shared table always uses java_lang_String::hash_code
|
||||
unsigned int hash = hash_wrapped_string(name);
|
||||
oop found_string = lookup_shared(name, hash);
|
||||
@@ -793,7 +802,7 @@ void StringTable::verify() {
|
||||
}
|
||||
|
||||
// Verification and comp
|
||||
class VerifyCompStrings : StackObj {
|
||||
class StringTable::VerifyCompStrings : StackObj {
|
||||
static unsigned string_hash(oop const& str) {
|
||||
return java_lang_String::hash_code_noupdate(str);
|
||||
}
|
||||
@@ -805,7 +814,7 @@ class VerifyCompStrings : StackObj {
|
||||
string_hash, string_equals> _table;
|
||||
public:
|
||||
size_t _errors;
|
||||
VerifyCompStrings() : _table(unsigned(_items_count / 8) + 1, 0 /* do not resize */), _errors(0) {}
|
||||
VerifyCompStrings() : _table(unsigned(items_count_acquire() / 8) + 1, 0 /* do not resize */), _errors(0) {}
|
||||
bool operator()(WeakHandle* val) {
|
||||
oop s = val->resolve();
|
||||
if (s == nullptr) {
|
||||
@@ -939,20 +948,31 @@ oop StringTable::lookup_shared(const jchar* name, int len) {
|
||||
return _shared_table.lookup(wrapped_name, java_lang_String::hash_code(name, len), 0);
|
||||
}
|
||||
|
||||
// This is called BEFORE we enter the CDS safepoint. We can allocate heap objects.
|
||||
// This should be called when we know no more strings will be added (which will be easy
|
||||
// to guarantee because CDS runs with a single Java thread. See JDK-8253495.)
|
||||
// This is called BEFORE we enter the CDS safepoint. We can still allocate Java object arrays to
|
||||
// be used by the shared strings table.
|
||||
void StringTable::allocate_shared_strings_array(TRAPS) {
|
||||
if (!CDSConfig::is_dumping_heap()) {
|
||||
return;
|
||||
}
|
||||
assert(CDSConfig::allow_only_single_java_thread(), "No more interned strings can be added");
|
||||
|
||||
if (_items_count > (size_t)max_jint) {
|
||||
fatal("Too many strings to be archived: %zu", _items_count);
|
||||
CompileBroker::wait_for_no_active_tasks();
|
||||
|
||||
precond(CDSConfig::allow_only_single_java_thread());
|
||||
|
||||
// At this point, no more strings will be added:
|
||||
// - There's only a single Java thread (this thread). It no longer executes Java bytecodes
|
||||
// so JIT compilation will eventually stop.
|
||||
// - CompileBroker has no more active tasks, so all JIT requests have been processed.
|
||||
|
||||
// This flag will be cleared after intern table dumping has completed, so we can run the
|
||||
// compiler again (for future AOT method compilation, etc).
|
||||
DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, true));
|
||||
|
||||
if (items_count_acquire() > (size_t)max_jint) {
|
||||
fatal("Too many strings to be archived: %zu", items_count_acquire());
|
||||
}
|
||||
|
||||
int total = (int)_items_count;
|
||||
int total = (int)items_count_acquire();
|
||||
size_t single_array_size = objArrayOopDesc::object_size(total);
|
||||
|
||||
log_info(aot)("allocated string table for %d strings", total);
|
||||
@@ -972,7 +992,7 @@ void StringTable::allocate_shared_strings_array(TRAPS) {
|
||||
// This can only happen if you have an extremely large number of classes that
|
||||
// refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern
|
||||
// but bail out for safety.
|
||||
log_error(aot)("Too many strings to be archived: %zu", _items_count);
|
||||
log_error(aot)("Too many strings to be archived: %zu", items_count_acquire());
|
||||
MetaspaceShared::unrecoverable_writing_error();
|
||||
}
|
||||
|
||||
@@ -1070,7 +1090,7 @@ oop StringTable::init_shared_strings_array() {
|
||||
|
||||
void StringTable::write_shared_table() {
|
||||
_shared_table.reset();
|
||||
CompactHashtableWriter writer((int)_items_count, ArchiveBuilder::string_stats());
|
||||
CompactHashtableWriter writer((int)items_count_acquire(), ArchiveBuilder::string_stats());
|
||||
|
||||
int index = 0;
|
||||
auto copy_into_shared_table = [&] (WeakHandle* val) {
|
||||
@@ -1084,6 +1104,8 @@ void StringTable::write_shared_table() {
|
||||
};
|
||||
_local_table->do_safepoint_scan(copy_into_shared_table);
|
||||
writer.dump(&_shared_table, "string");
|
||||
|
||||
DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, false));
|
||||
}
|
||||
|
||||
void StringTable::set_shared_strings_array_index(int root_index) {
|
||||
|
||||
@@ -40,7 +40,7 @@ class StringTableConfig;
|
||||
|
||||
class StringTable : AllStatic {
|
||||
friend class StringTableConfig;
|
||||
|
||||
class VerifyCompStrings;
|
||||
static volatile bool _has_work;
|
||||
|
||||
// Set if one bucket is out of balance due to hash algorithm deficiency
|
||||
@@ -74,6 +74,7 @@ private:
|
||||
|
||||
static void item_added();
|
||||
static void item_removed();
|
||||
static size_t items_count_acquire();
|
||||
|
||||
static oop intern(const StringWrapper& name, TRAPS);
|
||||
static oop do_intern(const StringWrapper& name, uintx hash, TRAPS);
|
||||
|
||||
@@ -344,6 +344,7 @@ AOTCodeCache::~AOTCodeCache() {
|
||||
_store_buffer = nullptr;
|
||||
}
|
||||
if (_table != nullptr) {
|
||||
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
|
||||
delete _table;
|
||||
_table = nullptr;
|
||||
}
|
||||
@@ -774,6 +775,9 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind
|
||||
// we need to take a lock to prevent race between compiler threads generating AOT code
|
||||
// and the main thread generating adapter
|
||||
MutexLocker ml(Compile_lock);
|
||||
if (!is_on()) {
|
||||
return false; // AOT code cache was already dumped and closed.
|
||||
}
|
||||
if (!cache->align_write()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1434,6 +1438,9 @@ AOTCodeAddressTable::~AOTCodeAddressTable() {
|
||||
if (_extrs_addr != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(address, _extrs_addr);
|
||||
}
|
||||
if (_stubs_addr != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(address, _stubs_addr);
|
||||
}
|
||||
if (_shared_blobs_addr != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(address, _shared_blobs_addr);
|
||||
}
|
||||
@@ -1485,6 +1492,7 @@ void AOTCodeCache::load_strings() {
|
||||
|
||||
int AOTCodeCache::store_strings() {
|
||||
if (_C_strings_used > 0) {
|
||||
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
|
||||
uint offset = _write_position;
|
||||
uint length = 0;
|
||||
uint* lengths = (uint *)reserve_bytes(sizeof(uint) * _C_strings_used);
|
||||
@@ -1510,15 +1518,17 @@ int AOTCodeCache::store_strings() {
|
||||
|
||||
const char* AOTCodeCache::add_C_string(const char* str) {
|
||||
if (is_on_for_dump() && str != nullptr) {
|
||||
return _cache->_table->add_C_string(str);
|
||||
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
|
||||
AOTCodeAddressTable* table = addr_table();
|
||||
if (table != nullptr) {
|
||||
return table->add_C_string(str);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
const char* AOTCodeAddressTable::add_C_string(const char* str) {
|
||||
if (_extrs_complete) {
|
||||
LogStreamHandle(Trace, aot, codecache, stringtable) log; // ctor outside lock
|
||||
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
|
||||
// Check previous strings address
|
||||
for (int i = 0; i < _C_strings_count; i++) {
|
||||
if (_C_strings_in[i] == str) {
|
||||
@@ -1535,9 +1545,7 @@ const char* AOTCodeAddressTable::add_C_string(const char* str) {
|
||||
_C_strings_in[_C_strings_count] = str;
|
||||
const char* dup = os::strdup(str);
|
||||
_C_strings[_C_strings_count++] = dup;
|
||||
if (log.is_enabled()) {
|
||||
log.print_cr("add_C_string: [%d] " INTPTR_FORMAT " '%s'", _C_strings_count, p2i(dup), dup);
|
||||
}
|
||||
log_trace(aot, codecache, stringtable)("add_C_string: [%d] " INTPTR_FORMAT " '%s'", _C_strings_count, p2i(dup), dup);
|
||||
return dup;
|
||||
} else {
|
||||
assert(false, "Number of C strings >= MAX_STR_COUNT");
|
||||
|
||||
@@ -136,6 +136,7 @@ private:
|
||||
public:
|
||||
AOTCodeAddressTable() :
|
||||
_extrs_addr(nullptr),
|
||||
_stubs_addr(nullptr),
|
||||
_shared_blobs_addr(nullptr),
|
||||
_C1_blobs_addr(nullptr),
|
||||
_extrs_length(0),
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "code/dependencies.hpp"
|
||||
#include "code/nativeInst.hpp"
|
||||
#include "code/nmethod.inline.hpp"
|
||||
#include "code/relocInfo.hpp"
|
||||
#include "code/scopeDesc.hpp"
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/compilationLog.hpp"
|
||||
@@ -1653,10 +1652,6 @@ void nmethod::maybe_print_nmethod(const DirectiveSet* directive) {
|
||||
}
|
||||
|
||||
void nmethod::print_nmethod(bool printmethod) {
|
||||
// Enter a critical section to prevent a race with deopts that patch code and updates the relocation info.
|
||||
// Unfortunately, we have to lock the NMethodState_lock before the tty lock due to the deadlock rules and
|
||||
// cannot lock in a more finely grained manner.
|
||||
ConditionalMutexLocker ml(NMethodState_lock, !NMethodState_lock->owned_by_self(), Mutex::_no_safepoint_check_flag);
|
||||
ttyLocker ttyl; // keep the following output all in one block
|
||||
if (xtty != nullptr) {
|
||||
xtty->begin_head("print_nmethod");
|
||||
@@ -2046,17 +2041,6 @@ bool nmethod::make_not_entrant(const char* reason) {
|
||||
// cache call.
|
||||
NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
|
||||
SharedRuntime::get_handle_wrong_method_stub());
|
||||
|
||||
// Update the relocation info for the patched entry.
|
||||
// First, get the old relocation info...
|
||||
RelocIterator iter(this, verified_entry_point(), verified_entry_point() + 8);
|
||||
if (iter.next() && iter.addr() == verified_entry_point()) {
|
||||
Relocation* old_reloc = iter.reloc();
|
||||
// ...then reset the iterator to update it.
|
||||
RelocIterator iter(this, verified_entry_point(), verified_entry_point() + 8);
|
||||
relocInfo::change_reloc_info_for_address(&iter, verified_entry_point(), old_reloc->type(),
|
||||
relocInfo::relocType::runtime_call_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (update_recompile_counts()) {
|
||||
|
||||
@@ -1750,6 +1750,10 @@ void CompileBroker::wait_for_completion(CompileTask* task) {
|
||||
}
|
||||
}
|
||||
|
||||
void CompileBroker::wait_for_no_active_tasks() {
|
||||
CompileTask::wait_for_no_active_tasks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize compiler thread(s) + compiler object(s). The postcondition
|
||||
* of this function is that the compiler runtimes are initialized and that
|
||||
|
||||
@@ -383,6 +383,9 @@ public:
|
||||
static bool is_compilation_disabled_forever() {
|
||||
return _should_compile_new_jobs == shutdown_compilation;
|
||||
}
|
||||
|
||||
static void wait_for_no_active_tasks();
|
||||
|
||||
static void handle_full_code_cache(CodeBlobType code_blob_type);
|
||||
// Ensures that warning is only printed once.
|
||||
static bool should_print_compiler_warning() {
|
||||
|
||||
@@ -37,12 +37,13 @@
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
|
||||
CompileTask* CompileTask::_task_free_list = nullptr;
|
||||
int CompileTask::_active_tasks = 0;
|
||||
|
||||
/**
|
||||
* Allocate a CompileTask, from the free list if possible.
|
||||
*/
|
||||
CompileTask* CompileTask::allocate() {
|
||||
MutexLocker locker(CompileTaskAlloc_lock);
|
||||
MonitorLocker locker(CompileTaskAlloc_lock);
|
||||
CompileTask* task = nullptr;
|
||||
|
||||
if (_task_free_list != nullptr) {
|
||||
@@ -56,6 +57,7 @@ CompileTask* CompileTask::allocate() {
|
||||
}
|
||||
assert(task->is_free(), "Task must be free.");
|
||||
task->set_is_free(false);
|
||||
_active_tasks++;
|
||||
return task;
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ CompileTask* CompileTask::allocate() {
|
||||
* Add a task to the free list.
|
||||
*/
|
||||
void CompileTask::free(CompileTask* task) {
|
||||
MutexLocker locker(CompileTaskAlloc_lock);
|
||||
MonitorLocker locker(CompileTaskAlloc_lock);
|
||||
if (!task->is_free()) {
|
||||
if ((task->_method_holder != nullptr && JNIHandles::is_weak_global_handle(task->_method_holder))) {
|
||||
JNIHandles::destroy_weak_global(task->_method_holder);
|
||||
@@ -79,6 +81,17 @@ void CompileTask::free(CompileTask* task) {
|
||||
task->set_is_free(true);
|
||||
task->set_next(_task_free_list);
|
||||
_task_free_list = task;
|
||||
_active_tasks--;
|
||||
if (_active_tasks == 0) {
|
||||
locker.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CompileTask::wait_for_no_active_tasks() {
|
||||
MonitorLocker locker(CompileTaskAlloc_lock);
|
||||
while (_active_tasks > 0) {
|
||||
locker.wait();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -83,6 +83,7 @@ class CompileTask : public CHeapObj<mtCompiler> {
|
||||
|
||||
private:
|
||||
static CompileTask* _task_free_list;
|
||||
static int _active_tasks;
|
||||
int _compile_id;
|
||||
Method* _method;
|
||||
jobject _method_holder;
|
||||
@@ -123,6 +124,7 @@ class CompileTask : public CHeapObj<mtCompiler> {
|
||||
|
||||
static CompileTask* allocate();
|
||||
static void free(CompileTask* task);
|
||||
static void wait_for_no_active_tasks();
|
||||
|
||||
int compile_id() const { return _compile_id; }
|
||||
Method* method() const { return _method; }
|
||||
|
||||
@@ -625,6 +625,34 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ShenandoahBarrierC2Support::is_anti_dependent_load_at_control(PhaseIdealLoop* phase, Node* maybe_load, Node* store,
|
||||
Node* control) {
|
||||
return maybe_load->is_Load() && phase->C->can_alias(store->adr_type(), phase->C->get_alias_index(maybe_load->adr_type())) &&
|
||||
phase->ctrl_or_self(maybe_load) == control;
|
||||
}
|
||||
|
||||
void ShenandoahBarrierC2Support::maybe_push_anti_dependent_loads(PhaseIdealLoop* phase, Node* maybe_store, Node* control, Unique_Node_List &wq) {
|
||||
if (!maybe_store->is_Store() && !maybe_store->is_LoadStore()) {
|
||||
return;
|
||||
}
|
||||
Node* mem = maybe_store->in(MemNode::Memory);
|
||||
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
|
||||
Node* u = mem->fast_out(i);
|
||||
if (is_anti_dependent_load_at_control(phase, u, maybe_store, control)) {
|
||||
wq.push(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahBarrierC2Support::push_data_inputs_at_control(PhaseIdealLoop* phase, Node* n, Node* ctrl, Unique_Node_List &wq) {
|
||||
for (uint i = 0; i < n->req(); i++) {
|
||||
Node* in = n->in(i);
|
||||
if (in != nullptr && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) {
|
||||
wq.push(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase) {
|
||||
// That both nodes have the same control is not sufficient to prove
|
||||
// domination, verify that there's no path from d to n
|
||||
@@ -639,22 +667,9 @@ bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node*
|
||||
if (m->is_Phi() && m->in(0)->is_Loop()) {
|
||||
assert(phase->ctrl_or_self(m->in(LoopNode::EntryControl)) != c, "following loop entry should lead to new control");
|
||||
} else {
|
||||
if (m->is_Store() || m->is_LoadStore()) {
|
||||
// Take anti-dependencies into account
|
||||
Node* mem = m->in(MemNode::Memory);
|
||||
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
|
||||
Node* u = mem->fast_out(i);
|
||||
if (u->is_Load() && phase->C->can_alias(m->adr_type(), phase->C->get_alias_index(u->adr_type())) &&
|
||||
phase->ctrl_or_self(u) == c) {
|
||||
wq.push(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint i = 0; i < m->req(); i++) {
|
||||
if (m->in(i) != nullptr && phase->ctrl_or_self(m->in(i)) == c) {
|
||||
wq.push(m->in(i));
|
||||
}
|
||||
}
|
||||
// Take anti-dependencies into account
|
||||
maybe_push_anti_dependent_loads(phase, m, c, wq);
|
||||
push_data_inputs_at_control(phase, m, c, wq);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1006,7 +1021,20 @@ void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* lo
|
||||
phase->register_new_node(val, ctrl);
|
||||
}
|
||||
|
||||
void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase) {
|
||||
void ShenandoahBarrierC2Support::collect_nodes_above_barrier(Unique_Node_List &nodes_above_barrier, PhaseIdealLoop* phase, Node* ctrl, Node* init_raw_mem) {
|
||||
nodes_above_barrier.clear();
|
||||
if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) {
|
||||
nodes_above_barrier.push(init_raw_mem);
|
||||
}
|
||||
for (uint next = 0; next < nodes_above_barrier.size(); next++) {
|
||||
Node* n = nodes_above_barrier.at(next);
|
||||
// Take anti-dependencies into account
|
||||
maybe_push_anti_dependent_loads(phase, n, ctrl, nodes_above_barrier);
|
||||
push_data_inputs_at_control(phase, n, ctrl, nodes_above_barrier);
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& nodes_above_barrier, uint last, PhaseIdealLoop* phase) {
|
||||
Node* ctrl = phase->get_ctrl(barrier);
|
||||
Node* init_raw_mem = fixer.find_mem(ctrl, barrier);
|
||||
|
||||
@@ -1017,30 +1045,17 @@ void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const Mem
|
||||
// control will be after the expanded barrier. The raw memory (if
|
||||
// its memory is control dependent on the barrier's input control)
|
||||
// must stay above the barrier.
|
||||
uses_to_ignore.clear();
|
||||
if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) {
|
||||
uses_to_ignore.push(init_raw_mem);
|
||||
}
|
||||
for (uint next = 0; next < uses_to_ignore.size(); next++) {
|
||||
Node *n = uses_to_ignore.at(next);
|
||||
for (uint i = 0; i < n->req(); i++) {
|
||||
Node* in = n->in(i);
|
||||
if (in != nullptr && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) {
|
||||
uses_to_ignore.push(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
collect_nodes_above_barrier(nodes_above_barrier, phase, ctrl, init_raw_mem);
|
||||
for (DUIterator_Fast imax, i = ctrl->fast_outs(imax); i < imax; i++) {
|
||||
Node* u = ctrl->fast_out(i);
|
||||
if (u->_idx < last &&
|
||||
u != barrier &&
|
||||
!u->depends_only_on_test() && // preserve dependency on test
|
||||
!uses_to_ignore.member(u) &&
|
||||
!nodes_above_barrier.member(u) &&
|
||||
(u->in(0) != ctrl || (!u->is_Region() && !u->is_Phi())) &&
|
||||
(ctrl->Opcode() != Op_CatchProj || u->Opcode() != Op_CreateEx)) {
|
||||
Node* old_c = phase->ctrl_or_self(u);
|
||||
Node* c = old_c;
|
||||
if (c != ctrl ||
|
||||
if (old_c != ctrl ||
|
||||
is_dominator_same_ctrl(old_c, barrier, u, phase) ||
|
||||
ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) {
|
||||
phase->igvn().rehash_node_delayed(u);
|
||||
@@ -1315,7 +1330,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
|
||||
|
||||
// Expand load-reference-barriers
|
||||
MemoryGraphFixer fixer(Compile::AliasIdxRaw, true, phase);
|
||||
Unique_Node_List uses_to_ignore;
|
||||
Unique_Node_List nodes_above_barriers;
|
||||
for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) {
|
||||
ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i);
|
||||
uint last = phase->C->unique();
|
||||
@@ -1410,7 +1425,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
|
||||
Node* out_val = val_phi;
|
||||
phase->register_new_node(val_phi, region);
|
||||
|
||||
fix_ctrl(lrb, region, fixer, uses, uses_to_ignore, last, phase);
|
||||
fix_ctrl(lrb, region, fixer, uses, nodes_above_barriers, last, phase);
|
||||
|
||||
ctrl = orig_ctrl;
|
||||
|
||||
|
||||
@@ -62,8 +62,12 @@ private:
|
||||
PhaseIdealLoop* phase, int flags);
|
||||
static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr,
|
||||
DecoratorSet decorators, PhaseIdealLoop* phase);
|
||||
|
||||
static void collect_nodes_above_barrier(Unique_Node_List &nodes_above_barrier, PhaseIdealLoop* phase, Node* ctrl,
|
||||
Node* init_raw_mem);
|
||||
|
||||
static void test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase);
|
||||
static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase);
|
||||
static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& nodes_above_barrier, uint last, PhaseIdealLoop* phase);
|
||||
|
||||
static Node* get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* lrb);
|
||||
public:
|
||||
@@ -76,6 +80,11 @@ public:
|
||||
static bool expand(Compile* C, PhaseIterGVN& igvn);
|
||||
static void pin_and_expand(PhaseIdealLoop* phase);
|
||||
|
||||
static void push_data_inputs_at_control(PhaseIdealLoop* phase, Node* n, Node* ctrl,
|
||||
Unique_Node_List &wq);
|
||||
static bool is_anti_dependent_load_at_control(PhaseIdealLoop* phase, Node* maybe_load, Node* store, Node* control);
|
||||
|
||||
static void maybe_push_anti_dependent_loads(PhaseIdealLoop* phase, Node* maybe_store, Node* control, Unique_Node_List &wq);
|
||||
#ifdef ASSERT
|
||||
static void verify(RootNode* root);
|
||||
#endif
|
||||
|
||||
@@ -183,6 +183,29 @@ void ShenandoahGenerationalHeap::stop() {
|
||||
regulator_thread()->stop();
|
||||
}
|
||||
|
||||
bool ShenandoahGenerationalHeap::requires_barriers(stackChunkOop obj) const {
|
||||
if (is_idle()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_concurrent_young_mark_in_progress() && is_in_young(obj) && !marking_context()->allocated_after_mark_start(obj)) {
|
||||
// We are marking young, this object is in young, and it is below the TAMS
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_in_old(obj)) {
|
||||
// Card marking barriers are required for objects in the old generation
|
||||
return true;
|
||||
}
|
||||
|
||||
if (has_forwarded_objects()) {
|
||||
// Object may have pointers that need to be updated
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShenandoahGenerationalHeap::evacuate_collection_set(bool concurrent) {
|
||||
ShenandoahRegionIterator regions;
|
||||
ShenandoahGenerationalEvacuationTask task(this, ®ions, concurrent, false /* only promote regions */);
|
||||
|
||||
@@ -128,6 +128,8 @@ public:
|
||||
|
||||
void stop() override;
|
||||
|
||||
bool requires_barriers(stackChunkOop obj) const override;
|
||||
|
||||
// Used for logging the result of a region transfer outside the heap lock
|
||||
struct TransferResult {
|
||||
bool success;
|
||||
|
||||
@@ -948,22 +948,24 @@
|
||||
<Field type="long" contentType="bytes" name="freeSize" label="Free Size" description="Free swap space" />
|
||||
</Event>
|
||||
|
||||
<Event name="ExecutionSample" category="Java Virtual Machine, Profiling" label="Method Profiling Sample" description="Snapshot of a threads state"
|
||||
<Event name="ExecutionSample" category="Java Virtual Machine, Profiling" label="Java Execution Sample"
|
||||
description="Snapshot of a thread executing Java code. Threads that are not executing Java code, including those waiting or executing native code, are not included."
|
||||
period="everyChunk">
|
||||
<Field type="Thread" name="sampledThread" label="Thread" />
|
||||
<Field type="StackTrace" name="stackTrace" label="Stack Trace" />
|
||||
<Field type="ThreadState" name="state" label="Thread State" />
|
||||
</Event>
|
||||
|
||||
<Event name="NativeMethodSample" category="Java Virtual Machine, Profiling" label="Method Profiling Sample Native" description="Snapshot of a threads state when in native"
|
||||
<Event name="NativeMethodSample" category="Java Virtual Machine, Profiling" label="Native Sample"
|
||||
description="Snapshot of a thread in native code, executing or waiting. Threads that are executing Java code are not included."
|
||||
period="everyChunk">
|
||||
<Field type="Thread" name="sampledThread" label="Thread" />
|
||||
<Field type="StackTrace" name="stackTrace" label="Stack Trace" />
|
||||
<Field type="ThreadState" name="state" label="Thread State" />
|
||||
</Event>
|
||||
|
||||
<Event name="CPUTimeSample" category="Java Virtual Machine, Profiling" label="CPU Time Method Sample"
|
||||
description="Snapshot of a threads state from the CPU time sampler. The throttle can be either an upper bound for the event emission rate, e.g. 100/s, or the cpu-time period, e.g. 10ms, with s, ms, us and ns supported as time units."
|
||||
<Event name="CPUTimeSample" category="Java Virtual Machine, Profiling" label="CPU Time Sample"
|
||||
description="Snapshot of a threads state from the CPU time sampler, both threads executing native and Java code are included. The throttle setting can be either an upper bound for the event emission rate, e.g. 100/s, or the cpu-time period, e.g. 10ms, with s, ms, us and ns supported as time units."
|
||||
throttle="true" thread="false" experimental="true" startTime="false">
|
||||
<Field type="StackTrace" name="stackTrace" label="Stack Trace" />
|
||||
<Field type="Thread" name="eventThread" label="Thread" />
|
||||
@@ -972,7 +974,7 @@
|
||||
<Field type="boolean" name="biased" label="Biased" description="The sample is safepoint-biased" />
|
||||
</Event>
|
||||
|
||||
<Event name="CPUTimeSamplesLost" category="Java Virtual Machine, Profiling" label="CPU Time Method Profiling Lost Samples" description="Records that the CPU time sampler lost samples"
|
||||
<Event name="CPUTimeSamplesLost" category="Java Virtual Machine, Profiling" label="CPU Time Samples Lost" description="Records that the CPU time sampler lost samples"
|
||||
thread="false" stackTrace="false" startTime="false" experimental="true">
|
||||
<Field type="int" name="lostSamples" label="Lost Samples" />
|
||||
<Field type="Thread" name="eventThread" label="Thread" />
|
||||
|
||||
@@ -79,7 +79,8 @@ JfrThreadLocal::JfrThreadLocal() :
|
||||
_enqueued_requests(false),
|
||||
_vthread(false),
|
||||
_notified(false),
|
||||
_dead(false)
|
||||
_dead(false),
|
||||
_sampling_critical_section(false)
|
||||
#ifdef LINUX
|
||||
,_cpu_timer(nullptr),
|
||||
_cpu_time_jfr_locked(UNLOCKED),
|
||||
|
||||
@@ -47,7 +47,6 @@ void VectorSet::init(Arena* arena) {
|
||||
|
||||
// Expand the existing set to a bigger size
|
||||
void VectorSet::grow(uint new_word_capacity) {
|
||||
_nesting.check(_set_arena); // Check if a potential reallocation in the arena is safe
|
||||
assert(new_word_capacity >= _size, "Should have been checked before, use maybe_grow?");
|
||||
assert(new_word_capacity < (1U << 30), "");
|
||||
uint x = next_power_of_2(new_word_capacity);
|
||||
|
||||
@@ -52,6 +52,7 @@ private:
|
||||
|
||||
// Grow vector to required word capacity
|
||||
void maybe_grow(uint new_word_capacity) {
|
||||
_nesting.check(_set_arena); // Check if a potential reallocation in the arena is safe
|
||||
if (new_word_capacity >= _size) {
|
||||
grow(new_word_capacity);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "cds/cdsConfig.hpp"
|
||||
#include "oops/fieldInfo.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "utilities/packedTable.hpp"
|
||||
|
||||
void FieldInfo::print(outputStream* os, ConstantPool* cp) {
|
||||
os->print_cr("index=%d name_index=%d name=%s signature_index=%d signature=%s offset=%d "
|
||||
@@ -37,8 +40,10 @@ void FieldInfo::print(outputStream* os, ConstantPool* cp) {
|
||||
field_flags().as_uint(),
|
||||
initializer_index(),
|
||||
generic_signature_index(),
|
||||
_field_flags.is_injected() ? lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8(),
|
||||
contended_group());
|
||||
_field_flags.is_generic() ? (_field_flags.is_injected() ?
|
||||
lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8()
|
||||
) : "",
|
||||
is_contended() ? contended_group() : 0);
|
||||
}
|
||||
|
||||
void FieldInfo::print_from_growable_array(outputStream* os, GrowableArray<FieldInfo>* array, ConstantPool* cp) {
|
||||
@@ -62,13 +67,17 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
|
||||
StreamSizer s;
|
||||
StreamFieldSizer sizer(&s);
|
||||
|
||||
assert(fields->length() == java_fields + injected_fields, "must be");
|
||||
|
||||
sizer.consumer()->accept_uint(java_fields);
|
||||
sizer.consumer()->accept_uint(injected_fields);
|
||||
for (int i = 0; i < fields->length(); i++) {
|
||||
FieldInfo* fi = fields->adr_at(i);
|
||||
sizer.map_field_info(*fi);
|
||||
}
|
||||
int storage_size = sizer.consumer()->position() + 1;
|
||||
// Originally there was an extra byte with 0 terminating the reading;
|
||||
// now we check limits instead.
|
||||
int storage_size = sizer.consumer()->position();
|
||||
Array<u1>* const fis = MetadataFactory::new_array<u1>(loader_data, storage_size, CHECK_NULL);
|
||||
|
||||
using StreamWriter = UNSIGNED5::Writer<Array<u1>*, int, ArrayHelper<Array<u1>*, int>>;
|
||||
@@ -79,15 +88,14 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
|
||||
writer.consumer()->accept_uint(java_fields);
|
||||
writer.consumer()->accept_uint(injected_fields);
|
||||
for (int i = 0; i < fields->length(); i++) {
|
||||
FieldInfo* fi = fields->adr_at(i);
|
||||
writer.map_field_info(*fi);
|
||||
writer.map_field_info(fields->at(i));
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
FieldInfoReader r(fis);
|
||||
int jfc = r.next_uint();
|
||||
int jfc, ifc;
|
||||
r.read_field_counts(&jfc, &ifc);
|
||||
assert(jfc == java_fields, "Must be");
|
||||
int ifc = r.next_uint();
|
||||
assert(ifc == injected_fields, "Must be");
|
||||
for (int i = 0; i < jfc + ifc; i++) {
|
||||
FieldInfo fi;
|
||||
@@ -113,30 +121,221 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
|
||||
return fis;
|
||||
}
|
||||
|
||||
GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count) {
|
||||
int length = FieldInfoStream::num_total_fields(fis);
|
||||
GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
|
||||
int FieldInfoStream::compare_name_and_sig(const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2) {
|
||||
int cmp = n1->fast_compare(n2);
|
||||
return cmp != 0 ? cmp : s1->fast_compare(s2);
|
||||
}
|
||||
|
||||
|
||||
// We use both name and signature during the comparison; while JLS require unique
|
||||
// names for fields, JVMS requires only unique name + signature combination.
|
||||
struct field_pos {
|
||||
Symbol* _name;
|
||||
Symbol* _signature;
|
||||
int _index;
|
||||
int _position;
|
||||
};
|
||||
|
||||
class FieldInfoSupplier: public PackedTableBuilder::Supplier {
|
||||
const field_pos* _positions;
|
||||
size_t _elements;
|
||||
|
||||
public:
|
||||
FieldInfoSupplier(const field_pos* positions, size_t elements): _positions(positions), _elements(elements) {}
|
||||
|
||||
bool next(uint32_t* key, uint32_t* value) override {
|
||||
if (_elements == 0) {
|
||||
return false;
|
||||
}
|
||||
*key = _positions->_position;
|
||||
*value = _positions->_index;
|
||||
++_positions;
|
||||
--_elements;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Array<u1>* FieldInfoStream::create_search_table(ConstantPool* cp, const Array<u1>* fis, ClassLoaderData* loader_data, TRAPS) {
|
||||
if (CDSConfig::is_dumping_dynamic_archive()) {
|
||||
// We cannot use search table; in case of dynamic archives it should be sorted by "requested" addresses,
|
||||
// but Symbol* addresses are coming from _constants, which has "buffered" addresses.
|
||||
// For background, see new comments inside allocate_node_impl in symbolTable.cpp
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FieldInfoReader r(fis);
|
||||
*java_fields_count = r.next_uint();
|
||||
*injected_fields_count = r.next_uint();
|
||||
int java_fields;
|
||||
int injected_fields;
|
||||
r.read_field_counts(&java_fields, &injected_fields);
|
||||
assert(java_fields >= 0, "must be");
|
||||
if (java_fields == 0 || fis->length() == 0 || static_cast<uint>(java_fields) < BinarySearchThreshold) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ResourceMark rm;
|
||||
field_pos* positions = NEW_RESOURCE_ARRAY(field_pos, java_fields);
|
||||
for (int i = 0; i < java_fields; ++i) {
|
||||
assert(r.has_next(), "number of fields must match");
|
||||
|
||||
positions[i]._position = r.position();
|
||||
FieldInfo fi;
|
||||
r.read_field_info(fi);
|
||||
|
||||
positions[i]._name = fi.name(cp);
|
||||
positions[i]._signature = fi.signature(cp);
|
||||
positions[i]._index = i;
|
||||
}
|
||||
auto compare_pair = [](const void* v1, const void* v2) {
|
||||
const field_pos* p1 = reinterpret_cast<const field_pos*>(v1);
|
||||
const field_pos* p2 = reinterpret_cast<const field_pos*>(v2);
|
||||
return compare_name_and_sig(p1->_name, p1->_signature, p2->_name, p2->_signature);
|
||||
};
|
||||
qsort(positions, java_fields, sizeof(field_pos), compare_pair);
|
||||
|
||||
PackedTableBuilder builder(fis->length() - 1, java_fields - 1);
|
||||
Array<u1>* table = MetadataFactory::new_array<u1>(loader_data, java_fields * builder.element_bytes(), CHECK_NULL);
|
||||
FieldInfoSupplier supplier(positions, java_fields);
|
||||
builder.fill(table->data(), static_cast<size_t>(table->length()), supplier);
|
||||
return table;
|
||||
}
|
||||
|
||||
GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count) {
|
||||
FieldInfoReader r(fis);
|
||||
r.read_field_counts(java_fields_count, injected_fields_count);
|
||||
int length = *java_fields_count + *injected_fields_count;
|
||||
|
||||
GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
|
||||
while (r.has_next()) {
|
||||
FieldInfo fi;
|
||||
r.read_field_info(fi);
|
||||
array->append(fi);
|
||||
}
|
||||
assert(array->length() == length, "Must be");
|
||||
assert(array->length() == *java_fields_count + *injected_fields_count, "Must be");
|
||||
return array;
|
||||
}
|
||||
|
||||
void FieldInfoStream::print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp) {
|
||||
int length = FieldInfoStream::num_total_fields(fis);
|
||||
FieldInfoReader r(fis);
|
||||
int java_field_count = r.next_uint();
|
||||
int injected_fields_count = r.next_uint();
|
||||
int java_fields_count;
|
||||
int injected_fields_count;
|
||||
r.read_field_counts(&java_fields_count, &injected_fields_count);
|
||||
while (r.has_next()) {
|
||||
FieldInfo fi;
|
||||
r.read_field_info(fi);
|
||||
fi.print(os, cp);
|
||||
}
|
||||
}
|
||||
|
||||
class FieldInfoComparator: public PackedTableLookup::Comparator {
|
||||
const FieldInfoReader* _reader;
|
||||
ConstantPool* _cp;
|
||||
const Symbol* _name;
|
||||
const Symbol* _signature;
|
||||
|
||||
public:
|
||||
FieldInfoComparator(const FieldInfoReader* reader, ConstantPool* cp, const Symbol* name, const Symbol* signature):
|
||||
_reader(reader), _cp(cp), _name(name), _signature(signature) {}
|
||||
|
||||
int compare_to(uint32_t position) override {
|
||||
FieldInfoReader r2(*_reader);
|
||||
r2.set_position_and_next_index(position, -1);
|
||||
u2 name_index, sig_index;
|
||||
r2.read_name_and_signature(&name_index, &sig_index);
|
||||
Symbol* mid_name = _cp->symbol_at(name_index);
|
||||
Symbol* mid_sig = _cp->symbol_at(sig_index);
|
||||
|
||||
return FieldInfoStream::compare_name_and_sig(_name, _signature, mid_name, mid_sig);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
void reset(uint32_t position) override {
|
||||
FieldInfoReader r2(*_reader);
|
||||
r2.set_position_and_next_index(position, -1);
|
||||
u2 name_index, signature_index;
|
||||
r2.read_name_and_signature(&name_index, &signature_index);
|
||||
_name = _cp->symbol_at(name_index);
|
||||
_signature = _cp->symbol_at(signature_index);
|
||||
}
|
||||
#endif // ASSERT
|
||||
};
|
||||
|
||||
#ifdef ASSERT
|
||||
void FieldInfoStream::validate_search_table(ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table) {
|
||||
if (search_table == nullptr) {
|
||||
return;
|
||||
}
|
||||
FieldInfoReader reader(fis);
|
||||
int java_fields, injected_fields;
|
||||
reader.read_field_counts(&java_fields, &injected_fields);
|
||||
assert(java_fields > 0, "must be");
|
||||
|
||||
PackedTableLookup lookup(fis->length() - 1, java_fields - 1, search_table);
|
||||
assert(lookup.element_bytes() * java_fields == static_cast<unsigned int>(search_table->length()), "size does not match");
|
||||
|
||||
FieldInfoComparator comparator(&reader, cp, nullptr, nullptr);
|
||||
// Check 1: assert that elements have the correct order based on the comparison function
|
||||
lookup.validate_order(comparator);
|
||||
|
||||
// Check 2: Iterate through the original stream (not just search_table) and try if lookup works as expected
|
||||
reader.set_position_and_next_index(0, 0);
|
||||
reader.read_field_counts(&java_fields, &injected_fields);
|
||||
while (reader.has_next()) {
|
||||
int field_start = reader.position();
|
||||
FieldInfo fi;
|
||||
reader.read_field_info(fi);
|
||||
if (fi.field_flags().is_injected()) {
|
||||
// checking only java fields that precede injected ones
|
||||
break;
|
||||
}
|
||||
|
||||
FieldInfoReader r2(fis);
|
||||
int index = r2.search_table_lookup(search_table, fi.name(cp), fi.signature(cp), cp, java_fields);
|
||||
assert(index == static_cast<int>(fi.index()), "wrong index: %d != %u", index, fi.index());
|
||||
assert(index == r2.next_index(), "index should match");
|
||||
assert(field_start == r2.position(), "must find the same position");
|
||||
}
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
void FieldInfoStream::print_search_table(outputStream* st, ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table) {
|
||||
if (search_table == nullptr) {
|
||||
return;
|
||||
}
|
||||
FieldInfoReader reader(fis);
|
||||
int java_fields, injected_fields;
|
||||
reader.read_field_counts(&java_fields, &injected_fields);
|
||||
assert(java_fields > 0, "must be");
|
||||
PackedTableLookup lookup(fis->length() - 1, java_fields - 1, search_table);
|
||||
auto printer = [&] (size_t offset, uint32_t position, uint32_t index) {
|
||||
reader.set_position_and_next_index(position, -1);
|
||||
u2 name_index, sig_index;
|
||||
reader.read_name_and_signature(&name_index, &sig_index);
|
||||
Symbol* name = cp->symbol_at(name_index);
|
||||
Symbol* sig = cp->symbol_at(sig_index);
|
||||
st->print(" [%zu] #%d,#%d = ", offset, name_index, sig_index);
|
||||
name->print_symbol_on(st);
|
||||
st->print(":");
|
||||
sig->print_symbol_on(st);
|
||||
st->print(" @ %p,%p", name, sig);
|
||||
st->cr();
|
||||
};
|
||||
|
||||
lookup.iterate(printer);
|
||||
}
|
||||
|
||||
int FieldInfoReader::search_table_lookup(const Array<u1>* search_table, const Symbol* name, const Symbol* signature, ConstantPool* cp, int java_fields) {
|
||||
assert(java_fields >= 0, "must be");
|
||||
if (java_fields == 0) {
|
||||
return -1;
|
||||
}
|
||||
FieldInfoComparator comp(this, cp, name, signature);
|
||||
PackedTableLookup lookup(_r.limit() - 1, java_fields - 1, search_table);
|
||||
uint32_t position;
|
||||
static_assert(sizeof(uint32_t) == sizeof(_next_index), "field size assert");
|
||||
if (lookup.search(comp, &position, reinterpret_cast<uint32_t*>(&_next_index))) {
|
||||
_r.set_position(static_cast<int>(position));
|
||||
return _next_index;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,29 +222,28 @@ public:
|
||||
void map_field_info(const FieldInfo& fi);
|
||||
};
|
||||
|
||||
|
||||
// Gadget for decoding and reading the stream of field records.
|
||||
class FieldInfoReader {
|
||||
friend class FieldInfoStream;
|
||||
friend class ClassFileParser;
|
||||
friend class FieldStreamBase;
|
||||
friend class FieldInfo;
|
||||
|
||||
UNSIGNED5::Reader<const u1*, int> _r;
|
||||
int _next_index;
|
||||
|
||||
public:
|
||||
public:
|
||||
FieldInfoReader(const Array<u1>* fi);
|
||||
|
||||
private:
|
||||
uint32_t next_uint() { return _r.next_uint(); }
|
||||
private:
|
||||
inline uint32_t next_uint() { return _r.next_uint(); }
|
||||
void skip(int n) { int s = _r.try_skip(n); assert(s == n,""); }
|
||||
|
||||
public:
|
||||
int has_next() { return _r.has_next(); }
|
||||
int position() { return _r.position(); }
|
||||
int next_index() { return _next_index; }
|
||||
void read_field_counts(int* java_fields, int* injected_fields);
|
||||
int has_next() const { return _r.position() < _r.limit(); }
|
||||
int position() const { return _r.position(); }
|
||||
int next_index() const { return _next_index; }
|
||||
void read_name_and_signature(u2* name_index, u2* signature_index);
|
||||
void read_field_info(FieldInfo& fi);
|
||||
|
||||
int search_table_lookup(const Array<u1>* search_table, const Symbol* name, const Symbol* signature, ConstantPool* cp, int java_fields);
|
||||
|
||||
// skip a whole field record, both required and optional bits
|
||||
FieldInfoReader& skip_field_info();
|
||||
|
||||
@@ -271,6 +270,11 @@ class FieldInfoStream : AllStatic {
|
||||
friend class JavaFieldStream;
|
||||
friend class FieldStreamBase;
|
||||
friend class ClassFileParser;
|
||||
friend class FieldInfoReader;
|
||||
friend class FieldInfoComparator;
|
||||
|
||||
private:
|
||||
static int compare_name_and_sig(const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2);
|
||||
|
||||
public:
|
||||
static int num_java_fields(const Array<u1>* fis);
|
||||
@@ -278,9 +282,14 @@ class FieldInfoStream : AllStatic {
|
||||
static int num_total_fields(const Array<u1>* fis);
|
||||
|
||||
static Array<u1>* create_FieldInfoStream(GrowableArray<FieldInfo>* fields, int java_fields, int injected_fields,
|
||||
ClassLoaderData* loader_data, TRAPS);
|
||||
ClassLoaderData* loader_data, TRAPS);
|
||||
static Array<u1>* create_search_table(ConstantPool* cp, const Array<u1>* fis, ClassLoaderData* loader_data, TRAPS);
|
||||
static GrowableArray<FieldInfo>* create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count);
|
||||
static void print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp);
|
||||
|
||||
DEBUG_ONLY(static void validate_search_table(ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table);)
|
||||
|
||||
static void print_search_table(outputStream* st, ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table);
|
||||
};
|
||||
|
||||
class FieldStatus {
|
||||
|
||||
@@ -56,16 +56,27 @@ inline Symbol* FieldInfo::lookup_symbol(int symbol_index) const {
|
||||
|
||||
inline int FieldInfoStream::num_injected_java_fields(const Array<u1>* fis) {
|
||||
FieldInfoReader fir(fis);
|
||||
fir.skip(1);
|
||||
return fir.next_uint();
|
||||
int java_fields_count;
|
||||
int injected_fields_count;
|
||||
fir.read_field_counts(&java_fields_count, &injected_fields_count);
|
||||
return injected_fields_count;
|
||||
}
|
||||
|
||||
inline int FieldInfoStream::num_total_fields(const Array<u1>* fis) {
|
||||
FieldInfoReader fir(fis);
|
||||
return fir.next_uint() + fir.next_uint();
|
||||
int java_fields_count;
|
||||
int injected_fields_count;
|
||||
fir.read_field_counts(&java_fields_count, &injected_fields_count);
|
||||
return java_fields_count + injected_fields_count;
|
||||
}
|
||||
|
||||
inline int FieldInfoStream::num_java_fields(const Array<u1>* fis) { return FieldInfoReader(fis).next_uint(); }
|
||||
inline int FieldInfoStream::num_java_fields(const Array<u1>* fis) {
|
||||
FieldInfoReader fir(fis);
|
||||
int java_fields_count;
|
||||
int injected_fields_count;
|
||||
fir.read_field_counts(&java_fields_count, &injected_fields_count);
|
||||
return java_fields_count;
|
||||
}
|
||||
|
||||
template<typename CON>
|
||||
inline void Mapper<CON>::map_field_info(const FieldInfo& fi) {
|
||||
@@ -94,13 +105,22 @@ inline void Mapper<CON>::map_field_info(const FieldInfo& fi) {
|
||||
|
||||
|
||||
inline FieldInfoReader::FieldInfoReader(const Array<u1>* fi)
|
||||
: _r(fi->data(), 0),
|
||||
: _r(fi->data(), fi->length()),
|
||||
_next_index(0) { }
|
||||
|
||||
inline void FieldInfoReader::read_field_counts(int* java_fields, int* injected_fields) {
|
||||
*java_fields = next_uint();
|
||||
*injected_fields = next_uint();
|
||||
}
|
||||
|
||||
inline void FieldInfoReader::read_name_and_signature(u2* name_index, u2* signature_index) {
|
||||
*name_index = checked_cast<u2>(next_uint());
|
||||
*signature_index = checked_cast<u2>(next_uint());
|
||||
}
|
||||
|
||||
inline void FieldInfoReader::read_field_info(FieldInfo& fi) {
|
||||
fi._index = _next_index++;
|
||||
fi._name_index = checked_cast<u2>(next_uint());
|
||||
fi._signature_index = checked_cast<u2>(next_uint());
|
||||
read_name_and_signature(&fi._name_index, &fi._signature_index);
|
||||
fi._offset = next_uint();
|
||||
fi._access_flags = AccessFlags(checked_cast<u2>(next_uint()));
|
||||
fi._field_flags = FieldInfo::FieldFlags(next_uint());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -56,17 +56,23 @@ class FieldStreamBase : public StackObj {
|
||||
|
||||
inline FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit);
|
||||
|
||||
inline FieldStreamBase(Array<u1>* fieldinfo_stream, ConstantPool* constants);
|
||||
inline FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants);
|
||||
|
||||
private:
|
||||
private:
|
||||
void initialize() {
|
||||
int java_fields_count = _reader.next_uint();
|
||||
int injected_fields_count = _reader.next_uint();
|
||||
assert( _limit <= java_fields_count + injected_fields_count, "Safety check");
|
||||
int java_fields_count;
|
||||
int injected_fields_count;
|
||||
_reader.read_field_counts(&java_fields_count, &injected_fields_count);
|
||||
if (_limit < _index) {
|
||||
_limit = java_fields_count + injected_fields_count;
|
||||
} else {
|
||||
assert( _limit <= java_fields_count + injected_fields_count, "Safety check");
|
||||
}
|
||||
if (_limit != 0) {
|
||||
_reader.read_field_info(_fi_buf);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
inline FieldStreamBase(InstanceKlass* klass);
|
||||
|
||||
@@ -138,8 +144,11 @@ class FieldStreamBase : public StackObj {
|
||||
|
||||
// Iterate over only the Java fields
|
||||
class JavaFieldStream : public FieldStreamBase {
|
||||
Array<u1>* _search_table;
|
||||
|
||||
public:
|
||||
JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()) {}
|
||||
JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()),
|
||||
_search_table(k->fieldinfo_search_table()) {}
|
||||
|
||||
u2 name_index() const {
|
||||
assert(!field()->field_flags().is_injected(), "regular only");
|
||||
@@ -149,7 +158,6 @@ class JavaFieldStream : public FieldStreamBase {
|
||||
u2 signature_index() const {
|
||||
assert(!field()->field_flags().is_injected(), "regular only");
|
||||
return field()->signature_index();
|
||||
return -1;
|
||||
}
|
||||
|
||||
u2 generic_signature_index() const {
|
||||
@@ -164,6 +172,10 @@ class JavaFieldStream : public FieldStreamBase {
|
||||
assert(!field()->field_flags().is_injected(), "regular only");
|
||||
return field()->initializer_index();
|
||||
}
|
||||
|
||||
// Performs either a linear search or binary search through the stream
|
||||
// looking for a matching name/signature combo
|
||||
bool lookup(const Symbol* name, const Symbol* signature);
|
||||
};
|
||||
|
||||
|
||||
@@ -176,7 +188,6 @@ class InternalFieldStream : public FieldStreamBase {
|
||||
|
||||
class AllFieldStream : public FieldStreamBase {
|
||||
public:
|
||||
AllFieldStream(Array<u1>* fieldinfo, ConstantPool* constants): FieldStreamBase(fieldinfo, constants) {}
|
||||
AllFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants()) {}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,22 +33,18 @@
|
||||
FieldStreamBase::FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit) :
|
||||
_fieldinfo_stream(fieldinfo_stream),
|
||||
_reader(FieldInfoReader(_fieldinfo_stream)),
|
||||
_constants(constantPoolHandle(Thread::current(), constants)), _index(start) {
|
||||
_index = start;
|
||||
if (limit < start) {
|
||||
_limit = FieldInfoStream::num_total_fields(_fieldinfo_stream);
|
||||
} else {
|
||||
_limit = limit;
|
||||
}
|
||||
_constants(constantPoolHandle(Thread::current(), constants)),
|
||||
_index(start),
|
||||
_limit(limit) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
FieldStreamBase::FieldStreamBase(Array<u1>* fieldinfo_stream, ConstantPool* constants) :
|
||||
FieldStreamBase::FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants) :
|
||||
_fieldinfo_stream(fieldinfo_stream),
|
||||
_reader(FieldInfoReader(_fieldinfo_stream)),
|
||||
_constants(constantPoolHandle(Thread::current(), constants)),
|
||||
_index(0),
|
||||
_limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) {
|
||||
_limit(-1) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
@@ -57,9 +53,28 @@ FieldStreamBase::FieldStreamBase(InstanceKlass* klass) :
|
||||
_reader(FieldInfoReader(_fieldinfo_stream)),
|
||||
_constants(constantPoolHandle(Thread::current(), klass->constants())),
|
||||
_index(0),
|
||||
_limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) {
|
||||
_limit(-1) {
|
||||
assert(klass == field_holder(), "");
|
||||
initialize();
|
||||
}
|
||||
|
||||
inline bool JavaFieldStream::lookup(const Symbol* name, const Symbol* signature) {
|
||||
if (_search_table != nullptr) {
|
||||
int index = _reader.search_table_lookup(_search_table, name, signature, _constants(), _limit);
|
||||
if (index >= 0) {
|
||||
assert(index < _limit, "must be");
|
||||
_index = index;
|
||||
_reader.read_field_info(_fi_buf);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
for (; !done(); next()) {
|
||||
if (this->name() == name && this->signature() == signature) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // SHARE_OOPS_FIELDSTREAMS_INLINE_HPP
|
||||
|
||||
@@ -686,6 +686,11 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
}
|
||||
set_fieldinfo_stream(nullptr);
|
||||
|
||||
if (fieldinfo_search_table() != nullptr && !fieldinfo_search_table()->is_shared()) {
|
||||
MetadataFactory::free_array<u1>(loader_data, fieldinfo_search_table());
|
||||
}
|
||||
set_fieldinfo_search_table(nullptr);
|
||||
|
||||
if (fields_status() != nullptr && !fields_status()->is_shared()) {
|
||||
MetadataFactory::free_array<FieldStatus>(loader_data, fields_status());
|
||||
}
|
||||
@@ -1786,13 +1791,12 @@ FieldInfo InstanceKlass::field(int index) const {
|
||||
}
|
||||
|
||||
bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
|
||||
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
|
||||
Symbol* f_name = fs.name();
|
||||
Symbol* f_sig = fs.signature();
|
||||
if (f_name == name && f_sig == sig) {
|
||||
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.to_FieldInfo());
|
||||
return true;
|
||||
}
|
||||
JavaFieldStream fs(this);
|
||||
if (fs.lookup(name, sig)) {
|
||||
assert(fs.name() == name, "name must match");
|
||||
assert(fs.signature() == sig, "signature must match");
|
||||
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.to_FieldInfo());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2610,6 +2614,7 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
|
||||
}
|
||||
|
||||
it->push(&_fieldinfo_stream);
|
||||
it->push(&_fieldinfo_search_table);
|
||||
// _fields_status might be written into by Rewriter::scan_method() -> fd.set_has_initialized_final_update()
|
||||
it->push(&_fields_status, MetaspaceClosure::_writable);
|
||||
|
||||
@@ -2710,6 +2715,8 @@ void InstanceKlass::remove_unshareable_info() {
|
||||
DEBUG_ONLY(_shared_class_load_count = 0);
|
||||
|
||||
remove_unshareable_flags();
|
||||
|
||||
DEBUG_ONLY(FieldInfoStream::validate_search_table(_constants, _fieldinfo_stream, _fieldinfo_search_table));
|
||||
}
|
||||
|
||||
void InstanceKlass::remove_unshareable_flags() {
|
||||
@@ -2816,6 +2823,8 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
|
||||
if (DiagnoseSyncOnValueBasedClasses && has_value_based_class_annotation() && !is_value_based()) {
|
||||
set_is_value_based();
|
||||
}
|
||||
|
||||
DEBUG_ONLY(FieldInfoStream::validate_search_table(_constants, _fieldinfo_stream, _fieldinfo_search_table));
|
||||
}
|
||||
|
||||
// Check if a class or any of its supertypes has a version older than 50.
|
||||
@@ -3760,6 +3769,11 @@ void InstanceKlass::print_on(outputStream* st) const {
|
||||
map++;
|
||||
}
|
||||
st->cr();
|
||||
|
||||
if (fieldinfo_search_table() != nullptr) {
|
||||
st->print_cr(BULLET"---- field info search table:");
|
||||
FieldInfoStream::print_search_table(st, _constants, _fieldinfo_stream, _fieldinfo_search_table);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceKlass::print_value_on(outputStream* st) const {
|
||||
|
||||
@@ -276,6 +276,7 @@ class InstanceKlass: public Klass {
|
||||
|
||||
// Fields information is stored in an UNSIGNED5 encoded stream (see fieldInfo.hpp)
|
||||
Array<u1>* _fieldinfo_stream;
|
||||
Array<u1>* _fieldinfo_search_table;
|
||||
Array<FieldStatus>* _fields_status;
|
||||
|
||||
// embedded Java vtable follows here
|
||||
@@ -398,6 +399,9 @@ class InstanceKlass: public Klass {
|
||||
Array<u1>* fieldinfo_stream() const { return _fieldinfo_stream; }
|
||||
void set_fieldinfo_stream(Array<u1>* fis) { _fieldinfo_stream = fis; }
|
||||
|
||||
Array<u1>* fieldinfo_search_table() const { return _fieldinfo_search_table; }
|
||||
void set_fieldinfo_search_table(Array<u1>* table) { _fieldinfo_search_table = table; }
|
||||
|
||||
Array<FieldStatus>* fields_status() const {return _fields_status; }
|
||||
void set_fields_status(Array<FieldStatus>* array) { _fields_status = array; }
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "runtime/handles.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "utilities/resizeableResourceHash.hpp"
|
||||
@@ -286,7 +287,12 @@ private:
|
||||
static bool is_klass_loaded(Klass* k) {
|
||||
if (have_data()) {
|
||||
// If we're running in AOT mode some classes may not be loaded yet
|
||||
return !k->is_instance_klass() || InstanceKlass::cast(k)->is_loaded();
|
||||
if (k->is_objArray_klass()) {
|
||||
k = ObjArrayKlass::cast(k)->bottom_klass();
|
||||
}
|
||||
if (k->is_instance_klass()) {
|
||||
return InstanceKlass::cast(k)->is_loaded();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -37,11 +37,8 @@
|
||||
#include "utilities/copy.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
void Block_Array::grow( uint i ) {
|
||||
_nesting.check(_arena); // Check if a potential reallocation in the arena is safe
|
||||
if (i < Max()) {
|
||||
return; // No need to grow
|
||||
}
|
||||
void Block_Array::grow(uint i) {
|
||||
assert(i >= Max(), "Should have been checked before, use maybe_grow?");
|
||||
DEBUG_ONLY(_limit = i+1);
|
||||
if( i < _size ) return;
|
||||
if( !_size ) {
|
||||
|
||||
@@ -53,7 +53,13 @@ class Block_Array : public ArenaObj {
|
||||
ReallocMark _nesting; // Safety checks for arena reallocation
|
||||
protected:
|
||||
Block **_blocks;
|
||||
void grow( uint i ); // Grow array node to fit
|
||||
void maybe_grow(uint i) {
|
||||
_nesting.check(_arena); // Check if a potential reallocation in the arena is safe
|
||||
if (i >= Max()) {
|
||||
grow(i);
|
||||
}
|
||||
}
|
||||
void grow(uint i); // Grow array node to fit
|
||||
|
||||
public:
|
||||
Block_Array(Arena *a) : _size(OptoBlockListSize), _arena(a) {
|
||||
@@ -68,7 +74,7 @@ public:
|
||||
Block *operator[] ( uint i ) const // Lookup, or assert for not mapped
|
||||
{ assert( i < Max(), "oob" ); return _blocks[i]; }
|
||||
// Extend the mapping: index i maps to Block *n.
|
||||
void map( uint i, Block *n ) { grow(i); _blocks[i] = n; }
|
||||
void map( uint i, Block *n ) { maybe_grow(i); _blocks[i] = n; }
|
||||
uint Max() const { DEBUG_ONLY(return _limit); return _size; }
|
||||
};
|
||||
|
||||
|
||||
@@ -298,19 +298,52 @@ IdealLoopTree* PhaseIdealLoop::insert_outer_loop(IdealLoopTree* loop, LoopNode*
|
||||
return outer_ilt;
|
||||
}
|
||||
|
||||
// Create a skeleton strip mined outer loop: a Loop head before the
|
||||
// inner strip mined loop, a safepoint and an exit condition guarded
|
||||
// by an opaque node after the inner strip mined loop with a backedge
|
||||
// to the loop head. The inner strip mined loop is left as it is. Only
|
||||
// once loop optimizations are over, do we adjust the inner loop exit
|
||||
// condition to limit its number of iterations, set the outer loop
|
||||
// exit condition and add Phis to the outer loop head. Some loop
|
||||
// optimizations that operate on the inner strip mined loop need to be
|
||||
// aware of the outer strip mined loop: loop unswitching needs to
|
||||
// clone the outer loop as well as the inner, unrolling needs to only
|
||||
// clone the inner loop etc. No optimizations need to change the outer
|
||||
// strip mined loop as it is only a skeleton.
|
||||
IdealLoopTree* PhaseIdealLoop::create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control,
|
||||
// Create a skeleton strip mined outer loop: an OuterStripMinedLoop head before the inner strip mined CountedLoop, a
|
||||
// SafePoint on exit of the inner CountedLoopEnd and an OuterStripMinedLoopEnd test that can't constant fold until loop
|
||||
// optimizations are over. The inner strip mined loop is left as it is. Only once loop optimizations are over, do we
|
||||
// adjust the inner loop exit condition to limit its number of iterations, set the outer loop exit condition and add
|
||||
// Phis to the outer loop head. Some loop optimizations that operate on the inner strip mined loop need to be aware of
|
||||
// the outer strip mined loop: loop unswitching needs to clone the outer loop as well as the inner, unrolling needs to
|
||||
// only clone the inner loop etc. No optimizations need to change the outer strip mined loop as it is only a skeleton.
|
||||
//
|
||||
// Schematically:
|
||||
//
|
||||
// OuterStripMinedLoop -------|
|
||||
// | |
|
||||
// CountedLoop ----------- | |
|
||||
// \- Phi (iv) -| | |
|
||||
// / \ | | |
|
||||
// CmpI AddI --| | |
|
||||
// \ | |
|
||||
// Bool | |
|
||||
// \ | |
|
||||
// CountedLoopEnd | |
|
||||
// / \ | |
|
||||
// IfFalse IfTrue--------| |
|
||||
// | |
|
||||
// SafePoint |
|
||||
// | |
|
||||
// OuterStripMinedLoopEnd |
|
||||
// / \ |
|
||||
// IfFalse IfTrue-----------|
|
||||
// |
|
||||
//
|
||||
//
|
||||
// As loop optimizations transform the inner loop, the outer strip mined loop stays mostly unchanged. The only exception
|
||||
// is nodes referenced from the SafePoint and sunk from the inner loop: they end up in the outer strip mined loop.
|
||||
//
|
||||
// Not adding Phis to the outer loop head from the beginning, and only adding them after loop optimizations does not
|
||||
// conform to C2's IR rules: any variable or memory slice that is mutated in a loop should have a Phi. The main
|
||||
// motivation for such a design that doesn't conform to C2's IR rules is to allow existing loop optimizations to be
|
||||
// mostly unaffected by the outer strip mined loop: the only extra step needed in most cases is to step over the
|
||||
// OuterStripMinedLoop. The main drawback is that once loop optimizations are over, an extra step is needed to finish
|
||||
// constructing the outer loop. This is handled by OuterStripMinedLoopNode::adjust_strip_mined_loop().
|
||||
//
|
||||
// Adding Phis to the outer loop is largely straightforward: there needs to be one Phi in the outer loop for every Phi
|
||||
// in the inner loop. Things may be more complicated for sunk Store nodes: there may not be any inner loop Phi left
|
||||
// after sinking for a particular memory slice but the outer loop needs a Phi. See
|
||||
// OuterStripMinedLoopNode::handle_sunk_stores_when_finishing_construction()
|
||||
IdealLoopTree* PhaseIdealLoop::create_outer_strip_mined_loop(Node* init_control,
|
||||
IdealLoopTree* loop, float cl_prob, float le_fcnt,
|
||||
Node*& entry_control, Node*& iffalse) {
|
||||
Node* outer_test = intcon(0);
|
||||
@@ -2255,9 +2288,8 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_
|
||||
is_deleteable_safept(sfpt);
|
||||
IdealLoopTree* outer_ilt = nullptr;
|
||||
if (strip_mine_loop) {
|
||||
outer_ilt = create_outer_strip_mined_loop(test, cmp, init_control, loop,
|
||||
cl_prob, le->_fcnt, entry_control,
|
||||
iffalse);
|
||||
outer_ilt = create_outer_strip_mined_loop(init_control, loop, cl_prob, le->_fcnt,
|
||||
entry_control, iffalse);
|
||||
}
|
||||
|
||||
// Now setup a new CountedLoopNode to replace the existing LoopNode
|
||||
@@ -2870,10 +2902,11 @@ BaseCountedLoopNode* BaseCountedLoopNode::make(Node* entry, Node* backedge, Basi
|
||||
return new LongCountedLoopNode(entry, backedge);
|
||||
}
|
||||
|
||||
void OuterStripMinedLoopNode::fix_sunk_stores(CountedLoopEndNode* inner_cle, LoopNode* inner_cl, PhaseIterGVN* igvn,
|
||||
PhaseIdealLoop* iloop) {
|
||||
Node* cle_out = inner_cle->proj_out(false);
|
||||
Node* cle_tail = inner_cle->proj_out(true);
|
||||
void OuterStripMinedLoopNode::fix_sunk_stores_when_back_to_counted_loop(PhaseIterGVN* igvn,
|
||||
PhaseIdealLoop* iloop) const {
|
||||
CountedLoopNode* inner_cl = inner_counted_loop();
|
||||
IfFalseNode* cle_out = inner_loop_exit();
|
||||
|
||||
if (cle_out->outcnt() > 1) {
|
||||
// Look for chains of stores that were sunk
|
||||
// out of the inner loop and are in the outer loop
|
||||
@@ -2988,11 +3021,90 @@ void OuterStripMinedLoopNode::fix_sunk_stores(CountedLoopEndNode* inner_cle, Loo
|
||||
}
|
||||
}
|
||||
|
||||
// The outer strip mined loop is initially only partially constructed. In particular Phis are omitted.
|
||||
// See comment above: PhaseIdealLoop::create_outer_strip_mined_loop()
|
||||
// We're now in the process of finishing the construction of the outer loop. For each Phi in the inner loop, a Phi in
|
||||
// the outer loop was just now created. However, Sunk Stores cause an extra challenge:
|
||||
// 1) If all Stores in the inner loop were sunk for a particular memory slice, there's no Phi left for that memory slice
|
||||
// in the inner loop anymore, and hence we did not yet add a Phi for the outer loop. So an extra Phi must now be
|
||||
// added for each chain of sunk Stores for a particular memory slice.
|
||||
// 2) If some Stores were sunk and some left in the inner loop, a Phi was already created in the outer loop but
|
||||
// its backedge input wasn't wired correctly to the last Store of the chain: the backedge input was set to the
|
||||
// backedge of the inner loop Phi instead, but it needs to be the last Store of the chain in the outer loop. We now
|
||||
// have to fix that too.
|
||||
void OuterStripMinedLoopNode::handle_sunk_stores_when_finishing_construction(PhaseIterGVN* igvn) {
|
||||
IfFalseNode* cle_exit_proj = inner_loop_exit();
|
||||
|
||||
// Find Sunk stores: Sunk stores are pinned on the loop exit projection of the inner loop. Indeed, because Sunk Stores
|
||||
// modify the memory state captured by the SafePoint in the outer strip mined loop, they must be above it. The
|
||||
// SafePoint's control input is the loop exit projection. It's also the only control out of the inner loop above the
|
||||
// SafePoint.
|
||||
#ifdef ASSERT
|
||||
int stores_in_outer_loop_cnt = 0;
|
||||
for (DUIterator_Fast imax, i = cle_exit_proj->fast_outs(imax); i < imax; i++) {
|
||||
Node* u = cle_exit_proj->fast_out(i);
|
||||
if (u->is_Store()) {
|
||||
stores_in_outer_loop_cnt++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sunk stores are reachable from the memory state of the outer loop safepoint
|
||||
SafePointNode* safepoint = outer_safepoint();
|
||||
MergeMemNode* mm = safepoint->in(TypeFunc::Memory)->isa_MergeMem();
|
||||
if (mm == nullptr) {
|
||||
// There is no MergeMem, which should only happen if there was no memory node
|
||||
// sunk out of the loop.
|
||||
assert(stores_in_outer_loop_cnt == 0, "inconsistent");
|
||||
return;
|
||||
}
|
||||
DEBUG_ONLY(int stores_in_outer_loop_cnt2 = 0);
|
||||
for (MergeMemStream mms(mm); mms.next_non_empty();) {
|
||||
Node* mem = mms.memory();
|
||||
// Traverse up the chain of stores to find the first store pinned
|
||||
// at the loop exit projection.
|
||||
Node* last = mem;
|
||||
Node* first = nullptr;
|
||||
while (mem->is_Store() && mem->in(0) == cle_exit_proj) {
|
||||
DEBUG_ONLY(stores_in_outer_loop_cnt2++);
|
||||
first = mem;
|
||||
mem = mem->in(MemNode::Memory);
|
||||
}
|
||||
if (first != nullptr) {
|
||||
// Found a chain of Stores that were sunk
|
||||
// Do we already have a memory Phi for that slice on the outer loop? If that is the case, that Phi was created
|
||||
// by cloning an inner loop Phi. The inner loop Phi should have mem, the memory state of the first Store out of
|
||||
// the inner loop, as input on the backedge. So does the outer loop Phi given it's a clone.
|
||||
Node* phi = nullptr;
|
||||
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
|
||||
Node* u = mem->fast_out(i);
|
||||
if (u->is_Phi() && u->in(0) == this && u->in(LoopBackControl) == mem) {
|
||||
assert(phi == nullptr, "there should be only one");
|
||||
phi = u;
|
||||
PRODUCT_ONLY(break);
|
||||
}
|
||||
}
|
||||
if (phi == nullptr) {
|
||||
// No outer loop Phi? create one
|
||||
phi = PhiNode::make(this, last);
|
||||
phi->set_req(EntryControl, mem);
|
||||
phi = igvn->transform(phi);
|
||||
igvn->replace_input_of(first, MemNode::Memory, phi);
|
||||
} else {
|
||||
// Fix memory state along the backedge: it should be the last sunk Store of the chain
|
||||
igvn->replace_input_of(phi, LoopBackControl, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(stores_in_outer_loop_cnt == stores_in_outer_loop_cnt2, "inconsistent");
|
||||
}
|
||||
|
||||
void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) {
|
||||
verify_strip_mined(1);
|
||||
// Look for the outer & inner strip mined loop, reduce number of
|
||||
// iterations of the inner loop, set exit condition of outer loop,
|
||||
// construct required phi nodes for outer loop.
|
||||
CountedLoopNode* inner_cl = unique_ctrl_out()->as_CountedLoop();
|
||||
CountedLoopNode* inner_cl = inner_counted_loop();
|
||||
assert(inner_cl->is_strip_mined(), "inner loop should be strip mined");
|
||||
if (LoopStripMiningIter == 0) {
|
||||
remove_outer_loop_and_safepoint(igvn);
|
||||
@@ -3010,7 +3122,7 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) {
|
||||
inner_cl->clear_strip_mined();
|
||||
return;
|
||||
}
|
||||
CountedLoopEndNode* inner_cle = inner_cl->loopexit();
|
||||
CountedLoopEndNode* inner_cle = inner_counted_loop_end();
|
||||
|
||||
int stride = inner_cl->stride_con();
|
||||
// For a min int stride, LoopStripMiningIter * stride overflows the int range for all values of LoopStripMiningIter
|
||||
@@ -3091,8 +3203,9 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) {
|
||||
}
|
||||
|
||||
Node* iv_phi = nullptr;
|
||||
// Make a clone of each phi in the inner loop
|
||||
// for the outer loop
|
||||
// Make a clone of each phi in the inner loop for the outer loop
|
||||
// When Stores were Sunk, after this step, a Phi may still be missing or its backedge incorrectly wired. See
|
||||
// handle_sunk_stores_when_finishing_construction()
|
||||
for (uint i = 0; i < inner_cl->outcnt(); i++) {
|
||||
Node* u = inner_cl->raw_out(i);
|
||||
if (u->is_Phi()) {
|
||||
@@ -3111,6 +3224,8 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) {
|
||||
}
|
||||
}
|
||||
|
||||
handle_sunk_stores_when_finishing_construction(igvn);
|
||||
|
||||
if (iv_phi != nullptr) {
|
||||
// Now adjust the inner loop's exit condition
|
||||
Node* limit = inner_cl->limit();
|
||||
@@ -3166,7 +3281,7 @@ void OuterStripMinedLoopNode::transform_to_counted_loop(PhaseIterGVN* igvn, Phas
|
||||
CountedLoopEndNode* inner_cle = inner_cl->loopexit();
|
||||
Node* safepoint = outer_safepoint();
|
||||
|
||||
fix_sunk_stores(inner_cle, inner_cl, igvn, iloop);
|
||||
fix_sunk_stores_when_back_to_counted_loop(igvn, iloop);
|
||||
|
||||
// make counted loop exit test always fail
|
||||
ConINode* zero = igvn->intcon(0);
|
||||
|
||||
@@ -573,7 +573,8 @@ class LoopLimitNode : public Node {
|
||||
// Support for strip mining
|
||||
class OuterStripMinedLoopNode : public LoopNode {
|
||||
private:
|
||||
static void fix_sunk_stores(CountedLoopEndNode* inner_cle, LoopNode* inner_cl, PhaseIterGVN* igvn, PhaseIdealLoop* iloop);
|
||||
void fix_sunk_stores_when_back_to_counted_loop(PhaseIterGVN* igvn, PhaseIdealLoop* iloop) const;
|
||||
void handle_sunk_stores_when_finishing_construction(PhaseIterGVN* igvn);
|
||||
|
||||
public:
|
||||
OuterStripMinedLoopNode(Compile* C, Node *entry, Node *backedge)
|
||||
@@ -589,6 +590,10 @@ public:
|
||||
virtual OuterStripMinedLoopEndNode* outer_loop_end() const;
|
||||
virtual IfFalseNode* outer_loop_exit() const;
|
||||
virtual SafePointNode* outer_safepoint() const;
|
||||
CountedLoopNode* inner_counted_loop() const { return unique_ctrl_out()->as_CountedLoop(); }
|
||||
CountedLoopEndNode* inner_counted_loop_end() const { return inner_counted_loop()->loopexit(); }
|
||||
IfFalseNode* inner_loop_exit() const { return inner_counted_loop_end()->proj_out(false)->as_IfFalse(); }
|
||||
|
||||
void adjust_strip_mined_loop(PhaseIterGVN* igvn);
|
||||
|
||||
void remove_outer_loop_and_safepoint(PhaseIterGVN* igvn) const;
|
||||
@@ -1293,7 +1298,7 @@ public:
|
||||
void add_parse_predicate(Deoptimization::DeoptReason reason, Node* inner_head, IdealLoopTree* loop, SafePointNode* sfpt);
|
||||
SafePointNode* find_safepoint(Node* back_control, Node* x, IdealLoopTree* loop);
|
||||
IdealLoopTree* insert_outer_loop(IdealLoopTree* loop, LoopNode* outer_l, Node* outer_ift);
|
||||
IdealLoopTree* create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control,
|
||||
IdealLoopTree* create_outer_strip_mined_loop(Node* init_control,
|
||||
IdealLoopTree* loop, float cl_prob, float le_fcnt,
|
||||
Node*& entry_control, Node*& iffalse);
|
||||
|
||||
|
||||
@@ -65,13 +65,8 @@ public:
|
||||
Node_Stack::push(n, (uint)ns);
|
||||
}
|
||||
void push(Node *n, Node_State ns, Node *parent, int indx) {
|
||||
++_inode_top;
|
||||
if ((_inode_top + 1) >= _inode_max) grow();
|
||||
_inode_top->node = parent;
|
||||
_inode_top->indx = (uint)indx;
|
||||
++_inode_top;
|
||||
_inode_top->node = n;
|
||||
_inode_top->indx = (uint)ns;
|
||||
Node_Stack::push(parent, (uint)indx);
|
||||
Node_Stack::push(n, (uint)ns);
|
||||
}
|
||||
Node *parent() {
|
||||
pop();
|
||||
|
||||
@@ -2798,7 +2798,6 @@ const RegMask &Node::in_RegMask(uint) const {
|
||||
}
|
||||
|
||||
void Node_Array::grow(uint i) {
|
||||
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
|
||||
assert(i >= _max, "Should have been checked before, use maybe_grow?");
|
||||
assert(_max > 0, "invariant");
|
||||
uint old = _max;
|
||||
@@ -3038,10 +3037,6 @@ void Unique_Node_List::remove_useless_nodes(VectorSet &useful) {
|
||||
|
||||
//=============================================================================
|
||||
void Node_Stack::grow() {
|
||||
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
|
||||
if (_inode_top < _inode_max) {
|
||||
return; // No need to grow
|
||||
}
|
||||
size_t old_top = pointer_delta(_inode_top,_inodes,sizeof(INode)); // save _top
|
||||
size_t old_max = pointer_delta(_inode_max,_inodes,sizeof(INode));
|
||||
size_t max = old_max << 1; // max * 2
|
||||
|
||||
@@ -1633,6 +1633,7 @@ protected:
|
||||
|
||||
// Grow array to required capacity
|
||||
void maybe_grow(uint i) {
|
||||
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
|
||||
if (i >= _max) {
|
||||
grow(i);
|
||||
}
|
||||
@@ -1884,7 +1885,15 @@ protected:
|
||||
INode *_inodes; // Array storage for the stack
|
||||
Arena *_a; // Arena to allocate in
|
||||
ReallocMark _nesting; // Safety checks for arena reallocation
|
||||
|
||||
void maybe_grow() {
|
||||
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
|
||||
if (_inode_top >= _inode_max) {
|
||||
grow();
|
||||
}
|
||||
}
|
||||
void grow();
|
||||
|
||||
public:
|
||||
Node_Stack(int size) {
|
||||
size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize;
|
||||
@@ -1907,7 +1916,7 @@ public:
|
||||
}
|
||||
void push(Node *n, uint i) {
|
||||
++_inode_top;
|
||||
grow();
|
||||
maybe_grow();
|
||||
INode *top = _inode_top; // optimization
|
||||
top->node = n;
|
||||
top->indx = i;
|
||||
|
||||
@@ -2966,7 +2966,7 @@ JVM_ENTRY(jobject, JVM_CreateThreadSnapshot(JNIEnv* env, jobject jthread))
|
||||
oop snapshot = ThreadSnapshotFactory::get_thread_snapshot(jthread, THREAD);
|
||||
return JNIHandles::make_local(THREAD, snapshot);
|
||||
#else
|
||||
return nullptr;
|
||||
THROW_NULL(vmSymbols::java_lang_UnsupportedOperationException());
|
||||
#endif
|
||||
JVM_END
|
||||
|
||||
|
||||
@@ -3550,6 +3550,13 @@ void VM_RedefineClasses::set_new_constant_pool(
|
||||
Array<u1>* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, scratch_class->class_loader_data(), CHECK);
|
||||
scratch_class->set_fieldinfo_stream(new_fis);
|
||||
MetadataFactory::free_array<u1>(scratch_class->class_loader_data(), old_stream);
|
||||
|
||||
Array<u1>* old_table = scratch_class->fieldinfo_search_table();
|
||||
Array<u1>* search_table = FieldInfoStream::create_search_table(scratch_class->constants(), new_fis, scratch_class->class_loader_data(), CHECK);
|
||||
scratch_class->set_fieldinfo_search_table(search_table);
|
||||
MetadataFactory::free_array<u1>(scratch_class->class_loader_data(), old_table);
|
||||
|
||||
DEBUG_ONLY(FieldInfoStream::validate_search_table(scratch_class->constants(), new_fis, search_table));
|
||||
}
|
||||
|
||||
// Update constant pool indices in the inner classes info to use
|
||||
|
||||
@@ -2005,6 +2005,10 @@ const int ObjectAlignmentInBytes = 8;
|
||||
product(bool, UseThreadsLockThrottleLock, true, DIAGNOSTIC, \
|
||||
"Use an extra lock during Thread start and exit to alleviate" \
|
||||
"contention on Threads_lock.") \
|
||||
\
|
||||
develop(uint, BinarySearchThreshold, 16, \
|
||||
"Minimal number of elements in a sorted collection to prefer" \
|
||||
"binary search over simple linear search." ) \
|
||||
|
||||
// end of RUNTIME_FLAGS
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ Monitor* CompileTaskWait_lock = nullptr;
|
||||
Monitor* MethodCompileQueue_lock = nullptr;
|
||||
Monitor* CompileThread_lock = nullptr;
|
||||
Monitor* Compilation_lock = nullptr;
|
||||
Mutex* CompileTaskAlloc_lock = nullptr;
|
||||
Monitor* CompileTaskAlloc_lock = nullptr;
|
||||
Mutex* CompileStatistics_lock = nullptr;
|
||||
Mutex* DirectivesStack_lock = nullptr;
|
||||
Monitor* Terminator_lock = nullptr;
|
||||
@@ -343,7 +343,7 @@ void mutex_init() {
|
||||
MUTEX_DEFL(G1RareEvent_lock , PaddedMutex , Threads_lock, true);
|
||||
}
|
||||
|
||||
MUTEX_DEFL(CompileTaskAlloc_lock , PaddedMutex , MethodCompileQueue_lock);
|
||||
MUTEX_DEFL(CompileTaskAlloc_lock , PaddedMonitor, MethodCompileQueue_lock);
|
||||
MUTEX_DEFL(CompileTaskWait_lock , PaddedMonitor, MethodCompileQueue_lock);
|
||||
|
||||
#if INCLUDE_PARALLELGC
|
||||
|
||||
@@ -85,7 +85,7 @@ extern Monitor* CompileThread_lock; // a lock held by compile threa
|
||||
extern Monitor* Compilation_lock; // a lock used to pause compilation
|
||||
extern Mutex* TrainingData_lock; // a lock used when accessing training records
|
||||
extern Monitor* TrainingReplayQueue_lock; // a lock held when class are added/removed to the training replay queue
|
||||
extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
|
||||
extern Monitor* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
|
||||
extern Monitor* CompileTaskWait_lock; // a lock held when CompileTasks are waited/notified
|
||||
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
|
||||
extern Mutex* DirectivesStack_lock; // a lock held when mutating the dirstack and ref counting directives
|
||||
|
||||
@@ -1168,9 +1168,10 @@ void ThreadsSMRSupport::print_info_on(const Thread* thread, outputStream* st) {
|
||||
// The count is only interesting if we have a _threads_list_ptr.
|
||||
st->print(", _nested_threads_hazard_ptr_cnt=%u", thread->_nested_threads_hazard_ptr_cnt);
|
||||
}
|
||||
if (SafepointSynchronize::is_at_safepoint() || Thread::current() == thread) {
|
||||
// It is only safe to walk the list if we're at a safepoint or the
|
||||
// calling thread is walking its own list.
|
||||
if ((SafepointSynchronize::is_at_safepoint() && thread->is_Java_thread()) ||
|
||||
Thread::current() == thread) {
|
||||
// It is only safe to walk the list if we're at a safepoint and processing a JavaThread,
|
||||
// or the calling thread is walking its own list.
|
||||
SafeThreadsListPtr* current = thread->_threads_list_ptr;
|
||||
if (current != nullptr) {
|
||||
// Skip the top nesting level as it is always printed above.
|
||||
|
||||
@@ -771,8 +771,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
#endif
|
||||
|
||||
if (CDSConfig::is_using_aot_linked_classes()) {
|
||||
AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR);
|
||||
SystemDictionary::restore_archived_method_handle_intrinsics();
|
||||
AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR);
|
||||
}
|
||||
|
||||
// Start string deduplication thread if requested.
|
||||
|
||||
@@ -1439,7 +1439,17 @@ oop ThreadSnapshotFactory::get_thread_snapshot(jobject jthread, TRAPS) {
|
||||
|
||||
ResourceMark rm(THREAD);
|
||||
HandleMark hm(THREAD);
|
||||
Handle thread_h(THREAD, JNIHandles::resolve(jthread));
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
oop thread_oop;
|
||||
bool has_javathread = tlh.cv_internal_thread_to_JavaThread(jthread, &java_thread, &thread_oop);
|
||||
assert((has_javathread && thread_oop != nullptr) || !has_javathread, "Missing Thread oop");
|
||||
Handle thread_h(THREAD, thread_oop);
|
||||
bool is_virtual = java_lang_VirtualThread::is_instance(thread_h()); // Deals with null
|
||||
|
||||
if (!has_javathread && !is_virtual) {
|
||||
return nullptr; // thread terminated so not of interest
|
||||
}
|
||||
|
||||
// wrapper to auto delete JvmtiVTMSTransitionDisabler
|
||||
class TransitionDisabler {
|
||||
@@ -1460,8 +1470,6 @@ oop ThreadSnapshotFactory::get_thread_snapshot(jobject jthread, TRAPS) {
|
||||
}
|
||||
} transition_disabler;
|
||||
|
||||
JavaThread* java_thread = nullptr;
|
||||
bool is_virtual = java_lang_VirtualThread::is_instance(thread_h());
|
||||
Handle carrier_thread;
|
||||
if (is_virtual) {
|
||||
// 1st need to disable mount/unmount transitions
|
||||
|
||||
113
src/hotspot/share/utilities/packedTable.cpp
Normal file
113
src/hotspot/share/utilities/packedTable.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute 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 <cstring>
|
||||
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/count_leading_zeros.hpp"
|
||||
#include "utilities/packedTable.hpp"
|
||||
|
||||
// The thresholds are inclusive, and in practice the limits are rounded
|
||||
// to the nearest power-of-two - 1.
|
||||
// Based on the max_key and max_value we figure out the number of bits required to store
|
||||
// key and value; imagine that only as bits (not aligned to byte boundary... yet).
|
||||
// Then we concatenate the bits for key and value, and 'add' 1-7 padding zeroes
|
||||
// (high-order bits) to align on bytes.
|
||||
// In the end we have each element in the table consuming 1-8 bytes (case with 0 bits for key
|
||||
// is ruled out).
|
||||
PackedTableBase::PackedTableBase(uint32_t max_key, uint32_t max_value) {
|
||||
unsigned int key_bits = max_key == 0 ? 0 : 32 - count_leading_zeros(max_key);
|
||||
unsigned int value_bits = max_value == 0 ? 0 : 32 - count_leading_zeros(max_value);
|
||||
_element_bytes = align_up(key_bits + value_bits, 8) / 8;
|
||||
// shifting left by 32 is undefined behaviour, and in practice returns 1
|
||||
_key_mask = key_bits >= 32 ? -1 : (1U << key_bits) - 1;
|
||||
_value_shift = key_bits;
|
||||
_value_mask = value_bits >= 32 ? -1 : (1U << value_bits) - 1;
|
||||
guarantee(_element_bytes > 0, "wouldn't work");
|
||||
assert(_element_bytes <= sizeof(uint64_t), "shouldn't happen");
|
||||
}
|
||||
|
||||
// Note: we require the supplier to provide the elements in the final order as we can't easily sort
|
||||
// within this method - qsort() accepts only pure function as comparator.
|
||||
void PackedTableBuilder::fill(u1* table, size_t table_length, Supplier &supplier) const {
|
||||
uint32_t key, value;
|
||||
size_t offset = 0;
|
||||
for (; offset <= table_length && supplier.next(&key, &value); offset += _element_bytes) {
|
||||
assert((key & ~_key_mask) == 0, "key out of bounds");
|
||||
assert((value & ~_value_mask) == 0, "value out of bounds: %x vs. %x (%x)", value, _value_mask, ~_value_mask);
|
||||
uint64_t element = static_cast<uint64_t>(key) | (static_cast<uint64_t>(value) << _value_shift);
|
||||
for (unsigned int i = 0; i < _element_bytes; ++i) {
|
||||
table[offset + i] = static_cast<u1>(0xFF & element);
|
||||
element >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
assert(offset == table_length, "Did not fill whole array");
|
||||
assert(!supplier.next(&key, &value), "Supplier has more elements");
|
||||
}
|
||||
|
||||
uint64_t PackedTableLookup::read_element(size_t offset) const {
|
||||
uint64_t element = 0;
|
||||
for (unsigned int i = 0; i < _element_bytes; ++i) {
|
||||
element |= static_cast<uint64_t>(_table[offset + i]) << (8 * i);
|
||||
}
|
||||
assert((element & ~((uint64_t) _key_mask | ((uint64_t) _value_mask << _value_shift))) == 0, "read too much");
|
||||
return element;
|
||||
}
|
||||
|
||||
bool PackedTableLookup::search(Comparator& comparator, uint32_t* found_key, uint32_t* found_value) const {
|
||||
unsigned int low = 0, high = checked_cast<unsigned int>(_table_length / _element_bytes);
|
||||
assert(low < high, "must be");
|
||||
while (low < high) {
|
||||
unsigned int mid = low + (high - low) / 2;
|
||||
assert(mid >= low && mid < high, "integer overflow?");
|
||||
uint64_t element = read_element(_element_bytes * mid);
|
||||
// Ignoring high 32 bits in element on purpose
|
||||
uint32_t key = static_cast<uint32_t>(element) & _key_mask;
|
||||
int cmp = comparator.compare_to(key);
|
||||
if (cmp == 0) {
|
||||
*found_key = key;
|
||||
// Since __builtin_memcpy in read_element does not copy bits outside the element
|
||||
// anything above _value_mask << _value_shift should be zero.
|
||||
*found_value = checked_cast<uint32_t>(element >> _value_shift) & _value_mask;
|
||||
return true;
|
||||
} else if (cmp < 0) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
void PackedTableLookup::validate_order(Comparator &comparator) const {
|
||||
auto validator = [&] (size_t offset, uint32_t key, uint32_t value) {
|
||||
if (offset != 0) {
|
||||
assert(comparator.compare_to(key) < 0, "not sorted");
|
||||
}
|
||||
comparator.reset(key);
|
||||
};
|
||||
iterate(validator);
|
||||
}
|
||||
#endif
|
||||
123
src/hotspot/share/utilities/packedTable.hpp
Normal file
123
src/hotspot/share/utilities/packedTable.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute 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 "oops/array.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
// Base for space-optimized structure supporting binary search. Each element
|
||||
// consists of up to 32-bit key, and up to 32-bit value; these are packed
|
||||
// into a bit-record with 1-byte alignment.
|
||||
// The keys are ordered according to a custom comparator.
|
||||
class PackedTableBase {
|
||||
protected:
|
||||
unsigned int _element_bytes;
|
||||
uint32_t _key_mask;
|
||||
unsigned int _value_shift;
|
||||
uint32_t _value_mask;
|
||||
|
||||
public:
|
||||
PackedTableBase(uint32_t max_key, uint32_t max_value);
|
||||
|
||||
// Returns number of bytes each element will occupy.
|
||||
inline unsigned int element_bytes(void) const { return _element_bytes; }
|
||||
};
|
||||
|
||||
// Helper class for constructing a packed table in the provided array.
|
||||
class PackedTableBuilder: public PackedTableBase {
|
||||
public:
|
||||
class Supplier {
|
||||
public:
|
||||
// Returns elements with already ordered keys.
|
||||
// This function should return true when the key and value was set,
|
||||
// and false when there's no more elements.
|
||||
// Packed table does NOT support duplicate keys.
|
||||
virtual bool next(uint32_t* key, uint32_t* value) = 0;
|
||||
};
|
||||
|
||||
// The thresholds are inclusive, and in practice the limits are rounded
|
||||
// to the nearest power-of-two - 1.
|
||||
// See PackedTableBase constructor for details.
|
||||
PackedTableBuilder(uint32_t max_key, uint32_t max_value): PackedTableBase(max_key, max_value) {}
|
||||
|
||||
// Constructs a packed table in the provided array, filling it with elements
|
||||
// from the supplier. Note that no comparator is requied by this method -
|
||||
// the supplier must return elements with already ordered keys.
|
||||
// The table_length (in bytes) should match number of elements provided
|
||||
// by the supplier (when Supplier::next() returns false the whole array should
|
||||
// be filled).
|
||||
void fill(u1* table, size_t table_length, Supplier &supplier) const;
|
||||
};
|
||||
|
||||
// Helper class for lookup in a packed table.
|
||||
class PackedTableLookup: public PackedTableBase {
|
||||
const u1* const _table;
|
||||
const size_t _table_length;
|
||||
|
||||
uint64_t read_element(size_t offset) const;
|
||||
|
||||
public:
|
||||
|
||||
// The comparator implementation does not have to store a key (uint32_t);
|
||||
// the idea is that key can point into a different structure that hosts data
|
||||
// suitable for the actual comparison. That's why PackedTableLookup::search(...)
|
||||
// returns the key it found as well as the value.
|
||||
class Comparator {
|
||||
public:
|
||||
// Returns negative/0/positive if the target referred to by this comparator
|
||||
// is lower/equal/higher than the target referred to by the key.
|
||||
virtual int compare_to(uint32_t key) = 0;
|
||||
// Changes the target this comparator refers to.
|
||||
DEBUG_ONLY(virtual void reset(uint32_t key) = 0);
|
||||
};
|
||||
|
||||
// The thresholds are inclusive, and in practice the limits are rounded
|
||||
// to the nearest power-of-two - 1.
|
||||
// See PackedTableBase constructor for details.
|
||||
PackedTableLookup(uint32_t max_key, uint32_t max_value, const u1 *table, size_t table_length):
|
||||
PackedTableBase(max_key, max_value), _table(table), _table_length(table_length) {}
|
||||
|
||||
PackedTableLookup(uint32_t max_key, uint32_t max_value, const Array<u1> *table):
|
||||
PackedTableLookup(max_key, max_value, table->data(), static_cast<size_t>(table->length())) {}
|
||||
|
||||
// Performs a binary search in the packed table, looking for an element with key
|
||||
// referring to a target equal according to the comparator.
|
||||
// When the element is found, found_key and found_value are updated from the element
|
||||
// and the function returns true.
|
||||
// When the element is not found, found_key and found_value are not changed and
|
||||
// the function returns false.
|
||||
bool search(Comparator& comparator, uint32_t* found_key, uint32_t* found_value) const;
|
||||
|
||||
// Asserts that elements in the packed table follow the order defined by the comparator.
|
||||
DEBUG_ONLY(void validate_order(Comparator &comparator) const);
|
||||
|
||||
template<typename Function>
|
||||
void iterate(Function func) const {
|
||||
for (size_t offset = 0; offset < _table_length; offset += _element_bytes) {
|
||||
uint64_t element = read_element(offset);
|
||||
uint32_t key = static_cast<uint32_t>(element) & _key_mask;
|
||||
uint32_t value = checked_cast<uint32_t>(element >> _value_shift) & _value_mask;
|
||||
func(offset, key, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -261,7 +261,7 @@ class UNSIGNED5 : AllStatic {
|
||||
ARR _array;
|
||||
OFF _limit;
|
||||
OFF _position;
|
||||
int next_length() {
|
||||
int next_length() const {
|
||||
return UNSIGNED5::check_length(_array, _position, _limit, GET());
|
||||
}
|
||||
public:
|
||||
@@ -270,7 +270,7 @@ class UNSIGNED5 : AllStatic {
|
||||
uint32_t next_uint() {
|
||||
return UNSIGNED5::read_uint(_array, _position, _limit, GET());
|
||||
}
|
||||
bool has_next() {
|
||||
bool has_next() const {
|
||||
return next_length() != 0;
|
||||
}
|
||||
// tries to skip count logical entries; returns actual number skipped
|
||||
@@ -284,8 +284,9 @@ class UNSIGNED5 : AllStatic {
|
||||
return actual;
|
||||
}
|
||||
ARR array() { return _array; }
|
||||
OFF limit() { return _limit; }
|
||||
OFF position() { return _position; }
|
||||
OFF limit() const { return _limit; }
|
||||
OFF position() const { return _position; }
|
||||
void set_limit(OFF limit) { _limit = limit; }
|
||||
void set_position(OFF position) { _position = position; }
|
||||
|
||||
// For debugging, even in product builds (see debug.cpp).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2013, 2025 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
|
||||
@@ -52,6 +52,15 @@ class AixFileSystemProvider extends UnixFileSystemProvider {
|
||||
return new AixFileStore(path);
|
||||
}
|
||||
|
||||
private static boolean supportsUserDefinedFileAttributeView(UnixPath file) {
|
||||
try {
|
||||
FileStore store = new AixFileStore(file);
|
||||
return store.supportsFileAttributeView(UserDefinedFileAttributeView.class);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V getFileAttributeView(Path obj,
|
||||
@@ -59,8 +68,10 @@ class AixFileSystemProvider extends UnixFileSystemProvider {
|
||||
LinkOption... options)
|
||||
{
|
||||
if (type == UserDefinedFileAttributeView.class) {
|
||||
return (V) new AixUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
Util.followLinks(options));
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
return supportsUserDefinedFileAttributeView(file) ?
|
||||
(V) new AixUserDefinedFileAttributeView(file, Util.followLinks(options))
|
||||
: null;
|
||||
}
|
||||
return super.getFileAttributeView(obj, type, options);
|
||||
}
|
||||
@@ -71,8 +82,10 @@ class AixFileSystemProvider extends UnixFileSystemProvider {
|
||||
LinkOption... options)
|
||||
{
|
||||
if (name.equals("user")) {
|
||||
return new AixUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
Util.followLinks(options));
|
||||
UnixPath file = UnixPath.toUnixPath(obj);
|
||||
return supportsUserDefinedFileAttributeView(file) ?
|
||||
new AixUserDefinedFileAttributeView(file, Util.followLinks(options))
|
||||
: null;
|
||||
}
|
||||
return super.getFileAttributeView(obj, name, options);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,6 +23,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -229,33 +230,50 @@ void setOSNameAndVersion(java_props_t *sprops) {
|
||||
NSString *nsVerStr = NULL;
|
||||
char* osVersionCStr = NULL;
|
||||
NSOperatingSystemVersion osVer = [[NSProcessInfo processInfo] operatingSystemVersion];
|
||||
// Copy out the char* if running on version other than 10.16 Mac OS (10.16 == 11.x)
|
||||
// or explicitly requesting version compatibility
|
||||
if (!((long)osVer.majorVersion == 10 && (long)osVer.minorVersion >= 16) ||
|
||||
(getenv("SYSTEM_VERSION_COMPAT") != NULL)) {
|
||||
if (osVer.patchVersion == 0) { // Omit trailing ".0"
|
||||
// Some macOS versions require special handling. For example,
|
||||
// when the NSOperatingSystemVersion reports 10.16 as the version
|
||||
// then it should be treated as 11. Similarly, when it reports 16.0
|
||||
// as the version then it should be treated as 26.
|
||||
// If the SYSTEM_VERSION_COMPAT environment variable (a macOS construct)
|
||||
// is set to 1, then we don't do any special handling for any versions
|
||||
// and just literally use the value that NSOperatingSystemVersion reports.
|
||||
const char* envVal = getenv("SYSTEM_VERSION_COMPAT");
|
||||
const bool versionCompatEnabled = envVal != NULL
|
||||
&& strncmp(envVal, "1", 1) == 0;
|
||||
const bool requiresSpecialHandling =
|
||||
((long) osVer.majorVersion == 10 && (long) osVer.minorVersion >= 16)
|
||||
|| ((long) osVer.majorVersion == 16 && (long) osVer.minorVersion >= 0);
|
||||
if (!requiresSpecialHandling || versionCompatEnabled) {
|
||||
// no special handling - just use the version reported
|
||||
// by NSOperatingSystemVersion
|
||||
if (osVer.patchVersion == 0) {
|
||||
// Omit trailing ".0"
|
||||
nsVerStr = [NSString stringWithFormat:@"%ld.%ld",
|
||||
(long)osVer.majorVersion, (long)osVer.minorVersion];
|
||||
} else {
|
||||
nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld",
|
||||
(long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion];
|
||||
(long)osVer.majorVersion, (long)osVer.minorVersion,
|
||||
(long)osVer.patchVersion];
|
||||
}
|
||||
} else {
|
||||
// Version 10.16, without explicit env setting of SYSTEM_VERSION_COMPAT
|
||||
// AKA 11+ Read the *real* ProductVersion from the hidden link to avoid SYSTEM_VERSION_COMPAT
|
||||
// If not found, fallback below to the SystemVersion.plist
|
||||
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :
|
||||
@"/System/Library/CoreServices/.SystemVersionPlatform.plist"];
|
||||
// Requires special handling. We ignore the version reported
|
||||
// by the NSOperatingSystemVersion API and instead read the
|
||||
// *real* ProductVersion from
|
||||
// /System/Library/CoreServices/.SystemVersionPlatform.plist.
|
||||
// If not found there, then as a last resort we fallback to
|
||||
// /System/Library/CoreServices/SystemVersion.plist
|
||||
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:
|
||||
@"/System/Library/CoreServices/.SystemVersionPlatform.plist"];
|
||||
if (version != NULL) {
|
||||
nsVerStr = [version objectForKey : @"ProductVersion"];
|
||||
nsVerStr = [version objectForKey: @"ProductVersion"];
|
||||
}
|
||||
}
|
||||
// Fallback to reading the SystemVersion.plist
|
||||
// Last resort - fallback to reading the SystemVersion.plist
|
||||
if (nsVerStr == NULL) {
|
||||
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :
|
||||
@"/System/Library/CoreServices/SystemVersion.plist"];
|
||||
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:
|
||||
@"/System/Library/CoreServices/SystemVersion.plist"];
|
||||
if (version != NULL) {
|
||||
nsVerStr = [version objectForKey : @"ProductVersion"];
|
||||
nsVerStr = [version objectForKey: @"ProductVersion"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import java.nio.charset.StandardCharsets;
|
||||
* <p>
|
||||
* The {@link #readln()} and {@link #readln(String)} methods decode bytes read from
|
||||
* {@code System.in} into characters. The charset used for decoding is specified by the
|
||||
* {@link System#getProperties stdin.encoding} property. If this property is not present,
|
||||
* {@link System##stdin.encoding stdin.encoding} property. If this property is not present,
|
||||
* or if the charset it names cannot be loaded, then UTF-8 is used instead. Decoding
|
||||
* always replaces malformed and unmappable byte sequences with the charset's default
|
||||
* replacement string.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -41,7 +41,7 @@ import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* {@code Process} provides control of native processes started by
|
||||
* ProcessBuilder.start and Runtime.exec.
|
||||
* {@code ProcessBuilder.start} and {@code Runtime.exec}.
|
||||
* The class provides methods for performing input from the process, performing
|
||||
* output to the process, waiting for the process to complete,
|
||||
* checking the exit status of the process, and destroying (killing)
|
||||
@@ -78,10 +78,6 @@ import java.util.stream.Stream;
|
||||
* process I/O can also be redirected</a>
|
||||
* using methods of the {@link ProcessBuilder} class.
|
||||
*
|
||||
* <p>The process is not killed when there are no more references to
|
||||
* the {@code Process} object, but rather the process
|
||||
* continues executing asynchronously.
|
||||
*
|
||||
* <p>There is no requirement that the process represented by a {@code
|
||||
* Process} object execute asynchronously or concurrently with respect
|
||||
* to the Java process that owns the {@code Process} object.
|
||||
@@ -98,6 +94,49 @@ import java.util.stream.Stream;
|
||||
* Delegating to the underlying Process or ProcessHandle is typically
|
||||
* easiest and most efficient.
|
||||
*
|
||||
* <h2>Resource Usage</h2>
|
||||
* {@linkplain ProcessBuilder#start() Starting a process} uses resources in both the invoking process and the invoked
|
||||
* process and for the communication streams between them.
|
||||
* The resources to control the process and for communication between the processes are retained
|
||||
* until there are no longer any references to the Process or the input, error, and output streams
|
||||
* or readers, or they have been closed.
|
||||
*
|
||||
* <p>The process is not killed when there are no more references to the {@code Process} object,
|
||||
* but rather the process continues executing asynchronously.
|
||||
* The process implementation closes file descriptors and handles for streams
|
||||
* that are no longer referenced to prevent leaking operating system resources.
|
||||
* Processes that have terminated or been terminated are monitored and their resources released.
|
||||
*
|
||||
* <p>Streams should be {@code closed} when they are no longer needed, to avoid delaying
|
||||
* releasing the operating system resources.
|
||||
* {@code Try-with-resources} can be used to open and close the streams.
|
||||
* <p>For example, to capture the output of a program known to produce some output and then exit:
|
||||
* {@snippet lang = "java" :
|
||||
* List<String> capture(List<String> args) throws Exception {
|
||||
* ProcessBuilder pb = new ProcessBuilder(args);
|
||||
* Process process = pb.start();
|
||||
* try (BufferedReader in = process.inputReader()) {
|
||||
* List<String> captured = in.readAllLines();
|
||||
* int status = process.waitFor();
|
||||
* if (status != 0) {
|
||||
* throw new RuntimeException("Process %d: %s failed with %d"
|
||||
* .formatted(process.pid(), args, status));
|
||||
* }
|
||||
* return captured;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* <p>Stream resources (file descriptor or handle) are always paired; one in the invoking process
|
||||
* and the other end of that connection in the invoked process.
|
||||
* Closing a stream at either end terminates communication but does not have any direct effect
|
||||
* on the other Process. The closing of the stream typically results in the other process exiting.
|
||||
*
|
||||
* <p> {@linkplain #destroy Destroying a process} signals the operating system to terminate the process.
|
||||
* It is up to the operating system to clean up and release the resources of that process.
|
||||
* Typically, file descriptors and handles are closed. When they are closed, any connections to
|
||||
* other processes are terminated and file descriptors and handles in the invoking process signal
|
||||
* end-of-file or closed. Usually, that is seen as an end-of-file or an exception.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class Process {
|
||||
@@ -127,6 +166,9 @@ public abstract class Process {
|
||||
* then this method will return a
|
||||
* <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
|
||||
*
|
||||
* <p>The output stream should be {@linkplain OutputStream#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* @apiNote
|
||||
* When writing to both {@link #getOutputStream()} and either {@link #outputWriter()}
|
||||
* or {@link #outputWriter(Charset)}, {@link BufferedWriter#flush BufferedWriter.flush}
|
||||
@@ -159,9 +201,15 @@ public abstract class Process {
|
||||
* then the input stream returned by this method will receive the
|
||||
* merged standard output and the standard error of the process.
|
||||
*
|
||||
* <p>The input stream should be {@linkplain InputStream#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* @apiNote
|
||||
* Use {@link #getInputStream()} and {@link #inputReader()} with extreme care.
|
||||
* The {@code BufferedReader} may have buffered input from the input stream.
|
||||
* Use either this method or an {@linkplain #inputReader() input reader}
|
||||
* but not both on the same {@code Process}.
|
||||
* The input reader consumes and buffers bytes from the input stream.
|
||||
* Bytes read from the input stream would not be seen by the reader and
|
||||
* buffer contents are unpredictable.
|
||||
*
|
||||
* @implNote
|
||||
* Implementation note: It is a good idea for the returned
|
||||
@@ -185,9 +233,15 @@ public abstract class Process {
|
||||
* then this method will return a
|
||||
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
|
||||
*
|
||||
* <p>The error stream should be {@linkplain InputStream#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* @apiNote
|
||||
* Use {@link #getErrorStream()} and {@link #errorReader()} with extreme care.
|
||||
* The {@code BufferedReader} may have buffered input from the error stream.
|
||||
* Use either this method or an {@linkplain #errorReader() error reader}
|
||||
* but not both on the same {@code Process}.
|
||||
* The error reader consumes and buffers bytes from the error stream.
|
||||
* Bytes read from the error stream would not be seen by the reader and the
|
||||
* buffer contents are unpredictable.
|
||||
*
|
||||
* @implNote
|
||||
* Implementation note: It is a good idea for the returned
|
||||
@@ -208,6 +262,16 @@ public abstract class Process {
|
||||
* If the {@code native.encoding} is not a valid charset name or not supported
|
||||
* the {@link Charset#defaultCharset()} is used.
|
||||
*
|
||||
* <p>The reader should be {@linkplain BufferedReader#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* @apiNote
|
||||
* Use either this method or the {@linkplain #getInputStream input stream}
|
||||
* but not both on the same {@code Process}.
|
||||
* The input reader consumes and buffers bytes from the input stream.
|
||||
* Bytes read from the input stream would not be seen by the reader and the
|
||||
* buffer contents are unpredictable.
|
||||
*
|
||||
* @return a {@link BufferedReader BufferedReader} using the
|
||||
* {@code native.encoding} if supported, otherwise, the
|
||||
* {@link Charset#defaultCharset()}
|
||||
@@ -238,6 +302,9 @@ public abstract class Process {
|
||||
* then the {@code InputStreamReader} will be reading from a
|
||||
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
|
||||
*
|
||||
* <p>The reader should be {@linkplain BufferedReader#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* <p>Otherwise, if the standard error of the process has been redirected using
|
||||
* {@link ProcessBuilder#redirectErrorStream(boolean)
|
||||
* ProcessBuilder.redirectErrorStream} then the input reader returned by
|
||||
@@ -245,9 +312,11 @@ public abstract class Process {
|
||||
* of the process.
|
||||
*
|
||||
* @apiNote
|
||||
* Using both {@link #getInputStream} and {@link #inputReader(Charset)} has
|
||||
* unpredictable behavior since the buffered reader reads ahead from the
|
||||
* input stream.
|
||||
* Use either this method or the {@linkplain #getInputStream input stream}
|
||||
* but not both on the same {@code Process}.
|
||||
* The input reader consumes and buffers bytes from the input stream.
|
||||
* Bytes read from the input stream would not be seen by the reader and the
|
||||
* buffer contents are unpredictable.
|
||||
*
|
||||
* <p>When the process has terminated, and the standard input has not been redirected,
|
||||
* reading of the bytes available from the underlying stream is on a best effort basis and
|
||||
@@ -283,6 +352,16 @@ public abstract class Process {
|
||||
* If the {@code native.encoding} is not a valid charset name or not supported
|
||||
* the {@link Charset#defaultCharset()} is used.
|
||||
*
|
||||
* <p>The error reader should be {@linkplain BufferedReader#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* @apiNote
|
||||
* Use either this method or the {@linkplain #getErrorStream error stream}
|
||||
* but not both on the same {@code Process}.
|
||||
* The error reader consumes and buffers bytes from the error stream.
|
||||
* Bytes read from the error stream would not be seen by the reader and the
|
||||
* buffer contents are unpredictable.
|
||||
*
|
||||
* @return a {@link BufferedReader BufferedReader} using the
|
||||
* {@code native.encoding} if supported, otherwise, the
|
||||
* {@link Charset#defaultCharset()}
|
||||
@@ -314,10 +393,15 @@ public abstract class Process {
|
||||
* then the {@code InputStreamReader} will be reading from a
|
||||
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
|
||||
*
|
||||
* <p>The error reader should be {@linkplain BufferedReader#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* @apiNote
|
||||
* Using both {@link #getErrorStream} and {@link #errorReader(Charset)} has
|
||||
* unpredictable behavior since the buffered reader reads ahead from the
|
||||
* error stream.
|
||||
* Use either this method or the {@linkplain #getErrorStream error stream}
|
||||
* but not both on the same {@code Process}.
|
||||
* The error reader consumes and buffers bytes from the error stream.
|
||||
* Bytes read from the error stream would not be seen by the reader and the
|
||||
* buffer contents are unpredictable.
|
||||
*
|
||||
* <p>When the process has terminated, and the standard error has not been redirected,
|
||||
* reading of the bytes available from the underlying stream is on a best effort basis and
|
||||
@@ -346,7 +430,7 @@ public abstract class Process {
|
||||
/**
|
||||
* Returns a {@code BufferedWriter} connected to the normal input of the process
|
||||
* using the native encoding.
|
||||
* Writes text to a character-output stream, buffering characters so as to provide
|
||||
* Writes text to a character-output stream, buffering characters to provide
|
||||
* for the efficient writing of single characters, arrays, and strings.
|
||||
*
|
||||
* <p>This method delegates to {@link #outputWriter(Charset)} using the
|
||||
@@ -354,6 +438,9 @@ public abstract class Process {
|
||||
* If the {@code native.encoding} is not a valid charset name or not supported
|
||||
* the {@link Charset#defaultCharset()} is used.
|
||||
*
|
||||
* <p>The output writer should be {@linkplain BufferedWriter#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* @return a {@code BufferedWriter} to the standard input of the process using the charset
|
||||
* for the {@code native.encoding} system property
|
||||
* @since 17
|
||||
@@ -365,7 +452,7 @@ public abstract class Process {
|
||||
/**
|
||||
* Returns a {@code BufferedWriter} connected to the normal input of the process
|
||||
* using a Charset.
|
||||
* Writes text to a character-output stream, buffering characters so as to provide
|
||||
* Writes text to a character-output stream, buffering characters to provide
|
||||
* for the efficient writing of single characters, arrays, and strings.
|
||||
*
|
||||
* <p>Characters written by the writer are encoded to bytes using {@link OutputStreamWriter}
|
||||
@@ -383,6 +470,9 @@ public abstract class Process {
|
||||
* ProcessBuilder.redirectInput} then the {@code OutputStreamWriter} writes to a
|
||||
* <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
|
||||
*
|
||||
* <p>The output writer should be {@linkplain BufferedWriter#close closed}
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* @apiNote
|
||||
* A {@linkplain BufferedWriter} writes characters, arrays of characters, and strings.
|
||||
* Wrapping the {@link BufferedWriter} with a {@link PrintWriter} provides
|
||||
@@ -674,11 +764,12 @@ public abstract class Process {
|
||||
* free the current thread and block only if and when the value is needed.
|
||||
* <br>
|
||||
* For example, launching a process to compare two files and get a boolean if they are identical:
|
||||
* <pre> {@code Process p = new ProcessBuilder("cmp", "f1", "f2").start();
|
||||
* Future<Boolean> identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0);
|
||||
* ...
|
||||
* if (identical.get()) { ... }
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* Process p = new ProcessBuilder("cmp", "f1", "f2").start();
|
||||
* Future<Boolean> identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0);
|
||||
* ...
|
||||
* if (identical.get()) { ... }
|
||||
* }
|
||||
*
|
||||
* @implSpec
|
||||
* This implementation executes {@link #waitFor()} in a separate thread
|
||||
@@ -695,11 +786,11 @@ public abstract class Process {
|
||||
* External implementations should override this method and provide
|
||||
* a more efficient implementation. For example, to delegate to the underlying
|
||||
* process, it can do the following:
|
||||
* <pre>{@code
|
||||
* {@snippet lang = "java" :
|
||||
* public CompletableFuture<Process> onExit() {
|
||||
* return delegate.onExit().thenApply(p -> this);
|
||||
* }
|
||||
* }</pre>
|
||||
* }
|
||||
* @apiNote
|
||||
* The process may be observed to have terminated with {@link #isAlive}
|
||||
* before the ComputableFuture is completed and dependent actions are invoked.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -150,30 +150,33 @@ import jdk.internal.event.ProcessStartEvent;
|
||||
* <p>Starting a new process which uses the default working directory
|
||||
* and environment is easy:
|
||||
*
|
||||
* <pre> {@code
|
||||
* {@snippet lang = "java" :
|
||||
|
||||
* Process p = new ProcessBuilder("myCommand", "myArg").start();
|
||||
* }</pre>
|
||||
* }
|
||||
|
||||
*
|
||||
* <p>Here is an example that starts a process with a modified working
|
||||
* directory and environment, and redirects standard output and error
|
||||
* to be appended to a log file:
|
||||
*
|
||||
* <pre> {@code
|
||||
* ProcessBuilder pb =
|
||||
* new ProcessBuilder("myCommand", "myArg1", "myArg2");
|
||||
* Map<String, String> env = pb.environment();
|
||||
* env.put("VAR1", "myValue");
|
||||
* env.remove("OTHERVAR");
|
||||
* env.put("VAR2", env.get("VAR1") + "suffix");
|
||||
* pb.directory(new File("myDir"));
|
||||
* File log = new File("log");
|
||||
* pb.redirectErrorStream(true);
|
||||
* pb.redirectOutput(Redirect.appendTo(log));
|
||||
* Process p = pb.start();
|
||||
* assert pb.redirectInput() == Redirect.PIPE;
|
||||
* assert pb.redirectOutput().file() == log;
|
||||
* assert p.getInputStream().read() == -1;
|
||||
* }</pre>
|
||||
* {@snippet lang = "java":
|
||||
* ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
|
||||
* Map<String, String> env = pb.environment();
|
||||
* env.put("VAR1", "myValue");
|
||||
* env.remove("OTHERVAR");
|
||||
* env.put("VAR2", env.get("VAR1") + "suffix");
|
||||
*
|
||||
* pb.directory(new File("myDir"));
|
||||
* File log = new File("log");
|
||||
* pb.redirectErrorStream(true);
|
||||
* pb.redirectOutput(Redirect.appendTo(log));
|
||||
*
|
||||
* Process p = pb.start();
|
||||
* assert pb.redirectInput() == Redirect.PIPE;
|
||||
* assert pb.redirectOutput().file() == log;
|
||||
* assert p.getInputStream().read() == -1;
|
||||
* }
|
||||
*
|
||||
* <p>To start a process with an explicit set of environment
|
||||
* variables, first call {@link java.util.Map#clear() Map.clear()}
|
||||
@@ -506,10 +509,10 @@ public final class ProcessBuilder
|
||||
* This is the default handling of subprocess standard I/O.
|
||||
*
|
||||
* <p>It will always be true that
|
||||
* <pre> {@code
|
||||
* Redirect.PIPE.file() == null &&
|
||||
* Redirect.PIPE.type() == Redirect.Type.PIPE
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* Redirect.PIPE.file() == null &&
|
||||
* Redirect.PIPE.type() == Redirect.Type.PIPE
|
||||
* }
|
||||
*/
|
||||
public static final Redirect PIPE = new Redirect() {
|
||||
public Type type() { return Type.PIPE; }
|
||||
@@ -521,10 +524,10 @@ public final class ProcessBuilder
|
||||
* behavior of most operating system command interpreters (shells).
|
||||
*
|
||||
* <p>It will always be true that
|
||||
* <pre> {@code
|
||||
* Redirect.INHERIT.file() == null &&
|
||||
* Redirect.INHERIT.type() == Redirect.Type.INHERIT
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* Redirect.INHERIT.file() == null &&
|
||||
* Redirect.INHERIT.type() == Redirect.Type.INHERIT
|
||||
* }
|
||||
*/
|
||||
public static final Redirect INHERIT = new Redirect() {
|
||||
public Type type() { return Type.INHERIT; }
|
||||
@@ -537,11 +540,10 @@ public final class ProcessBuilder
|
||||
* an operating system specific "null file".
|
||||
*
|
||||
* <p>It will always be true that
|
||||
* <pre> {@code
|
||||
* Redirect.DISCARD.file() is the filename appropriate for the operating system
|
||||
* and may be null &&
|
||||
* Redirect.DISCARD.type() == Redirect.Type.WRITE
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* Redirect.DISCARD.file() != null && // is the filename appropriate for the operating system
|
||||
* Redirect.DISCARD.type() == Redirect.Type.WRITE;
|
||||
* }
|
||||
* @since 9
|
||||
*/
|
||||
public static final Redirect DISCARD = new Redirect() {
|
||||
@@ -572,10 +574,10 @@ public final class ProcessBuilder
|
||||
* Returns a redirect to read from the specified file.
|
||||
*
|
||||
* <p>It will always be true that
|
||||
* <pre> {@code
|
||||
* Redirect.from(file).file() == file &&
|
||||
* Redirect.from(file).type() == Redirect.Type.READ
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* Redirect.from(file).file() == file &&
|
||||
* Redirect.from(file).type() == Redirect.Type.READ
|
||||
* }
|
||||
*
|
||||
* @param file The {@code File} for the {@code Redirect}.
|
||||
* @return a redirect to read from the specified file
|
||||
@@ -598,10 +600,10 @@ public final class ProcessBuilder
|
||||
* its previous contents will be discarded.
|
||||
*
|
||||
* <p>It will always be true that
|
||||
* <pre> {@code
|
||||
* Redirect.to(file).file() == file &&
|
||||
* Redirect.to(file).type() == Redirect.Type.WRITE
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* Redirect.to(file).file() == file &&
|
||||
* Redirect.to(file).type() == Redirect.Type.WRITE
|
||||
* }
|
||||
*
|
||||
* @param file The {@code File} for the {@code Redirect}.
|
||||
* @return a redirect to write to the specified file
|
||||
@@ -628,10 +630,10 @@ public final class ProcessBuilder
|
||||
* system-dependent and therefore unspecified.
|
||||
*
|
||||
* <p>It will always be true that
|
||||
* <pre> {@code
|
||||
* Redirect.appendTo(file).file() == file &&
|
||||
* Redirect.appendTo(file).type() == Redirect.Type.APPEND
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* Redirect.appendTo(file).file() == file &&
|
||||
* Redirect.appendTo(file).type() == Redirect.Type.APPEND
|
||||
* }
|
||||
*
|
||||
* @param file The {@code File} for the {@code Redirect}.
|
||||
* @return a redirect to append to the specified file
|
||||
@@ -914,15 +916,15 @@ public final class ProcessBuilder
|
||||
* to be the same as those of the current Java process.
|
||||
*
|
||||
* <p>This is a convenience method. An invocation of the form
|
||||
* <pre> {@code
|
||||
* pb.inheritIO()
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* pb.inheritIO()
|
||||
* }
|
||||
* behaves in exactly the same way as the invocation
|
||||
* <pre> {@code
|
||||
* pb.redirectInput(Redirect.INHERIT)
|
||||
* .redirectOutput(Redirect.INHERIT)
|
||||
* .redirectError(Redirect.INHERIT)
|
||||
* }</pre>
|
||||
* {@snippet lang = "java" :
|
||||
* pb.redirectInput(Redirect.INHERIT)
|
||||
* .redirectOutput(Redirect.INHERIT)
|
||||
* .redirectError(Redirect.INHERIT)
|
||||
* }
|
||||
*
|
||||
* This gives behavior equivalent to most operating system
|
||||
* command interpreters, or the standard C library function
|
||||
@@ -1176,22 +1178,21 @@ public final class ProcessBuilder
|
||||
* @apiNote
|
||||
* For example to count the unique imports for all the files in a file hierarchy
|
||||
* on a Unix compatible platform:
|
||||
* <pre>{@code
|
||||
* String directory = "/home/duke/src";
|
||||
* ProcessBuilder[] builders = {
|
||||
* {@snippet lang = "java" :
|
||||
* String directory = "/home/duke/src";
|
||||
* ProcessBuilder[] builders = {
|
||||
* new ProcessBuilder("find", directory, "-type", "f"),
|
||||
* new ProcessBuilder("xargs", "grep", "-h", "^import "),
|
||||
* new ProcessBuilder("awk", "{print $2;}"),
|
||||
* new ProcessBuilder("sort", "-u")};
|
||||
* List<Process> processes = ProcessBuilder.startPipeline(
|
||||
* Arrays.asList(builders));
|
||||
* Process last = processes.get(processes.size()-1);
|
||||
* try (InputStream is = last.getInputStream();
|
||||
* List<Process> processes = ProcessBuilder.startPipeline( Arrays.asList(builders));
|
||||
* Process last = processes.get(processes.size() - 1);
|
||||
* try (InputStream is = last.getInputStream();
|
||||
* Reader isr = new InputStreamReader(is);
|
||||
* BufferedReader r = new BufferedReader(isr)) {
|
||||
* long count = r.lines().count();
|
||||
* long count = r.lines().count();
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param builders a List of ProcessBuilders
|
||||
* @return a {@code List<Process>}es started from the corresponding
|
||||
|
||||
@@ -1589,6 +1589,11 @@ public final class String
|
||||
* @return {@code true} if {@link #length()} is {@code 0}, otherwise
|
||||
* {@code false}
|
||||
*
|
||||
* @apiNote
|
||||
* To determine whether a string contains only
|
||||
* {@linkplain Character#isWhitespace(int) white space}, use
|
||||
* {@link #isBlank() isBlank}.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
@Override
|
||||
@@ -3827,9 +3832,13 @@ public final class String
|
||||
* begins with the character at index <i>k</i> and ends with the
|
||||
* character at index <i>m</i>-that is, the result of
|
||||
* {@code this.substring(k, m + 1)}.
|
||||
* <p>
|
||||
* This method may be used to trim space (as defined above) from
|
||||
* the beginning and end of a string.
|
||||
*
|
||||
* @apiNote
|
||||
* This method removes leading and trailing space characters and ASCII control
|
||||
* characters from the string. To remove characters using a Unicode-based definition of
|
||||
* {@linkplain Character#isWhitespace(int) white space}, use {@link #strip() strip},
|
||||
* {@link #stripIndent() stripIndent}, {@link #stripLeading() stripLeading}, or
|
||||
* {@link #stripTrailing() stripTrailing}.
|
||||
*
|
||||
* @return a string whose value is this string, with all leading
|
||||
* and trailing space removed, or this string if it
|
||||
@@ -3934,13 +3943,9 @@ public final class String
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the string is empty or contains only
|
||||
* {@linkplain Character#isWhitespace(int) white space} codepoints,
|
||||
* otherwise {@code false}.
|
||||
*
|
||||
* @return {@code true} if the string is empty or contains only
|
||||
* {@linkplain Character#isWhitespace(int) white space} codepoints,
|
||||
* otherwise {@code false}
|
||||
* {@return {@code true} if the string is {@linkplain #isEmpty empty} or contains
|
||||
* only {@linkplain Character#isWhitespace(int) white space} codepoints,
|
||||
* otherwise {@code false}}
|
||||
*
|
||||
* @see Character#isWhitespace(int)
|
||||
*
|
||||
|
||||
@@ -81,24 +81,24 @@ import java.util.Objects;
|
||||
* {@link PEMRecord}.
|
||||
*
|
||||
* <p> The {@linkplain #decode(String, Class)} and
|
||||
* {@linkplain #decode(InputStream, Class)} methods take a Class parameter
|
||||
* {@linkplain #decode(InputStream, Class)} methods take a class parameter
|
||||
* which determines the type of {@code DEREncodable} that is returned. These
|
||||
* methods are useful when extracting or changing the return class.
|
||||
* For example, if the PEM contains both public and private keys, the
|
||||
* Class parameter can specify which to return. Use
|
||||
* class parameter can specify which to return. Use
|
||||
* {@code PrivateKey.class} to return only the private key.
|
||||
* If the Class parameter is set to {@code X509EncodedKeySpec.class}, the
|
||||
* If the class parameter is set to {@code X509EncodedKeySpec.class}, the
|
||||
* public key will be returned in that format. Any type of PEM data can be
|
||||
* decoded into a {@code PEMRecord} by specifying {@code PEMRecord.class}.
|
||||
* If the Class parameter doesn't match the PEM content, an
|
||||
* {@code IllegalArgumentException} will be thrown.
|
||||
* If the class parameter doesn't match the PEM content, a
|
||||
* {@linkplain ClassCastException} will be thrown.
|
||||
*
|
||||
* <p> A new {@code PEMDecoder} instance is created when configured
|
||||
* with {@linkplain #withFactory(Provider)} and/or
|
||||
* {@linkplain #withDecryption(char[])}. {@linkplain #withFactory(Provider)}
|
||||
* configures the decoder to use only {@linkplain KeyFactory} and
|
||||
* {@linkplain CertificateFactory} instances from the given {@code Provider}.
|
||||
* {@link#withDecryption(char[])} configures the decoder to decrypt all
|
||||
* {@linkplain #withDecryption(char[])} configures the decoder to decrypt all
|
||||
* encrypted private key PEM data using the given password.
|
||||
* Configuring an instance for decryption does not prevent decoding with
|
||||
* unencrypted PEM. Any encrypted PEM that fails decryption
|
||||
@@ -117,15 +117,15 @@ import java.util.Objects;
|
||||
* <p> Here is an example of a {@code PEMDecoder} configured with decryption
|
||||
* and a factory provider:
|
||||
* {@snippet lang = java:
|
||||
* PEMDecoder pe = PEMDecoder.of().withDecryption(password).
|
||||
* PEMDecoder pd = PEMDecoder.of().withDecryption(password).
|
||||
* withFactory(provider);
|
||||
* byte[] pemData = pe.decode(privKey);
|
||||
* byte[] pemData = pd.decode(privKey);
|
||||
* }
|
||||
*
|
||||
* @implNote An implementation may support other PEM types and
|
||||
* {@code DEREncodables}. This implementation additionally supports PEM types:
|
||||
* {@code X509 CERTIFICATE}, {@code X.509 CERTIFICATE}, {@code CRL},
|
||||
* and {@code RSA PRIVATE KEY}.
|
||||
* {@code DEREncodable} objects. This implementation additionally supports
|
||||
* the following PEM types: {@code X509 CERTIFICATE},
|
||||
* {@code X.509 CERTIFICATE}, {@code CRL}, and {@code RSA PRIVATE KEY}.
|
||||
*
|
||||
* @see PEMEncoder
|
||||
* @see PEMRecord
|
||||
@@ -179,13 +179,13 @@ public final class PEMDecoder {
|
||||
return switch (pem.type()) {
|
||||
case Pem.PUBLIC_KEY -> {
|
||||
X509EncodedKeySpec spec =
|
||||
new X509EncodedKeySpec(decoder.decode(pem.pem()));
|
||||
new X509EncodedKeySpec(decoder.decode(pem.content()));
|
||||
yield getKeyFactory(
|
||||
KeyUtil.getAlgorithm(spec.getEncoded())).
|
||||
generatePublic(spec);
|
||||
}
|
||||
case Pem.PRIVATE_KEY -> {
|
||||
PKCS8Key p8key = new PKCS8Key(decoder.decode(pem.pem()));
|
||||
PKCS8Key p8key = new PKCS8Key(decoder.decode(pem.content()));
|
||||
String algo = p8key.getAlgorithm();
|
||||
KeyFactory kf = getKeyFactory(algo);
|
||||
DEREncodable d = kf.generatePrivate(
|
||||
@@ -216,27 +216,27 @@ public final class PEMDecoder {
|
||||
case Pem.ENCRYPTED_PRIVATE_KEY -> {
|
||||
if (password == null) {
|
||||
yield new EncryptedPrivateKeyInfo(decoder.decode(
|
||||
pem.pem()));
|
||||
pem.content()));
|
||||
}
|
||||
yield new EncryptedPrivateKeyInfo(decoder.decode(pem.pem())).
|
||||
yield new EncryptedPrivateKeyInfo(decoder.decode(pem.content())).
|
||||
getKey(password.getPassword());
|
||||
}
|
||||
case Pem.CERTIFICATE, Pem.X509_CERTIFICATE,
|
||||
Pem.X_509_CERTIFICATE -> {
|
||||
CertificateFactory cf = getCertFactory("X509");
|
||||
yield (X509Certificate) cf.generateCertificate(
|
||||
new ByteArrayInputStream(decoder.decode(pem.pem())));
|
||||
new ByteArrayInputStream(decoder.decode(pem.content())));
|
||||
}
|
||||
case Pem.X509_CRL, Pem.CRL -> {
|
||||
CertificateFactory cf = getCertFactory("X509");
|
||||
yield (X509CRL) cf.generateCRL(
|
||||
new ByteArrayInputStream(decoder.decode(pem.pem())));
|
||||
new ByteArrayInputStream(decoder.decode(pem.content())));
|
||||
}
|
||||
case Pem.RSA_PRIVATE_KEY -> {
|
||||
KeyFactory kf = getKeyFactory("RSA");
|
||||
yield kf.generatePrivate(
|
||||
RSAPrivateCrtKeyImpl.getKeySpec(decoder.decode(
|
||||
pem.pem())));
|
||||
pem.content())));
|
||||
}
|
||||
default -> pem;
|
||||
};
|
||||
@@ -271,7 +271,6 @@ public final class PEMDecoder {
|
||||
*/
|
||||
public DEREncodable decode(String str) {
|
||||
Objects.requireNonNull(str);
|
||||
DEREncodable de;
|
||||
try {
|
||||
return decode(new ByteArrayInputStream(
|
||||
str.getBytes(StandardCharsets.UTF_8)));
|
||||
@@ -483,9 +482,6 @@ public final class PEMDecoder {
|
||||
* from the specified {@link Provider} to produce cryptographic objects.
|
||||
* Any errors using the {@code Provider} will occur during decoding.
|
||||
*
|
||||
* <p>If {@code provider} is {@code null}, a new instance is returned with
|
||||
* the default provider configuration.
|
||||
*
|
||||
* @param provider the factory provider
|
||||
* @return a new PEMEncoder instance configured to the {@code Provider}.
|
||||
* @throws NullPointerException if {@code provider} is null
|
||||
|
||||
@@ -71,7 +71,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* OneAsymmetricKey structure using the "PRIVATE KEY" type.
|
||||
*
|
||||
* <p> When encoding a {@link PEMRecord}, the API surrounds the
|
||||
* {@linkplain PEMRecord#pem()} with the PEM header and footer
|
||||
* {@linkplain PEMRecord#content()} with the PEM header and footer
|
||||
* from {@linkplain PEMRecord#type()}. {@linkplain PEMRecord#leadingData()} is
|
||||
* not included in the encoding. {@code PEMRecord} will not perform
|
||||
* validity checks on the data.
|
||||
@@ -108,7 +108,8 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* byte[] pemData = pe.encode(privKey);
|
||||
* }
|
||||
*
|
||||
* @implNote An implementation may support other PEM types and DEREncodables.
|
||||
* @implNote An implementation may support other PEM types and
|
||||
* {@code DEREncodable} objects.
|
||||
*
|
||||
*
|
||||
* @see PEMDecoder
|
||||
@@ -287,7 +288,7 @@ public final class PEMEncoder {
|
||||
}
|
||||
|
||||
// If `keySpec` is non-null, then `key` hasn't been established.
|
||||
// Setting a `key' prevents repeated key generations operations.
|
||||
// Setting a `key` prevents repeated key generation operations.
|
||||
// withEncryption() is a configuration method and cannot throw an
|
||||
// exception; therefore generation is delayed.
|
||||
if (keySpec != null) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import sun.security.util.Pem;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -39,20 +38,20 @@ import java.util.Objects;
|
||||
* cryptographic object is not desired or the type has no
|
||||
* {@code DEREncodable}.
|
||||
*
|
||||
* <p> {@code type} and {@code pem} may not be {@code null}.
|
||||
* <p> {@code type} and {@code content} may not be {@code null}.
|
||||
* {@code leadingData} may be null if no non-PEM data preceded PEM header
|
||||
* during decoding. {@code leadingData} may be useful for reading metadata
|
||||
* that accompanies PEM data.
|
||||
*
|
||||
* <p> No validation is performed during instantiation to ensure that
|
||||
* {@code type} conforms to {@code RFC 7468}, that {@code pem} is valid Base64,
|
||||
* or that {@code pem} matches the {@code type}. {@code leadingData} is not
|
||||
* defensively copied and does not return a clone when
|
||||
* {@linkplain #leadingData()} is called.
|
||||
* {@code type} conforms to {@code RFC 7468}, that {@code content} is valid
|
||||
* Base64, or that {@code content} matches the {@code type}.
|
||||
* {@code leadingData} is not defensively copied and does not return a
|
||||
* clone when {@linkplain #leadingData()} is called.
|
||||
*
|
||||
* @param type the type identifier in the PEM header without PEM syntax labels.
|
||||
* For a public key, {@code type} would be "PUBLIC KEY".
|
||||
* @param pem any data between the PEM header and footer.
|
||||
* @param content the Base64-encoded data, excluding the PEM header and footer
|
||||
* @param leadingData any non-PEM data preceding the PEM header when decoding.
|
||||
*
|
||||
* @spec https://www.rfc-editor.org/info/rfc7468
|
||||
@@ -64,25 +63,25 @@ import java.util.Objects;
|
||||
* @since 25
|
||||
*/
|
||||
@PreviewFeature(feature = PreviewFeature.Feature.PEM_API)
|
||||
public record PEMRecord(String type, String pem, byte[] leadingData)
|
||||
public record PEMRecord(String type, String content, byte[] leadingData)
|
||||
implements DEREncodable {
|
||||
|
||||
/**
|
||||
* Creates a {@code PEMRecord} instance with the given parameters.
|
||||
*
|
||||
* @param type the type identifier
|
||||
* @param pem the Base64-encoded data encapsulated by the PEM header and
|
||||
* footer.
|
||||
* @param content the Base64-encoded data, excluding the PEM header and
|
||||
* footer
|
||||
* @param leadingData any non-PEM data read during the decoding process
|
||||
* before the PEM header. This value maybe {@code null}.
|
||||
* @throws IllegalArgumentException if the {@code type} is incorrectly
|
||||
* @throws IllegalArgumentException if {@code type} is incorrectly
|
||||
* formatted.
|
||||
* @throws NullPointerException if {@code type} and/or {@code pem} are
|
||||
* @throws NullPointerException if {@code type} and/or {@code content} are
|
||||
* {@code null}.
|
||||
*/
|
||||
public PEMRecord(String type, String pem, byte[] leadingData) {
|
||||
public PEMRecord {
|
||||
Objects.requireNonNull(type, "\"type\" cannot be null.");
|
||||
Objects.requireNonNull(pem, "\"pem\" cannot be null.");
|
||||
Objects.requireNonNull(content, "\"content\" cannot be null.");
|
||||
|
||||
// With no validity checking on `type`, the constructor accept anything
|
||||
// including lowercase. The onus is on the caller.
|
||||
@@ -92,37 +91,22 @@ public record PEMRecord(String type, String pem, byte[] leadingData)
|
||||
"Only the PEM type identifier is allowed");
|
||||
}
|
||||
|
||||
this.type = type;
|
||||
this.pem = pem;
|
||||
this.leadingData = leadingData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code PEMRecord} instance with a given {@code type} and
|
||||
* {@code pem} data in String form. {@code leadingData} is set to null.
|
||||
* {@code content} data in String form. {@code leadingData} is set to null.
|
||||
*
|
||||
* @param type the PEM type identifier
|
||||
* @param pem the Base64-encoded data encapsulated by the PEM header and
|
||||
* footer.
|
||||
* @throws IllegalArgumentException if the {@code type} is incorrectly
|
||||
* @param content the Base64-encoded data, excluding the PEM header and
|
||||
* footer
|
||||
* @throws IllegalArgumentException if {@code type} is incorrectly
|
||||
* formatted.
|
||||
* @throws NullPointerException if {@code type} and/or {@code pem} are
|
||||
* @throws NullPointerException if {@code type} and/or {@code content} are
|
||||
* {@code null}.
|
||||
*/
|
||||
public PEMRecord(String type, String pem) {
|
||||
this(type, pem, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the binary encoding from the Base64 data contained in
|
||||
* {@code pem}.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code pem} cannot be decoded.
|
||||
* @return a new array of the binary encoding each time this
|
||||
* method is called.
|
||||
*/
|
||||
public byte[] getEncoded() {
|
||||
return Base64.getMimeDecoder().decode(pem);
|
||||
public PEMRecord(String type, String content) {
|
||||
this(type, content, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -177,8 +177,11 @@ public class ThreadDumper {
|
||||
container.children().forEach(c -> dumpThreads(c, writer));
|
||||
}
|
||||
|
||||
private static void dumpThread(Thread thread, TextWriter writer) {
|
||||
private static boolean dumpThread(Thread thread, TextWriter writer) {
|
||||
ThreadSnapshot snapshot = ThreadSnapshot.of(thread);
|
||||
if (snapshot == null) {
|
||||
return false; // thread terminated
|
||||
}
|
||||
Instant now = Instant.now();
|
||||
Thread.State state = snapshot.threadState();
|
||||
writer.println("#" + thread.threadId() + " \"" + snapshot.threadName()
|
||||
@@ -217,6 +220,7 @@ public class ThreadDumper {
|
||||
depth++;
|
||||
}
|
||||
writer.println();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,8 +288,9 @@ public class ThreadDumper {
|
||||
Iterator<Thread> threads = container.threads().iterator();
|
||||
while (threads.hasNext()) {
|
||||
Thread thread = threads.next();
|
||||
dumpThread(thread, jsonWriter);
|
||||
threadCount++;
|
||||
if (dumpThread(thread, jsonWriter)) {
|
||||
threadCount++;
|
||||
}
|
||||
}
|
||||
jsonWriter.endArray(); // threads
|
||||
|
||||
@@ -303,11 +308,15 @@ public class ThreadDumper {
|
||||
|
||||
/**
|
||||
* Write a thread to the given JSON writer.
|
||||
* @return true if the thread dump was written, false otherwise
|
||||
* @throws UncheckedIOException if an I/O error occurs
|
||||
*/
|
||||
private static void dumpThread(Thread thread, JsonWriter jsonWriter) {
|
||||
private static boolean dumpThread(Thread thread, JsonWriter jsonWriter) {
|
||||
Instant now = Instant.now();
|
||||
ThreadSnapshot snapshot = ThreadSnapshot.of(thread);
|
||||
if (snapshot == null) {
|
||||
return false; // thread terminated
|
||||
}
|
||||
Thread.State state = snapshot.threadState();
|
||||
StackTraceElement[] stackTrace = snapshot.stackTrace();
|
||||
|
||||
@@ -369,6 +378,7 @@ public class ThreadDumper {
|
||||
}
|
||||
|
||||
jsonWriter.endObject();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,12 +52,14 @@ class ThreadSnapshot {
|
||||
|
||||
/**
|
||||
* Take a snapshot of a Thread to get all information about the thread.
|
||||
* Return null if a ThreadSnapshot is not created, for example if the
|
||||
* thread has terminated.
|
||||
* @throws UnsupportedOperationException if not supported by VM
|
||||
*/
|
||||
static ThreadSnapshot of(Thread thread) {
|
||||
ThreadSnapshot snapshot = create(thread);
|
||||
if (snapshot == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
return null; // thread terminated
|
||||
}
|
||||
if (snapshot.stackTrace == null) {
|
||||
snapshot.stackTrace = EMPTY_STACK;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -34,8 +34,8 @@ java.launcher.opt.footer = \ -cp <Klassensuchpfad mit Verzeichnissen und ZIP-
|
||||
Granularität\n -da[:<packagename>...|:<classname>]\n -disableassertions[:<packagename>...|:<classname>]\n Deaktiviert Assertions mit angegebener Granularität\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:<libname>[=<options>]\n Lädt die native Agent Library <libname>. Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:<pathname>[=<options>]\n Lädt die native Agent Library mit dem vollständigen Pfadnamen\n -javaagent:<jarpath>[=<options>]\n Lädt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:<imagepath>\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterstützt und verwendet,\n falls verfügbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" übergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgewählt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n --disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\n --enable-preview\n Lässt zu, das Klassen von Vorschaufeatures dieses Release abhängig sind\nUm ein Argument für eine lange Option anzugeben, können Sie --<Name>=<Wert> oder\n--<Name> <Wert> verwenden.\n
|
||||
|
||||
# Translators please note do not translate the options themselves
|
||||
java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:<durch {0} getrennte Verzeichnisse und ZIP-/JAR-Dateien>\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog:<Optionen> Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc:<Datei> Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc:<Datei> ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn<Größe> Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms<Größe> Legt die anfängliche Java-Heap-Größe fest\n -Xmx<Größe> Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss<Größe> Legt die Stackgröße des Java-Threads fest\n Die tatsächliche Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n \
|
||||
Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zukünftigen Release entfernt werden kann.\n --add-reads <Modul>=<Zielmodul>(,<Zielmodul>)*\n Aktualisiert <Modul>, damit <Zielmodul> gelesen wird, ungeachtet\n der Moduldeklaration. \n <Zielmodul> kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports <Modul>/<Package>=<Zielmodul>(,<Zielmodul>)*\n Aktualisiert <Modul>, um <Package> in <Zielmodul> zu exportieren,\n ungeachtet der Moduldeklaration.\n <Zielmodul> kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens <Modul>/<Package>=<Zielmodul>(,<Zielmodul>)*\n Aktualisiert <Modul>, um <Package> in\n <Zielmodul> zu öffnen, ungeachtet der Moduldeklaration.\n --limit-modules <Modulname>[,<Modulname>...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module <Modul>=<Datei>({0}<Datei>)*\n Überschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source <Version>\n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=<Wert>\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist <Wert> entweder "enabled" oder "disabled".\n Die Finalisierung ist standardmäßig aktiviert.\n --sun-misc-unsafe-memory-access=<value>\n Verwendung der nicht unterstützten API sun.misc.Unsafe zulassen oder verweigern\n <value> ist "allow", "warn", "debug" oder "deny".\n Der Standardwert ist "warn".\n\nDiese zusätzlichen Optionen können jederzeit ohne vorherige Ankündigung geändert werden.\n
|
||||
java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:<durch {0} getrennte Verzeichnisse und ZIP-/JAR-Dateien>\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog:<Optionen> Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc:<Datei> Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc:<Datei> ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn<Größe> Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms<size> Legt die minimale und die anfängliche Java-Heap-Größe fest\n -Xmx<Größe> Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss<Größe> Legt die Stackgröße des Java-Threads fest\n Die tatsächliche Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n \
|
||||
Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zukünftigen Release entfernt werden kann.\n --add-reads <Modul>=<Zielmodul>(,<Zielmodul>)*\n Aktualisiert <Modul>, damit <Zielmodul> gelesen wird, ungeachtet\n der Moduldeklaration. \n <Zielmodul> kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports <Modul>/<Package>=<Zielmodul>(,<Zielmodul>)*\n Aktualisiert <Modul>, um <Package> in <Zielmodul> zu exportieren,\n ungeachtet der Moduldeklaration.\n <Zielmodul> kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens <Modul>/<Package>=<Zielmodul>(,<Zielmodul>)*\n Aktualisiert <Modul>, um <Package> in\n <Zielmodul> zu öffnen, ungeachtet der Moduldeklaration.\n --limit-modules <Modulname>[,<Modulname>...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module <Modul>=<Datei>({0}<Datei>)*\n Überschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source <Version>\n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=<Wert>\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist <Wert> entweder "enabled" oder "disabled".\n Die Finalisierung ist standardmäßig aktiviert.\n --sun-misc-unsafe-memory-access=<value>\n Verwendung der nicht unterstützten API sun.misc.Unsafe zulassen oder verweigern\n <value> ist "allow", "warn", "debug" oder "deny".\n Der Standardwert ist "warn".\n\nDiese zusätzlichen Optionen können jederzeit ohne vorherige Ankündigung geändert werden.\n
|
||||
|
||||
# Translators please note do not translate the options themselves
|
||||
java.launcher.X.macosx.usage=\nDie folgenden Optionen sind für macOS spezifisch:\n -XstartOnFirstThread\n Führt die main()-Methode für den ersten (AppKit-)Thread aus\n -Xdock:name=<Anwendungsname>\n Setzt den im Dock angezeigten Standardanwendungsnamen außer Kraft\n -Xdock:icon=<Pfad zu Symboldatei>\n Setzt das im Dock angezeigte Standardsymbol außer Kraft\n\n
|
||||
@@ -51,6 +51,7 @@ java.launcher.cls.error4=Fehler: Beim Laden der Klasse {0} ist ein LinkageError
|
||||
java.launcher.cls.error5=Fehler: Hauptklasse {0} kann nicht initialisiert werden\nUrsache: {1}: {2}
|
||||
java.launcher.cls.error6=Fehler: Kein nicht privater Null-Argument-Konstruktor in Klasse {0} gefunden\nEntfernen Sie die Eigenschaft "private" aus dem vorhandenen Konstruktor, oder definieren Sie ihn als:\n public {0}()
|
||||
java.launcher.cls.error7=Fehler: Konstruktor mit nicht statischer innerer Klasse {0} kann nicht aufgerufen werden \nLegen Sie die innere Klasse als statisch fest, oder verschieben Sie sie in eine separate Quelldatei
|
||||
java.launcher.cls.error8=Fehler: Abstrakte Klasse {0} kann nicht instanziiert werden.\nVerwenden Sie eine konkrete Klasse
|
||||
java.launcher.jar.error1=Fehler: Beim Versuch, Datei {0} zu öffnen, ist ein unerwarteter Fehler aufgetreten
|
||||
java.launcher.jar.error2=Manifest in {0} nicht gefunden
|
||||
java.launcher.jar.error3=kein Hauptmanifestattribut, in {0}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -35,7 +35,7 @@ java.launcher.opt.footer = \ -cp <ディレクトリおよびzip/jarファイ
|
||||
-disableassertions[:<packagename>...|:<classname>]\n 指定した粒度でアサーションを無効にします\n -esa | -enablesystemassertions\n システム・アサーションを有効にします\n -dsa | -disablesystemassertions\n システム・アサーションを無効にします\n -agentlib:<libname>[=<options>]\n ネイティブ・エージェント・ライブラリ<libname>をロードします。例: -agentlib:jdwp\n -agentlib:jdwp=helpも参照してください\n -agentpath:<pathname>[=<options>]\n フルパス名を使用して、ネイティブ・エージェント・ライブラリをロードします\n -javaagent:<jarpath>[=<options>]\n Javaプログラミング言語エージェントをロードします。java.lang.instrumentを参照してください\n -splash:<imagepath>\n 指定されたイメージを含むスプラッシュ画面を表示します\n HiDPIスケールのイメージが自動的にサポートされて使用されます\n (可能な場合)。スケーリングされないイメージのファイル名(image.extなど)を\n 引数として-splashオプションに必ず渡す必要があります。\n 指定された最も適切なスケーリング済イメージが選択されます\n (自動的)。\n 詳細は、SplashScreen APIのドキュメントを参照してください\n @argumentファイル\n オプションを含む1つ以上の引数ファイル\n --disable-@files\n さらなる引数ファイル拡張を無効にします\n --enable-preview\n クラスをこのリリースのプレビュー機能に依存させることができます\n長いオプションの引数を指定する場合、--<name>=<value>または\n--<name> <value>を使用できます。\n
|
||||
|
||||
# Translators please note do not translate the options themselves
|
||||
java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:<directories and zip/jar files separated by {0}>\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog:<opts> Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc:<file> タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:<file>で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn<size> 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms<size> Javaの初期ヒープ・サイズを設定します\n -Xmx<size> Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off 共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n \
|
||||
java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:<directories and zip/jar files separated by {0}>\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog:<opts> Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc:<file> タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:<file>で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn<size> 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms<size> Javaの最小および初期のヒープ・サイズを設定します\n -Xmx<size> Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off 共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n \
|
||||
これはテスト・オプションであり、断続的な失敗につながる\n 可能性があります。本番環境では使用しないでください。\n -XshowSettings すべての設定を表示して続行します\n -XshowSettings:all\n すべての設定を詳細に表示して続行します\n -XshowSettings:locale\n すべてのロケール関連の設定を表示して続行します\n -XshowSettings:properties\n すべてのプロパティ設定を表示して続行します\n -XshowSettings:vm\n すべてのVM関連の設定を表示して続行します\n -XshowSettings:security\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:all\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:properties\n セキュリティ・プロパティを表示して続行します\n -XshowSettings:security:providers\n 静的セキュリティ・プロバイダ設定を表示して続行します\n -XshowSettings:security:tls\n TLS関連のセキュリティ設定を表示して続行します\n -XshowSettings:system\n (Linuxのみ)ホスト・システムまたはコンテナを表示します\n 構成して続行します\n -Xss<size> javaスレッドのスタック・サイズを設定します\n 実際のサイズは、次の倍数に切り上げられる場合があります: \n オペレーティング・システムの要件に応じたシステム・ページ・サイズ。\n -Xverify バイトコード・ベリファイアのモードを設定します\n オプション-Xverify:noneは非推奨になり、\n 将来のリリースで削除される可能性があります。\n --add-reads <module>=<target-module>(,<target-module>)*\n モジュール宣言に関係なく、<module>を更新して<target-module>を\n 読み取ります。 \n <target-module>をALL-UNNAMEDに設定すると、すべての名前のないモジュールを\n 読み取ることができます。\n --add-exports \
|
||||
<module>/<package>=<target-module>(,<target-module>)*\n モジュール宣言に関係なく、<module>を更新して<package>を<target-module>に\n エクスポートします。\n <target-module>をALL-UNNAMEDに設定すると、すべての名前のないモジュールに\n エクスポートできます。\n --add-opens <module>/<package>=<target-module>(,<target-module>)*\n モジュール宣言に関係なく、<module>を更新して<package>を\n <target-module>に開きます。\n --limit-modules <module name>[,<module name>...]\n 参照可能なモジュールの領域を制限します\n --patch-module <module>=<file>({0}<file>)*\n JARファイルまたはディレクトリのクラスおよびリソースで\n モジュールをオーバーライドまたは拡張します。\n --source <version>\n ソースファイル・モードでソースのバージョンを設定します。\n --finalization=<value>\n JVMがオブジェクトのファイナライズを実行するかどうかを制御します\n <value>は"enabled"または"disabled"のいずれかです。\n ファイナライズはデフォルトで有効になっています。\n --sun-misc-unsafe-memory-access=<value>\n サポートされていないAPI sun.misc.Unsafeの使用を許可または拒否します\n <value>は"allow"、"warn"、"debug"または"deny"のいずれかです。\n デフォルト値は"warn"です。\n\nこの追加オプションは予告なしに変更されることがあります。\n
|
||||
|
||||
@@ -53,6 +53,7 @@ java.launcher.cls.error4=エラー: メイン・クラス{0}のロード中にLi
|
||||
java.launcher.cls.error5=エラー: メイン・クラス{0}を初期化できません\n原因: {1}: {2}
|
||||
java.launcher.cls.error6=エラー: 非privateのゼロ引数コンストラクタがクラス{0}に見つかりません\n既存のコンストラクタからprivateを削除するか、次のように定義してください:\n public {0}()
|
||||
java.launcher.cls.error7=エラー: staticでない内部クラス{0}コンストラクタを起動できません \n内部クラスをstaticにするか、内部クラスを外部に出してソース・ファイルを区別してください
|
||||
java.launcher.cls.error8=エラー: 抽象クラス{0}はインスタンス化できません\n具象クラスを使用してください
|
||||
java.launcher.jar.error1=エラー: ファイル{0}を開こうとしているときに、予期しないエラーが発生しました
|
||||
java.launcher.jar.error2={0}にマニフェストが見つかりません
|
||||
java.launcher.jar.error3={0}にメイン・マニフェスト属性がありません
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# 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 @@ java.launcher.opt.footer = \ -cp <目录和 zip/jar 文件的类搜索路径>
|
||||
将产品版本输出到输出流并退出\n -showversion 将产品版本输出到错误流并继续\n --show-version\n 将产品版本输出到输出流并继续\n --show-module-resolution\n 在启动过程中显示模块解析输出\n -? -h -help\n 将此帮助消息输出到错误流\n --help 将此帮助消息输出到输出流\n -X 将额外选项的帮助输出到错误流\n --help-extra 将额外选项的帮助输出到输出流\n -ea[:<程序包名称>...|:<类名>]\n -enableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度启用断言\n -da[:<程序包名称>...|:<类名>]\n -disableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度禁用断言\n -esa | -enablesystemassertions\n 启用系统断言\n -dsa | -disablesystemassertions\n 禁用系统断言\n -agentlib:<库名>[=<选项>]\n 加载本机代理库 <库名>, 例如 -agentlib:jdwp\n 另请参阅 -agentlib:jdwp=help\n -agentpath:<路径名>[=<选项>]\n 按完整路径名加载本机代理库\n -javaagent:<jar 路径>[=<选项>]\n 加载 Java 编程语言代理, 请参阅 java.lang.instrument\n -splash:<图像路径>\n 使用指定的图像显示启动屏幕\n 自动支持和使用 HiDPI 缩放图像\n (如果可用)。应始终将未缩放的图像文件名 (例如, image.ext)\n 作为参数传递给 -splash 选项。\n 将自动选取提供的最合适的缩放\n 图像。\n 有关详细信息, 请参阅 SplashScreen API 文档\n @argument 文件\n 一个或多个包含选项的参数文件\n --disable-@files\n 阻止进一步扩展参数文件\n --enable-preview\n 允许类依赖于此发行版的预览功能\n要为长选项指定参数, 可以使用 --<名称>=<值> 或\n--<名称> <值>。\n
|
||||
|
||||
# Translators please note do not translate the options themselves
|
||||
java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog:<opts> 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc:<file> 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:<file>。\n -Xmixed 混合模式执行(默认值)\n -Xmn<size> 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms<size> 设置初始 Java 堆大小\n -Xmx<size> 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS \
|
||||
java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog:<opts> 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc:<file> 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:<file>。\n -Xmixed 混合模式执行(默认值)\n -Xmn<size> 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms<size> 设置最小和初始 Java 堆大小\n -Xmx<size> 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS \
|
||||
相关的安全设置并继续\n -XshowSettings:system\n (仅 Linux)显示主机系统或容器\n 配置并继续\n -Xss<size> 设置 Java 线程堆栈大小\n 实际大小可以舍入到\n 操作系统要求的系统页面大小的倍数。\n -Xverify 设置字节码验证器的模式\n 请注意,选项 -Xverify:none 已过时,\n 可能会在未来发行版中删除。\n --add-reads <module>=<target-module>(,<target-module>)*\n 更新 <module> 以读取 <target-module>,而无论\n 模块如何声明。 \n <target-module> 可以是 ALL-UNNAMED,将读取所有未命名\n 模块。\n --add-exports <module>/<package>=<target-module>(,<target-module>)*\n 更新 <module> 以将 <package> 导出到 <target-module>,\n 而无论模块如何声明。\n <target-module> 可以是 ALL-UNNAMED,将导出到所有\n 未命名模块。\n --add-opens <module>/<package>=<target-module>(,<target-module>)*\n 更新 <module> 以在 <target-module> 中打开\n <package>,而无论模块如何声明。\n --limit-modules <module name>[,<module name>...]\n 限制可观察模块的领域\n --patch-module <module>=<file>({0}<file>)*\n 使用 JAR 文件或目录中的类和资源\n 覆盖或增强模块。\n --source <version>\n 设置源文件模式中源的版本。\n --finalization=<value>\n 控制 JVM 是否执行对象最终处理,\n 其中 <value> 为 "enabled" 或 "disabled" 之一。\n 默认情况下,最终处理处于启用状态。\n --sun-misc-unsafe-memory-access=<value>\n 允许或拒绝使用不受支持的 API sun.misc.Unsafe\n <value> 为 "allow"、"warn"、"debug" 或 "deny" 之一。\n 默认值为 "warn"。\n\n这些额外选项如有更改, 恕不另行通知。\n
|
||||
|
||||
# Translators please note do not translate the options themselves
|
||||
@@ -51,6 +51,7 @@ java.launcher.cls.error4=错误: 加载主类 {0} 时出现 LinkageError\n\t{1}
|
||||
java.launcher.cls.error5=错误: 无法初始化主类 {0}\n原因: {1}: {2}
|
||||
java.launcher.cls.error6=错误:在类 {0} 中未找到非专用零参数构造器\n请从现有构造器中删除专用,或者定义为:\n public {0}()
|
||||
java.launcher.cls.error7=错误:无法调用非静态内部类 {0} 构造器\n请将内部类设为静态或将内部类移出到单独的源文件
|
||||
java.launcher.cls.error8=错误:无法实例化抽象类 {0}\n请使用具体类
|
||||
java.launcher.jar.error1=错误: 尝试打开文件{0}时出现意外错误
|
||||
java.launcher.jar.error2=在{0}中找不到清单
|
||||
java.launcher.jar.error3={0}中没有主清单属性
|
||||
|
||||
@@ -621,10 +621,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
if (port != -1 && port != url.getDefaultPort()) {
|
||||
host += ":" + String.valueOf(port);
|
||||
}
|
||||
String reqHost = requests.findValue("Host");
|
||||
if (reqHost == null || !reqHost.equalsIgnoreCase(host)) {
|
||||
requests.set("Host", host);
|
||||
}
|
||||
// if the "Host" header hasn't been explicitly set, then set its
|
||||
// value to the one determined through the request URL
|
||||
requests.setIfNotSet("Host", host);
|
||||
|
||||
requests.setIfNotSet("Accept", acceptString);
|
||||
|
||||
/*
|
||||
|
||||
@@ -94,6 +94,15 @@ public class Net {
|
||||
return EXCLUSIVE_BIND;
|
||||
}
|
||||
|
||||
private static final StableValue<Boolean> SHUTDOWN_WRITE_BEFORE_CLOSE = StableValue.of();
|
||||
|
||||
/**
|
||||
* Tells whether a TCP connection should be shutdown for writing before closing.
|
||||
*/
|
||||
static boolean shouldShutdownWriteBeforeClose() {
|
||||
return SHUTDOWN_WRITE_BEFORE_CLOSE.orElseSet(Net::shouldShutdownWriteBeforeClose0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether both IPV6_XXX and IP_XXX socket options should be set on
|
||||
* IPv6 sockets. On some kernels, both IPV6_XXX and IP_XXX socket options
|
||||
@@ -462,6 +471,8 @@ public class Net {
|
||||
*/
|
||||
private static native int isExclusiveBindAvailable();
|
||||
|
||||
private static native boolean shouldShutdownWriteBeforeClose0();
|
||||
|
||||
private static native boolean shouldSetBothIPv4AndIPv6Options0();
|
||||
|
||||
private static native boolean canIPv6SocketJoinIPv4Group0();
|
||||
|
||||
@@ -846,7 +846,7 @@ class SocketChannelImpl
|
||||
/**
|
||||
* Marks the beginning of a connect operation that might block.
|
||||
* @param blocking true if configured blocking
|
||||
* @param isa the remote address
|
||||
* @param sa the remote socket address
|
||||
* @throws ClosedChannelException if the channel is closed
|
||||
* @throws AlreadyConnectedException if already connected
|
||||
* @throws ConnectionPendingException is a connection is pending
|
||||
@@ -1070,8 +1070,8 @@ class SocketChannelImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the socket if there are no I/O operations in progress and the
|
||||
* channel is not registered with a Selector.
|
||||
* Closes the socket if there are no I/O operations in progress (or no I/O
|
||||
* operations tracked), and the channel is not registered with a Selector.
|
||||
*/
|
||||
private boolean tryClose() throws IOException {
|
||||
assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
|
||||
@@ -1096,11 +1096,21 @@ class SocketChannelImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this channel when configured in blocking mode.
|
||||
* Closes this channel when configured in blocking mode. If there are no I/O
|
||||
* operations in progress (or tracked), then the channel's socket is closed. If
|
||||
* there are I/O operations in progress then the behavior is platform specific.
|
||||
*
|
||||
* If there is an I/O operation in progress then the socket is pre-closed
|
||||
* and the I/O threads signalled, in which case the final close is deferred
|
||||
* until all I/O operations complete.
|
||||
* On Unix systems, the channel's socket is pre-closed. This unparks any virtual
|
||||
* threads that are blocked in I/O operations on this channel. If there are
|
||||
* platform threads blocked on the channel's socket then the socket is dup'ed
|
||||
* and the platform threads signalled. The final close is deferred until all I/O
|
||||
* operations complete.
|
||||
*
|
||||
* On Windows, the channel's socket is pre-closed. This unparks any virtual
|
||||
* threads that are blocked in I/O operations on this channel. If there are no
|
||||
* virtual threads blocked in I/O operations on this channel then the channel's
|
||||
* socket is closed. If there are virtual threads in I/O then the final close is
|
||||
* deferred until all I/O operations on virtual threads complete.
|
||||
*
|
||||
* Note that a channel configured blocking may be registered with a Selector
|
||||
* This arises when a key is canceled and the channel configured to blocking
|
||||
@@ -1112,17 +1122,17 @@ class SocketChannelImpl
|
||||
boolean connected = (state == ST_CONNECTED);
|
||||
state = ST_CLOSING;
|
||||
|
||||
if (!tryClose()) {
|
||||
if (connected && Net.shouldShutdownWriteBeforeClose()) {
|
||||
// shutdown output when linger interval not set to 0
|
||||
if (connected) {
|
||||
try {
|
||||
var SO_LINGER = StandardSocketOptions.SO_LINGER;
|
||||
if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) {
|
||||
Net.shutdown(fd, Net.SHUT_WR);
|
||||
}
|
||||
} catch (IOException ignore) { }
|
||||
}
|
||||
try {
|
||||
var SO_LINGER = StandardSocketOptions.SO_LINGER;
|
||||
if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) {
|
||||
Net.shutdown(fd, Net.SHUT_WR);
|
||||
}
|
||||
} catch (IOException ignore) { }
|
||||
}
|
||||
|
||||
if (!tryClose()) {
|
||||
// prepare file descriptor for closing
|
||||
nd.preClose(fd, readerThread, writerThread);
|
||||
}
|
||||
|
||||
@@ -565,7 +565,7 @@ public class X509Factory extends CertificateFactorySpi {
|
||||
} catch (EOFException e) {
|
||||
return null;
|
||||
}
|
||||
return Base64.getDecoder().decode(rec.pem());
|
||||
return Base64.getDecoder().decode(rec.content());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ NEWLINE=\n
|
||||
STAR=*******************************************
|
||||
STARNN=*******************************************\n\n
|
||||
# keytool: Help part
|
||||
.OPTION.=\u0020[OPTION]...
|
||||
.OPTION.=\ [OPTION]...
|
||||
Options.=Optionen:
|
||||
option.1.set.twice=Die Option %s wurde mehrmals angegeben. Alle Angaben bis auf die letzte werden ignoriert.
|
||||
multiple.commands.1.2=Nur ein Befehl ist zulässig: Sowohl %1$s als auch %2$s wurden angegeben.
|
||||
@@ -170,7 +170,7 @@ Certificate.reply.was.installed.in.keystore=Zertifikatsantwort wurde in Keystore
|
||||
Certificate.reply.was.not.installed.in.keystore=Zertifikatsantwort wurde nicht in Keystore installiert
|
||||
Certificate.was.added.to.keystore=Zertifikat wurde Keystore hinzugefügt
|
||||
Certificate.was.not.added.to.keystore=Zertifikat wurde nicht zu Keystore hinzugefügt
|
||||
.Storing.ksfname.=[{0} wird gesichert]
|
||||
.Storing.ksfname.=[{0} wird gespeichert]
|
||||
alias.has.no.public.key.certificate.={0} hat keinen Public Key (Zertifikat)
|
||||
Cannot.derive.signature.algorithm=Signaturalgorithmus kann nicht abgeleitet werden
|
||||
Alias.alias.does.not.exist=Alias <{0}> ist nicht vorhanden
|
||||
@@ -178,9 +178,9 @@ Alias.alias.has.no.certificate=Alias <{0}> hat kein Zertifikat
|
||||
groupname.keysize.coexist=Es können nicht sowohl -groupname als auch -keysize angegeben werden
|
||||
deprecate.keysize.for.ec=Das Angeben von -keysize zum Generieren von EC-Schlüsseln ist veraltet. Verwenden Sie stattdessen "-groupname %s".
|
||||
Key.pair.not.generated.alias.alias.already.exists=Schlüsselpaar wurde nicht generiert. Alias <{0}> ist bereits vorhanden
|
||||
size.bit.alg=%1$d-Bit %2$s
|
||||
Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=Schlüsselpaar {0} und selbstsigniertes Zertifikat ({1}) werden mit einer Gültigkeit von {2} Tagen generiert\n\tfür: {3}
|
||||
Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=Schlüsselpaar {0} und Zertifikat ({1}) werden generiert, das von <{2}> mit einer Gültigkeit von {3} Tagen ausgestellt wurde\n\tfür: {4}
|
||||
size.bit.alg=%1$d-Bit-%2$s
|
||||
Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=Generieren von {0}-Schlüsselpaar und selbstsigniertem Zertifikat ({1}) mit einer Gültigkeit von {2} Tagen\n\tfür: {3}
|
||||
Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=Generieren von {0}-Schlüsselpaar und einem von <{2}> ausgestellten Zertifikat ({1}) mit einer Gültigkeit von {3} Tagen\n\tfür: {4}
|
||||
Enter.key.password.for.alias.=Schlüsselkennwort für <{0}> eingeben
|
||||
.RETURN.if.same.as.keystore.password.=\t(RETURN, wenn identisch mit Keystore-Kennwort): \u0020
|
||||
Key.password.is.too.short.must.be.at.least.6.characters=Schlüsselkennwort ist zu kurz. Es muss mindestens sechs Zeichen lang sein
|
||||
@@ -216,7 +216,7 @@ Do.you.still.want.to.add.it.no.=Möchten Sie es trotzdem hinzufügen? [Nein]: \u
|
||||
Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias.=Zertifikat ist bereits unter Alias <{0}> im systemweiten CA-Keystore vorhanden
|
||||
Do.you.still.want.to.add.it.to.your.own.keystore.no.=Möchten Sie es trotzdem zu Ihrem eigenen Keystore hinzufügen? [Nein]: \u0020
|
||||
Trust.this.certificate.no.=Diesem Zertifikat vertrauen? [Nein]: \u0020
|
||||
New.prompt.=Neues {0}:\u0020
|
||||
New.prompt.={0} (neu):\u0020
|
||||
Passwords.must.differ=Kennwörter müssen sich unterscheiden
|
||||
Re.enter.new.prompt.=Neues {0} erneut eingeben:\u0020
|
||||
Re.enter.password.=Geben Sie das Kennwort erneut ein:\u0020
|
||||
@@ -238,7 +238,7 @@ Is.name.correct.=Ist {0} richtig?
|
||||
no=Nein
|
||||
yes=Ja
|
||||
y=J
|
||||
.defaultValue.=\u0020 [{0}]: \u0020
|
||||
.defaultValue.=\ [{0}]: \u0020
|
||||
Alias.alias.has.no.key=Alias <{0}> verfügt über keinen Schlüssel
|
||||
Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=Alias <{0}> verweist auf einen Eintragstyp, der kein Private-Key-Eintrag ist. Der Befehl -keyclone unterstützt nur das Klonen von Private-Key-Einträgen
|
||||
|
||||
@@ -302,8 +302,8 @@ alias.in.keystore=Aussteller <%s>
|
||||
with.weak=%s (schwach)
|
||||
with.disabled=%s (deaktiviert)
|
||||
key.bit=%s-Schlüssel
|
||||
key.bit.weak=%s Schlüssel (schwach)
|
||||
key.bit.disabled=%s Schlüssel (deaktiviert)
|
||||
key.bit.weak=%s-Schlüssel (schwach)
|
||||
key.bit.disabled=%s-Schlüssel (deaktiviert)
|
||||
.PATTERN.printX509Cert.with.weak=Eigentümer: {0}\nAussteller: {1}\nSeriennummer: {2}\nGültig von: {3} bis: {4}\nZertifikatsfingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignaturalgorithmusname: {7}\nPublic-Key-Algorithmus von Subject: {8}\nVersion: {9}
|
||||
PKCS.10.with.weak=PKCS #10-Zertifikatsanforderung (Version 1.0)\nSubject: %1$s\nFormat: %2$s\nPublic Key: %3$s\nSignaturalgorithmus: %4$s\n
|
||||
verified.by.s.in.s.weak=Von %1$s in %2$s mit %3$s verifiziert
|
||||
@@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$s verwendet den Signaturalgorithmus %2$s. Das gil
|
||||
Unable.to.parse.denyAfter.string.in.exception.message=denyAfter-Datumszeichenfolge in Ausnahmemeldung kann nicht geparst werden
|
||||
whose.sigalg.weak=%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko.
|
||||
whose.key.disabled=%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko und ist deaktiviert.
|
||||
whose.key.weak=%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko. Wird in einem zukünftigen Update deaktiviert.
|
||||
whose.key.weak=%1$s verwendet %2$s. Das gilt als Sicherheitsrisiko. Dieser Schlüssel wird in einem zukünftigen Update deaktiviert.
|
||||
jks.storetype.warning=Der %1$s-Keystore verwendet ein proprietäres Format. Es wird empfohlen, auf PKCS12 zu migrieren, das ein Industriestandardformat mit "keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12" ist.
|
||||
migrate.keystore.warning="%1$s" zu %4$s migriert. Der %2$s-Keystore wurde als "%3$s" gesichert.
|
||||
backup.keystore.warning=Der ursprüngliche Keystore "%1$s" wird als "%3$s" gesichert...
|
||||
|
||||
@@ -27,7 +27,7 @@ NEWLINE=\n
|
||||
STAR=*******************************************
|
||||
STARNN=*******************************************\n\n
|
||||
# keytool: Help part
|
||||
.OPTION.=\u0020[OPTION]...
|
||||
.OPTION.=\ [OPTION]...
|
||||
Options.=オプション:
|
||||
option.1.set.twice=%sオプションが複数回指定されています。最後のもの以外はすべて無視されます。
|
||||
multiple.commands.1.2=1つのコマンドのみ許可されます: %1$sと%2$sの両方が指定されました。
|
||||
@@ -178,9 +178,9 @@ Alias.alias.has.no.certificate=別名<{0}>には証明書がありません
|
||||
groupname.keysize.coexist=-groupnameと-keysizeの両方を指定できません
|
||||
deprecate.keysize.for.ec=-keysizeの指定によるECキーの生成は非推奨です。かわりに"-groupname %s"を使用してください。
|
||||
Key.pair.not.generated.alias.alias.already.exists=キー・ペアは生成されませんでした。別名<{0}>はすでに存在します
|
||||
size.bit.alg=%1$dビット%2$s
|
||||
Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for={0}キー・ペアおよび自己署名証明書({1})を{2}日の有効性で生成しています\n\t対象: {3}
|
||||
Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for={0}キー・ペアと<{2}>によって発行された証明書({1})を{3}日間の有効性で生成しています\n\t対象: {4}
|
||||
size.bit.alg=%1$d-ビット %2$s
|
||||
Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for={2}日間有効な{0}のキー・ペアと自己署名型証明書({1})を生成しています\n\tディレクトリ名: {3}
|
||||
Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for={3}日間有効な{0}キー・ペアと<{2}>によって発行される証明書({1})を生成しています\n\tディレクトリ名: {4}
|
||||
Enter.key.password.for.alias.=<{0}>のキー・パスワードを入力してください
|
||||
.RETURN.if.same.as.keystore.password.=\t(キーストアのパスワードと同じ場合はRETURNを押してください): \u0020
|
||||
Key.password.is.too.short.must.be.at.least.6.characters=キーのパスワードが短すぎます - 6文字以上を指定してください
|
||||
@@ -227,18 +227,18 @@ Enter.new.alias.name.RETURN.to.cancel.import.for.this.entry.=新しい別名を
|
||||
Enter.alias.name.=別名を入力してください: \u0020
|
||||
.RETURN.if.same.as.for.otherAlias.=\t(<{0}>と同じ場合はRETURNを押してください)
|
||||
enter.dname.components=識別名を入力します。サブコンポーネントを空のままにする場合はドット(.)を1つ入力し、中カッコ内のデフォルト値を使用する場合は[ENTER]を押します。
|
||||
What.is.your.first.and.last.name.=姓名は何ですか。
|
||||
What.is.the.name.of.your.organizational.unit.=組織単位名は何ですか。
|
||||
What.is.the.name.of.your.organization.=組織名は何ですか。
|
||||
What.is.the.name.of.your.City.or.Locality.=都市名または地域名は何ですか。
|
||||
What.is.the.name.of.your.State.or.Province.=都道府県名または州名は何ですか。
|
||||
What.is.the.two.letter.country.code.for.this.unit.=この単位に該当する2文字の国コードは何ですか。
|
||||
What.is.your.first.and.last.name.=姓名を入力してください。
|
||||
What.is.the.name.of.your.organizational.unit.=組織単位名を入力してください。
|
||||
What.is.the.name.of.your.organization.=組織名を入力してください。
|
||||
What.is.the.name.of.your.City.or.Locality.=都市名または地域名を入力してください。
|
||||
What.is.the.name.of.your.State.or.Province.=都道府県名を入力してください。
|
||||
What.is.the.two.letter.country.code.for.this.unit.=この単位に該当する2文字の国コードを入力してください。
|
||||
no.field.in.dname=少なくとも1つのフィールドを指定する必要があります。再度入力してください。
|
||||
Is.name.correct.={0}でよろしいですか。
|
||||
no=いいえ
|
||||
yes=はい
|
||||
y=y
|
||||
.defaultValue.=\u0020 [{0}]: \u0020
|
||||
.defaultValue.=\ [{0}]: \u0020
|
||||
Alias.alias.has.no.key=別名<{0}>にはキーがありません
|
||||
Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=別名<{0}>が参照しているエントリ・タイプは秘密キー・エントリではありません。-keycloneコマンドは秘密キー・エントリのクローン作成のみをサポートします
|
||||
|
||||
@@ -292,7 +292,7 @@ the.certificate=証明書
|
||||
the.crl=CRL
|
||||
the.tsa.certificate=TSA証明書
|
||||
the.input=入力
|
||||
reply=応答
|
||||
reply=返信
|
||||
one.in.many=%1$s #%2$d / %3$d
|
||||
one.in.many1=%1$s #%2$d
|
||||
one.in.many2=署名者の%1$s #%2$d
|
||||
@@ -302,7 +302,7 @@ alias.in.keystore=発行者<%s>
|
||||
with.weak=%s (弱)
|
||||
with.disabled=%s (無効)
|
||||
key.bit=%sキー
|
||||
key.bit.weak=%sキー(弱い)
|
||||
key.bit.weak=%sキー(弱)
|
||||
key.bit.disabled=%sキー(無効)
|
||||
.PATTERN.printX509Cert.with.weak=所有者: {0}\n発行者: {1}\nシリアル番号: {2}\n有効期間の開始日: {3}終了日: {4}\n証明書のフィンガプリント:\n\t SHA1: {5}\n\t SHA256: {6}\n署名アルゴリズム名: {7}\nサブジェクト公開キー・アルゴリズム: {8}\nバージョン: {9}
|
||||
PKCS.10.with.weak=PKCS #10証明書リクエスト(バージョン1.0)\nサブジェクト: %1$s\nフォーマット: %2$s\n公開キー: %3$s\n署名アルゴリズム: %4$s\n
|
||||
@@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$sは%2$s署名アルゴリズムを使用して
|
||||
Unable.to.parse.denyAfter.string.in.exception.message=例外メッセージのdenyAfter日付文字列を解析できません
|
||||
whose.sigalg.weak=%1$sは%2$s署名アルゴリズムを使用しており、これはセキュリティ・リスクとみなされます。
|
||||
whose.key.disabled=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされ、無効化されています。
|
||||
whose.key.weak=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされます。今後の更新では無効になります。
|
||||
whose.key.weak=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされます。これは将来の更新で無効化されます。
|
||||
jks.storetype.warning=%1$sキーストアは独自の形式を使用しています。"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12"を使用する業界標準の形式であるPKCS12に移行することをお薦めします。
|
||||
migrate.keystore.warning="%1$s"が%4$sに移行されました。%2$sキーストアは"%3$s"としてバックアップされます。
|
||||
backup.keystore.warning=元のキーストア"%1$s"は"%3$s"としてバックアップされます...
|
||||
|
||||
@@ -27,13 +27,13 @@ NEWLINE=\n
|
||||
STAR=*******************************************
|
||||
STARNN=*******************************************\n\n
|
||||
# keytool: Help part
|
||||
.OPTION.=\u0020[OPTION]...
|
||||
Options.=选项:
|
||||
.OPTION.=\ [OPTION]...
|
||||
Options.=选项:
|
||||
option.1.set.twice=多次指定了 %s 选项。除最后一个之外, 其余的将全部忽略。
|
||||
multiple.commands.1.2=只允许一个命令: 同时指定了 %1$s 和 %2$s。
|
||||
Use.keytool.help.for.all.available.commands=使用 "keytool -?, -h, or --help" 可输出此帮助消息
|
||||
Key.and.Certificate.Management.Tool=密钥和证书管理工具
|
||||
Commands.=命令:
|
||||
Commands.=命令:
|
||||
Use.keytool.command.name.help.for.usage.of.command.name=使用 "keytool -command_name --help" 可获取 command_name 的用法。\n使用 -conf <url> 选项可指定预配置的选项文件。
|
||||
# keytool: help: commands
|
||||
Generates.a.certificate.request=生成证书请求
|
||||
@@ -114,7 +114,7 @@ verbose.output=详细输出
|
||||
validity.number.of.days=有效天数
|
||||
Serial.ID.of.cert.to.revoke=要撤销的证书的序列 ID
|
||||
# keytool: Running part
|
||||
keytool.error.=keytool 错误:\u0020
|
||||
keytool.error.=keytool 错误:\u0020
|
||||
Illegal.option.=非法选项: \u0020
|
||||
Illegal.value.=非法值:\u0020
|
||||
Unknown.password.type.=未知口令类型:\u0020
|
||||
@@ -170,7 +170,7 @@ Certificate.reply.was.installed.in.keystore=证书回复已安装在密钥库中
|
||||
Certificate.reply.was.not.installed.in.keystore=证书回复未安装在密钥库中
|
||||
Certificate.was.added.to.keystore=证书已添加到密钥库中
|
||||
Certificate.was.not.added.to.keystore=证书未添加到密钥库中
|
||||
.Storing.ksfname.=[正在存储{0}]
|
||||
.Storing.ksfname.=[正在存储 {0}]
|
||||
alias.has.no.public.key.certificate.={0}没有公共密钥 (证书)
|
||||
Cannot.derive.signature.algorithm=无法派生签名算法
|
||||
Alias.alias.does.not.exist=别名 <{0}> 不存在
|
||||
@@ -179,8 +179,8 @@ groupname.keysize.coexist=无法同时指定 -groupname 和 -keysize
|
||||
deprecate.keysize.for.ec=为生成 EC 密钥指定 -keysize 已过时,请改为使用 "-groupname %s"。
|
||||
Key.pair.not.generated.alias.alias.already.exists=未生成密钥对, 别名 <{0}> 已经存在
|
||||
size.bit.alg=%1$d 位 %2$s
|
||||
Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=正在为 {3} 生成有效期为 {2} 天的 {0} 密钥对和自签名证书 ({1})\n
|
||||
Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=生成 {0} 密钥对和 <{2}> 颁发的证书 ({1}),有效期为 {3} 天 \n\t 对于:{4}
|
||||
Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=正在为以下对象生成 {0} 密钥对和自签名证书 ({1})(有效期为 {2} 天):\n\t{3}
|
||||
Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=正在为以下对象生成 {0} 密钥对和由 <{2}> 颁发的证书 ({1})(有效期为 {3} 天):\n\t{4}
|
||||
Enter.key.password.for.alias.=输入 <{0}> 的密钥口令
|
||||
.RETURN.if.same.as.keystore.password.=\t(如果和密钥库口令相同, 按回车): \u0020
|
||||
Key.password.is.too.short.must.be.at.least.6.characters=密钥口令太短 - 至少必须为 6 个字符
|
||||
@@ -216,7 +216,7 @@ Do.you.still.want.to.add.it.no.=是否仍要添加? [否]: \u0020
|
||||
Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias.=在别名 <{0}> 之下, 证书已经存在于系统范围的 CA 密钥库中
|
||||
Do.you.still.want.to.add.it.to.your.own.keystore.no.=是否仍要将它添加到自己的密钥库? [否]: \u0020
|
||||
Trust.this.certificate.no.=是否信任此证书? [否]: \u0020
|
||||
New.prompt.=新{0}:\u0020
|
||||
New.prompt.=新 {0}:\u0020
|
||||
Passwords.must.differ=口令不能相同
|
||||
Re.enter.new.prompt.=重新输入新{0}:\u0020
|
||||
Re.enter.password.=再次输入口令:\u0020
|
||||
@@ -238,14 +238,14 @@ Is.name.correct.={0}是否正确?
|
||||
no=否
|
||||
yes=是
|
||||
y=y
|
||||
.defaultValue.=\u0020 [{0}]: \u0020
|
||||
.defaultValue.=\ [{0}]: \u0020
|
||||
Alias.alias.has.no.key=别名 <{0}> 没有密钥
|
||||
Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=别名 <{0}> 引用了不属于私有密钥条目的条目类型。-keyclone 命令仅支持对私有密钥条目的克隆
|
||||
|
||||
.WARNING.WARNING.WARNING.=***************** WARNING WARNING WARNING *****************
|
||||
Signer.d.=签名者 #%d:
|
||||
Signer.d.=签名者 #%d:
|
||||
Certificate.d.=证书 #%d:
|
||||
Timestamp.=时间戳:
|
||||
Timestamp.=时间戳:
|
||||
Certificate.owner.=证书所有者:\u0020
|
||||
Not.a.signed.jar.file=不是已签名的 jar 文件
|
||||
No.certificate.from.the.SSL.server=没有来自 SSL 服务器的证书
|
||||
@@ -256,7 +256,7 @@ No.certificate.from.the.SSL.server=没有来自 SSL 服务器的证书
|
||||
Certificate.reply.does.not.contain.public.key.for.alias.=证书回复中不包含 <{0}> 的公共密钥
|
||||
Incomplete.certificate.chain.in.reply=回复中的证书链不完整
|
||||
Top.level.certificate.in.reply.=回复中的顶级证书:\n
|
||||
.is.not.trusted.=... 是不可信的。
|
||||
.is.not.trusted.=... 是不可信的。\u0020
|
||||
Install.reply.anyway.no.=是否仍要安装回复? [否]: \u0020
|
||||
Public.keys.in.reply.and.keystore.don.t.match=回复中的公共密钥与密钥库不匹配
|
||||
Certificate.reply.and.certificate.in.keystore.are.identical=证书回复与密钥库中的证书是相同的
|
||||
@@ -269,14 +269,14 @@ Please.provide.keysize.for.secret.key.generation=请提供 -keysize 以生成密
|
||||
warning.not.verified.make.sure.keystore.is.correct=警告: 未验证。请确保密钥库是正确的。
|
||||
warning.not.verified.make.sure.keystore.is.correct.or.specify.trustcacerts=警告:未验证。请确保密钥库是正确的,或者指定 -trustcacerts。
|
||||
|
||||
Extensions.=扩展:\u0020
|
||||
Extensions.=扩展:\u0020
|
||||
.Empty.value.=(空值)
|
||||
Extension.Request.=扩展请求:
|
||||
Unknown.keyUsage.type.=未知 keyUsage 类型:\u0020
|
||||
Unknown.extendedkeyUsage.type.=未知 extendedkeyUsage 类型:\u0020
|
||||
Unknown.AccessDescription.type.=未知 AccessDescription 类型:\u0020
|
||||
Unrecognized.GeneralName.type.=无法识别的 GeneralName 类型:\u0020
|
||||
This.extension.cannot.be.marked.as.critical.=无法将此扩展标记为“严重”。
|
||||
This.extension.cannot.be.marked.as.critical.=无法将此扩展标记为“严重”。\u0020
|
||||
Odd.number.of.hex.digits.found.=找到奇数个十六进制数字:\u0020
|
||||
Unknown.extension.type.=未知扩展类型:\u0020
|
||||
command.{0}.is.ambiguous.=命令{0}不明确:
|
||||
@@ -299,11 +299,11 @@ one.in.many2=签名者 #%2$d 的 %1$s
|
||||
one.in.many3=签名者 #%3$d 的 %1$s #%2$d
|
||||
alias.in.cacerts=cacerts 中的发布者 <%s>
|
||||
alias.in.keystore=发布者 <%s>
|
||||
with.weak=%s (弱)
|
||||
with.weak=%s(弱)
|
||||
with.disabled=%s(禁用)
|
||||
key.bit=%s 密钥
|
||||
key.bit.weak=%s 密钥(弱)
|
||||
key.bit.disabled=%s 密钥(已禁用)
|
||||
key.bit.disabled=%s 密钥(禁用)
|
||||
.PATTERN.printX509Cert.with.weak=所有者: {0}\n发布者: {1}\n序列号: {2}\n生效时间: {3}, 失效时间: {4}\n证书指纹:\n\t SHA1: {5}\n\t SHA256: {6}\n签名算法名称: {7}\n主体公共密钥算法: {8}\n版本: {9}
|
||||
PKCS.10.with.weak=PKCS #10 证书请求 (版本 1.0)\n主体: %1$s\n格式: %2$s\n公共密钥: %3$s\n签名算法: %4$s\n
|
||||
verified.by.s.in.s.weak=由 %2$s 中的 %1$s 以 %3$s 验证
|
||||
@@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$s 使用的 %2$s 签名算法被视为存在安
|
||||
Unable.to.parse.denyAfter.string.in.exception.message=无法解析异常错误消息中的 denyAfter 日期字符串
|
||||
whose.sigalg.weak=%1$s 使用的 %2$s 签名算法存在安全风险。
|
||||
whose.key.disabled=%1$s 使用的 %2$s 被视为存在安全风险而且被禁用。
|
||||
whose.key.weak=%1$s 使用的 %2$s 被视为存在安全风险。在将来的更新中将禁用它。
|
||||
whose.key.weak=%1$s 使用的 %2$s 被视为存在安全风险。它将在未来的更新中被禁用。
|
||||
jks.storetype.warning=%1$s 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。
|
||||
migrate.keystore.warning=已将 "%1$s" 迁移到 %4$s。将 %2$s 密钥库作为 "%3$s" 进行了备份。
|
||||
backup.keystore.warning=已将原始密钥库 "%1$s" 备份为 "%3$s"...
|
||||
|
||||
@@ -343,7 +343,7 @@ public class Pem {
|
||||
* @return PEM in a string
|
||||
*/
|
||||
public static String pemEncoded(PEMRecord pem) {
|
||||
String p = pem.pem().replaceAll("(.{64})", "$1\r\n");
|
||||
String p = pem.content().replaceAll("(.{64})", "$1\r\n");
|
||||
return pemEncoded(pem.type(), p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,22 +24,22 @@
|
||||
#
|
||||
|
||||
# NT principals
|
||||
invalid.null.input.value=无效的空输入: {0}
|
||||
NTDomainPrincipal.name=NTDomainPrincipal: {0}
|
||||
NTNumericCredential.name=NTNumericCredential: {0}
|
||||
invalid.null.input.value=无效的空输入:{0}
|
||||
NTDomainPrincipal.name=NTDomainPrincipal:{0}
|
||||
NTNumericCredential.name=NTNumericCredential:{0}
|
||||
Invalid.NTSid.value=无效的 NTSid 值
|
||||
NTSid.name=NTSid: {0}
|
||||
NTSidDomainPrincipal.name=NTSidDomainPrincipal: {0}
|
||||
NTSidGroupPrincipal.name=NTSidGroupPrincipal: {0}
|
||||
NTSidPrimaryGroupPrincipal.name=NTSidPrimaryGroupPrincipal: {0}
|
||||
NTSidUserPrincipal.name=NTSidUserPrincipal: {0}
|
||||
NTUserPrincipal.name=NTUserPrincipal: {0}
|
||||
NTSid.name=NTSid:{0}
|
||||
NTSidDomainPrincipal.name=NTSidDomainPrincipal:{0}
|
||||
NTSidGroupPrincipal.name=NTSidGroupPrincipal:{0}
|
||||
NTSidPrimaryGroupPrincipal.name=NTSidPrimaryGroupPrincipal:{0}
|
||||
NTSidUserPrincipal.name=NTSidUserPrincipal:{0}
|
||||
NTUserPrincipal.name=NTUserPrincipal:{0}
|
||||
|
||||
# UnixPrincipals
|
||||
UnixNumericGroupPrincipal.Primary.Group.name=UnixNumericGroupPrincipal [主组]: {0}
|
||||
UnixNumericGroupPrincipal.Primary.Group.name=UnixNumericGroupPrincipal [主组]:{0}
|
||||
UnixNumericGroupPrincipal.Supplementary.Group.name=UnixNumericGroupPrincipal [补充组]: {0}
|
||||
UnixNumericUserPrincipal.name=UnixNumericUserPrincipal: {0}
|
||||
UnixPrincipal.name=UnixPrincipal: {0}
|
||||
UnixNumericUserPrincipal.name=UnixNumericUserPrincipal:{0}
|
||||
UnixPrincipal.name=UnixPrincipal:{0}
|
||||
|
||||
# com.sun.security.auth.login.ConfigFile
|
||||
Unable.to.properly.expand.config=无法正确扩展{0}
|
||||
@@ -53,8 +53,8 @@ Configuration.Error.Line.line.expected.expect.=配置错误: \n\t行 {0}: 应为
|
||||
Configuration.Error.Line.line.system.property.value.expanded.to.empty.value=配置错误: \n\t行 {0}: 系统属性 [{1}] 扩展到空值
|
||||
|
||||
# com.sun.security.auth.module.JndiLoginModule
|
||||
username.=用户名:\u0020
|
||||
password.=口令:\u0020
|
||||
username.=用户名:\u0020
|
||||
password.=密码:\u0020
|
||||
|
||||
# com.sun.security.auth.module.KeyStoreLoginModule
|
||||
Please.enter.keystore.information=请输入密钥库信息
|
||||
@@ -63,5 +63,5 @@ Keystore.password.=密钥库口令:\u0020
|
||||
Private.key.password.optional.=私有密钥口令 (可选):\u0020
|
||||
|
||||
# com.sun.security.auth.module.Krb5LoginModule
|
||||
Kerberos.username.defUsername.=Kerberos 用户名 [{0}]:\u0020
|
||||
Kerberos.password.for.username.={0}的 Kerberos 口令:\u0020
|
||||
Kerberos.username.defUsername.=Kerberos 用户名 [{0}]:\u0020
|
||||
Kerberos.password.for.username.={0} 的 Kerberos 密码:\u0020
|
||||
|
||||
@@ -66,7 +66,7 @@ Login.Failure.all.modules.ignored=ログイン失敗: すべてのモジュー
|
||||
# sun.security.provider.PolicyParser
|
||||
duplicate.keystore.domain.name=重複するキーストア・ドメイン名: {0}
|
||||
duplicate.keystore.name=重複するキーストア名: {0}
|
||||
number.=数\u0020
|
||||
number.=数値\u0020
|
||||
expected.expect.read.end.of.file.=[{0}]ではなく[ファイルの終わり]が読み込まれました
|
||||
expected.read.end.of.file.=[;]ではなく[ファイルの終わり]が読み込まれました
|
||||
line.number.msg=行{0}: {1}
|
||||
|
||||
@@ -43,17 +43,17 @@ provided.null.OID.map=提供的 OID 映射为空值
|
||||
NEWLINE=\n
|
||||
invalid.null.action.provided=提供了无效的空操作
|
||||
invalid.null.Class.provided=提供了无效的空类
|
||||
Subject.=主体: \n
|
||||
.Principal.=\t主用户:\u0020
|
||||
.Public.Credential.=\t公共身份证明:\u0020
|
||||
.Private.Credential.=\t专用身份证明:\u0020
|
||||
Subject.=主体:\n
|
||||
.Principal.=\t主用户:\u0020
|
||||
.Public.Credential.=\t公共身份证明:\u0020
|
||||
.Private.Credential.=\t专用身份证明:\u0020
|
||||
.Private.Credential.inaccessible.=\t无法访问专用身份证明\n
|
||||
Subject.is.read.only=主体为只读
|
||||
attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set=正在尝试将一个非 java.security.Principal 实例的对象添加到主体的主用户集中
|
||||
attempting.to.add.an.object.which.is.not.an.instance.of.class=正在尝试添加一个非{0}实例的对象
|
||||
|
||||
# javax.security.auth.login.AppConfigurationEntry
|
||||
LoginModuleControlFlag.=LoginModuleControlFlag:\u0020
|
||||
LoginModuleControlFlag.=LoginModuleControlFlag:\u0020
|
||||
|
||||
# javax.security.auth.login.LoginContext
|
||||
Invalid.null.input.name=无效空输入: 名称
|
||||
@@ -69,8 +69,8 @@ duplicate.keystore.name=密钥库名称重复: {0}
|
||||
number.=编号\u0020
|
||||
expected.expect.read.end.of.file.=应为 [{0}], 读取的是 [文件结尾]
|
||||
expected.read.end.of.file.=应为 [;], 读取的是 [文件结尾]
|
||||
line.number.msg=列{0}: {1}
|
||||
line.number.msg=第 {0} 行:{1}
|
||||
line.number.expected.expect.found.actual.=行号 {0}: 应为 [{1}], 找到 [{2}]
|
||||
|
||||
# sun.security.pkcs11.SunPKCS11
|
||||
PKCS11.Token.providerName.Password.=PKCS11 标记 [{0}] 口令:\u0020
|
||||
PKCS11.Token.providerName.Password.=PKCS11 标记 [{0}] 密码:\u0020
|
||||
|
||||
21
src/java.base/share/data/cacerts/sectigocodesignroote46
Normal file
21
src/java.base/share/data/cacerts/sectigocodesignroote46
Normal file
@@ -0,0 +1,21 @@
|
||||
Owner: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
|
||||
Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
|
||||
Serial number: 50249ba2ef8ea6bf6c2c1f1a6385d4c3
|
||||
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
|
||||
Signature algorithm name: SHA384withECDSA
|
||||
Subject Public Key Algorithm: 384-bit EC (secp384r1) key
|
||||
Version: 3
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICKDCCAa+gAwIBAgIQUCSbou+Opr9sLB8aY4XUwzAKBggqhkjOPQQDAzBWMQsw
|
||||
CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT
|
||||
ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw
|
||||
MDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj
|
||||
dGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p
|
||||
bmcgUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQIMoEDH487om+BR4zl
|
||||
e7m6wWmyW0nAKLkUWG8kM85Qm3PZO8FoOZx6Yc5c0iJHRKuAhanllayqrmZYhlan
|
||||
uIODzLTRDqlR+EtnOX+MubY5aDSPGUq6jiHrQrisVp0J3AejQjBAMB0GA1UdDgQW
|
||||
BBTPfSygkHqYHd22XoXC4NoVcdLlXjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/
|
||||
BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjACd++zAerlV83j8HflRwwwlLmgchbs
|
||||
aGX/4g44dv/oG8KfzCVTRg6sZHMobtK0IqYCMGk5W6+oBFyZMtOebrSwXs8lGjll
|
||||
/zHz43Zy8DMXO+iiqzSEwWGneZ6KupkGGqfVKw==
|
||||
-----END CERTIFICATE-----
|
||||
39
src/java.base/share/data/cacerts/sectigocodesignrootr46
Normal file
39
src/java.base/share/data/cacerts/sectigocodesignrootr46
Normal file
@@ -0,0 +1,39 @@
|
||||
Owner: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
|
||||
Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
|
||||
Serial number: 4b2c3b01018bad2abc8c7b5b3eed9057
|
||||
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
|
||||
Signature algorithm name: SHA384withRSA
|
||||
Subject Public Key Algorithm: 4096-bit RSA key
|
||||
Version: 3
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFeDCCA2CgAwIBAgIQSyw7AQGLrSq8jHtbPu2QVzANBgkqhkiG9w0BAQwFADBW
|
||||
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD
|
||||
EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy
|
||||
MDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP
|
||||
U2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNp
|
||||
Z25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCN
|
||||
55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+shJHjUoq14pbe0IdjJImK
|
||||
/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCDJ9qaDStQ6Utbs7hkNqR+
|
||||
Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7P2bSlDFp+m2zNKzBenjc
|
||||
klDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extmeme/G3h+pDHazJyCh1rr9
|
||||
gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUzT2MuuC3hv2WnBGsY2HH6
|
||||
zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6qRT5uWl+PoVvLnTCGMOgD
|
||||
s0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mczmrYI4IAFSEDu9oJkRqj1
|
||||
c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEcQNYWFyn8XJwYK+pF9e+9
|
||||
1WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2TOglmmVhcKaO5DKYwODzQ
|
||||
RjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/AZwQsRb8zG4Y3G9i/qZQ
|
||||
p7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QIDAQABo0IwQDAdBgNVHQ4E
|
||||
FgQUMuuSmv81lkgvKEBCcCA2kVwXheYwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB
|
||||
/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAHZlwuPXIkrXHYle/2lexhQCTXOm
|
||||
zc0oyrA36r+nySGqql/av/aDbNCA0QpcAKTL88w5D55BcYjVPOiKe4wXI/fKNHSR
|
||||
bAauUD8AWbImPDwXg1cDPi3RGj3UzwdUskMLUnKoiPXEF/Jv0Vil0WjkPZgIGO42
|
||||
9EhImvpUcPCI1HAWMEJJ0Nk/dUtFcdiuorthDoiFUFe5uhErNikfjyBynlyeidGC
|
||||
2kWNapnahHFrM6UQu3nwl/Z0gaA/V8eGjDCMDjiVrgHGHqvcqB9vL9f/dh6uF3Nt
|
||||
5bl1s2EGqJUzwk5vsjfylb6FVBK5yL1iQnb3Kvz1NzEDJlf+0ebb8BYCcoOMCLOE
|
||||
rKnkB/ihiMQTWlBHVEKm7dBBNCyYsT6iNKEMXb2s9395p79tDFYyhRtLl7jhrOSk
|
||||
PHHxo+FOY9b0Rrr1CwjhYzztolkvCtQsayOinqFN7tESzRgzUO1Bbst/PUFgC2ML
|
||||
ePV170MVtzYLEK/cXBipmNk22R3YhLMGioLjexskp0LO7g8+VlwyfexL3lYrOzu6
|
||||
+XpY0FG2bNb2WKJSJHpEhqEcYD9J0/z6+YQcBcI0v+Lm8RkqmS9WVzWctfUHw0Yv
|
||||
3jg9GQ37o/HfE57nqXJYMa+96trX1m13MzOO9Kz9wb9Jh9JwBWd0Bqb2eEAtFgSR
|
||||
Dx/TFsS4ehcNJMmy
|
||||
-----END CERTIFICATE-----
|
||||
21
src/java.base/share/data/cacerts/sectigotlsroote46
Normal file
21
src/java.base/share/data/cacerts/sectigotlsroote46
Normal file
@@ -0,0 +1,21 @@
|
||||
Owner: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB
|
||||
Issuer: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB
|
||||
Serial number: 42f2ccda1b6937445f15fe752810b8f4
|
||||
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
|
||||
Signature algorithm name: SHA384withECDSA
|
||||
Subject Public Key Algorithm: 384-bit EC (secp384r1) key
|
||||
Version: 3
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw
|
||||
CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
|
||||
ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN
|
||||
MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG
|
||||
A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
|
||||
ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
|
||||
IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC
|
||||
WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+
|
||||
6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B
|
||||
Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa
|
||||
qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q
|
||||
4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw==
|
||||
-----END CERTIFICATE-----
|
||||
39
src/java.base/share/data/cacerts/sectigotlsrootr46
Normal file
39
src/java.base/share/data/cacerts/sectigotlsrootr46
Normal file
@@ -0,0 +1,39 @@
|
||||
Owner: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB
|
||||
Issuer: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB
|
||||
Serial number: 758dfd8bae7c0700faa925a7e1c7ad14
|
||||
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
|
||||
Signature algorithm name: SHA384withRSA
|
||||
Subject Public Key Algorithm: 4096-bit RSA key
|
||||
Version: 3
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf
|
||||
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
|
||||
Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
|
||||
HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY
|
||||
MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp
|
||||
YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
|
||||
AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa
|
||||
ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz
|
||||
SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf
|
||||
iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X
|
||||
ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3
|
||||
IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS
|
||||
VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE
|
||||
SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu
|
||||
+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt
|
||||
8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L
|
||||
HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt
|
||||
zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P
|
||||
AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
|
||||
mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ
|
||||
YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52
|
||||
gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA
|
||||
Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB
|
||||
JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX
|
||||
DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui
|
||||
TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5
|
||||
dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65
|
||||
LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp
|
||||
0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY
|
||||
QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1449,9 +1449,10 @@ These `java` options control the runtime behavior of the Java HotSpot VM.
|
||||
|
||||
`report-on-exit=`*identifier*
|
||||
: Specifies the name of the view to display when the Java Virtual Machine
|
||||
(JVM) shuts down. This option is not available if the disk option is set
|
||||
to false. For a list of available views, see `jfr help view`. By default,
|
||||
no report is generated.
|
||||
(JVM) shuts down. To specify more than one view, use the report-on-exit
|
||||
parameter repeatedly. This option is not available if the disk option
|
||||
is set to false. For a list of available views, see `jfr help view`.
|
||||
By default, no report is generated.
|
||||
|
||||
`settings=`*path*
|
||||
: Specifies the path and name of the event settings file (of type JFC).
|
||||
@@ -1514,6 +1515,15 @@ These `java` options control the runtime behavior of the Java HotSpot VM.
|
||||
|
||||
This option is similar to `-Xss`.
|
||||
|
||||
`-XX:+UseCompactObjectHeaders`
|
||||
: Enables compact object headers. By default, this option is disabled.
|
||||
Enabling this option reduces memory footprint in the Java heap by
|
||||
4 bytes per object (on average) and often improves performance.
|
||||
|
||||
The feature remains disabled by default while it continues to be evaluated.
|
||||
In a future release it is expected to be enabled by default, and
|
||||
eventually will be the only mode of operation.
|
||||
|
||||
`-XX:-UseCompressedOops`
|
||||
: Disables the use of compressed pointers. By default, this option is
|
||||
enabled, and compressed pointers are used. This will automatically limit
|
||||
@@ -3806,9 +3816,10 @@ general form:
|
||||
be loaded on top of those in the `<static_archive>`.
|
||||
- On Windows, the above path delimiter `:` should be replaced with `;`
|
||||
|
||||
(The names "static" and "dynamic" are used for historical reasons.
|
||||
The only significance is that the "static" archive is loaded first and
|
||||
the "dynamic" archive is loaded second).
|
||||
The names "static" and "dynamic" are used for historical reasons. The dynamic
|
||||
archive, while still useful, supports fewer optimizations than
|
||||
available for the static CDS archive. If the full set of CDS/AOT
|
||||
optimizations are desired, consider using the AOT cache described below.
|
||||
|
||||
The JVM can use up to two archives. To use only a single `<static_archive>`,
|
||||
you can omit the `<dynamic_archive>` portion:
|
||||
|
||||
@@ -91,14 +91,7 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
}
|
||||
|
||||
static int enhancedExceptionsInitialized = 0;
|
||||
static int enhancedExceptionsAllowed = -1;
|
||||
|
||||
#define CHECK_NULL_THROW_ERROR(X) \
|
||||
if (X == NULL) { \
|
||||
JNU_ThrowByName(env, "java/lang/InternalError", \
|
||||
"can't initialize enhanced exceptions"); \
|
||||
return -1; \
|
||||
}
|
||||
static int enhancedExceptionsAllowed = 0;
|
||||
|
||||
int getEnhancedExceptionsAllowed(JNIEnv *env) {
|
||||
jclass cls;
|
||||
@@ -108,9 +101,9 @@ int getEnhancedExceptionsAllowed(JNIEnv *env) {
|
||||
return enhancedExceptionsAllowed;
|
||||
}
|
||||
cls = (*env)->FindClass(env, "jdk/internal/util/Exceptions");
|
||||
CHECK_NULL_THROW_ERROR(cls);
|
||||
CHECK_NULL_RETURN(cls, ENH_INIT_ERROR);
|
||||
fid = (*env)->GetStaticFieldID(env, cls, "enhancedNonSocketExceptionText", "Z");
|
||||
CHECK_NULL_THROW_ERROR(fid);
|
||||
CHECK_NULL_RETURN(fid, ENH_INIT_ERROR);
|
||||
enhancedExceptionsAllowed = (*env)->GetStaticBooleanField(env, cls, fid);
|
||||
enhancedExceptionsInitialized = 1;
|
||||
return enhancedExceptionsAllowed;
|
||||
|
||||
@@ -183,6 +183,11 @@ int lookupCharacteristicsToAddressFamily(int characteristics);
|
||||
|
||||
int addressesInSystemOrder(int characteristics);
|
||||
|
||||
/* return codes */
|
||||
#define ENH_INIT_ERROR -1 /* initialization error: check exceptions */
|
||||
#define ENH_DISABLED 0 /* enhanced exceptions disabled */
|
||||
#define ENH_ENABLED 1 /* enhanced exceptions enabled */
|
||||
|
||||
int getEnhancedExceptionsAllowed(JNIEnv *env);
|
||||
|
||||
#endif /* NET_UTILS_H */
|
||||
|
||||
@@ -188,8 +188,11 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
|
||||
if (error_string == NULL)
|
||||
error_string = "unknown error";
|
||||
int enhancedExceptions = getEnhancedExceptionsAllowed(env);
|
||||
if (enhancedExceptions == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enhancedExceptions) {
|
||||
if (enhancedExceptions == ENH_ENABLED) {
|
||||
size = strlen(hostname);
|
||||
} else {
|
||||
size = 0;
|
||||
@@ -200,7 +203,7 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
|
||||
if (buf) {
|
||||
jstring s;
|
||||
int n;
|
||||
if (enhancedExceptions) {
|
||||
if (enhancedExceptions == ENH_ENABLED) {
|
||||
n = snprintf(buf, size, "%s: %s", hostname, error_string);
|
||||
} else {
|
||||
n = snprintf(buf, size, " %s", error_string);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user